1

I don't fully understand how PHP allocates, so I don't know if I have made an error, or if this is a bug.

usort() here is intermittently zeroing out the head or tail of the array.

class foo
{
  public $idx;
  public $data;
}

function compare_foos ($a, $b)
{
  if ($a->data == $b->data)
    return 0;
  elseif ($a->data < $b->data)
    return -1;
  else
    return 1;
}

$mylist = Array ();

for ($i=0; $i < 10; ++$i)
{
  $mylist[$i] = new foo ();
  $mylist[$i]->idx = $i;
  $mylist[$i]->data = rand() % 20;
}

print_r ($mylist);
usort ($mylist, compare_foos);
echo "<HR>";
print_r ($mylist);
  • Live example: http://codepad.org/fOdA0hca . What do you mean by *zeroing out head or tail*? The sort appears to work as intended. – Felix Kling May 28 '11 at 13:14
  • 1
    This code works correct. `usort ($mylist, compare_foos);` - quote `compare_foos`, it's just string, not constant. – OZ_ May 28 '11 at 13:16
  • It's probably a bug in my php install then. Sometimes it replaces first or last element with a null (no data). I don't know the specific PHP term for it. It works everytime if I code the sort func myself. I just wondered if I was allocating the array properly, that's all. Since you say I am, it's got to be a bug in the local system. –  May 28 '11 at 13:24

1 Answers1

1

Callbacks, like the one used by usort, can be specified in 3 different ways:

  • a string containing the name of the function:

    usort($mylist, 'compare_foos');
    
  • an actual function:

    usort($mylist, create_function(/*...*/));
    // php >= 5.3 only:
    usort($mylist, function ($a, $b) {
       /* ... */
    });
    
  • an array to access object methods:

    usort($mylist, array($myobject, 'mymethod'));
    

Using a callback the way you did is not valid and php returns an error:

PHP Notice:  Use of undefined constant compare_foos - assumed 'compare_foos' in /home/lepidosteus/test.php on line 28

To see it, remember to code with every error enabled on your development machine (but hide them on the production server), using error_reporting():

error_reporting(E_ALL); // display all errors including notices
error_reporting(0); // hide all errors

By the way if you want to use an object as a simple store, you don't need to create a dedicated class you can use stdClass():

$mylist[$i] = new stdClass();
$mylist[$i]->idx = $i;
$mylist[$i]->data = rand() % 20;

Also, you can use var_dump() instead of print_r when you debug to get detailed information about the type of each variable, can help you quickly find out if something is wrong.

Community
  • 1
  • 1
Lepidosteus
  • 10,790
  • 4
  • 34
  • 49
  • Thanks, this is helpful and teaches me things I did not know. I can see from var_dump() that usort is somehow replacing an element of the array with an uninitialised one. [10]=> object(foo)#10 (2) { ["idx"]=> NULL ["data"]=> NULL }. I'll put it down to a php bug, or a bug in my php system, and work around it. Maybe getting off topic here now, but is there a test suite to verify the functionality of a php system? –  May 28 '11 at 13:42
  • If I copy the code from your question inside a file (fixing the callback issue and adding php opening tag) and execute it a dozen times, I can't ever reproduce this behavior. Have you tried that yourself ? (ONLY the code in the question, not a single line more, even if you think it won't affect it). It feels like your issue comes from elsewhere. – Lepidosteus May 28 '11 at 13:45
  • Yea the code should work. This is why I thought to seek the advice of PHP specialists. It's fine on a different PHP server. Just some local weirdness with the install I guess. Again thanks for your assistance in explaining various PHP things. –  May 28 '11 at 18:26