Home:ALL Converter>Objects comparison in PHP

Objects comparison in PHP

Ask Time:2014-03-20T17:24:30         Author:Alma Do

Json Formatter

SO,

The problem

It's not well-known, but PHP allows to compare objects - and not just on equality == - but on < and > too. But - how it works? So if I want to create comparable objects - what restrictions/rules they should follow?

Most useful case is with DateTime() objects - they hold certain timestamp and they could be compared (and this has logical sense). On lxr there's some explanation for DateTime . But what about common case?

I have:

class C
{
   protected $holder;
   protected $mirror;
   public function __construct($h = null)
   {
      $this->holder=$h;
      $this->mirror=-1*$h;
   }
}


$one = new C(1);
$two = new C(2);
//false, false, true: used $holder
var_dump($one>$two, $one==$two, $one<$two);

-if I'll change properties declaration order, it will use $mirror:

class C
{
   //only order changed:
   protected $mirror;
   protected $holder;
   public function __construct($h = null)
   {
      $this->holder=$h;
      $this->mirror=-1*$h;
   }
}

$one = new C(1);
$two = new C(2);
//true, false, false: used $mirror
var_dump($one>$two, $one==$two, $one<$two);

So it seems one of the 'rules' is that it will use first declared property. But why is it using protected property at all is not clear to me too.

Now, more complex sample:

class Test
{
  protected $a;
  protected $b;

  function __construct($a, $b)
  {
    $this->a = $a;
    $this->b = $b;
  }
}

$x = new Test(1, 2);
$y = new Test(1, 3);

// true, false, false
var_dump($x < $y, $x == $y, $x > $y);

$x = new Test(3, 1);
$y = new Test(2, 1);

// false, false, true
var_dump($x < $y, $x == $y, $x > $y);

-so it will use first not-equal property for comparison. But code snippets above are only some cases. I want to know exactly how it's happening and why. Thus,

Question

Is: how it works? I mean, more detailed:

  • Can I rely on fact, that PHP will use first not-equal property for comparison?
  • What will be done if count of properties isn't equal? (i.e. some property was dynamically added to instance during code execution)
  • Can I treat protected/private properties as to be counted for such comparison always?

e.t.c. - so if there are some additional conditions/restrictions/rules that will affect result - please, post. Documentation states only for ==/=== comparison. Also, comparison of instances of different classes is out of the issue since it'll return false (obviously).

Author:Alma Do,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/22528491/objects-comparison-in-php
user703016 :

PHP compares sequentially (in the order of declaration) the object properties and stops at the first inequal property found. This behavior is not documented, so there's not much to be said about it, sadly, other than looking at the source of PHP.\n\nNot documented is usually a synonym of \"don't rely on it\".",
2014-03-20T09:30:08
VolkerK :

Each class in php has an associated structure (in the c code) of handler functions, it looks like \n\nstruct _zend_object_handlers {\n /* general object functions */\n zend_object_add_ref_t add_ref;\n zend_object_del_ref_t del_ref;\n[...]\n zend_object_compare_t compare_objects;\n[...]\n};\n\n\ncompare_objects points to a function that \"takes two objects\" and returns -1,0,1 according to whatever this comparator defines as the order (just like strcmp() does for strings).\nThis function is used only when both operands (objects) point to the same comparision function - but let's just stick with this case.\nThat's where e.g. DateTime \"adds\" its feature to compare two DateTime instances, it just defines another, DateTime-specific compare_objects function and puts it in the structure describing its class.\n\nstatic void date_register_classes(TSRMLS_D)\n{\n[...]\n\n INIT_CLASS_ENTRY(ce_date, \"DateTime\", date_funcs_date);\n ce_date.create_object = date_object_new_date;\n[...]\n date_object_handlers_date.compare_objects = date_object_compare_date;\n\n\nSo if you want to know (exactly) how two DateTime instances are compared, take a look at date_object_compare_date.\n\nThe comparision described in the manual (at least for the case cmp(o1,o2)==0) seems to be implemented in zend_std_compare_objects. And it's used by both StdClass and a simple user defined class like e.g.\n\n<?php\nclass Foo { }\n$a = new StdClass;\n$b = new Foo;\n\n$a > $b;\n\n\nBut other classes (in php extensions) do set other functions. DateTime, ArrayObject, PDOStatement, even Closures use different functions.\nBut I haven't found a way to define a comparision function/method in script code (but haven't looked too hard/long) ",
2014-03-20T10:17:42
yy