C++/Python guy here.
I need to compare two php-arrays containig user-defined classes.
class Point
{
var $x;
var $y;
function _construct($x_, $y_)
{
$this -> x = $x_;
$this -> y = $y_;
}
}
$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));
if (array_diff($mas1,$mas2) == array())
{
echo "they're equal
";
}
i got "Catchable fatal error: Object of class Point could not be converted to string". When i tried to use simple
if ($mas1 == $mas2)
i got False.
Questions: 1) is there way to overload comparison operator for my class Point 2) how to compare two arrays containing user-defined classes correctly?
Thank you.
I use php 5.2.11
I think you need to read this.
Unfortunately, PHP does not provide any way to write your own comparison method that will be automatically invoked when you use ==
or ===
but you could just do it with a method call, e.g.
class comparableObject {
var $property1 = FALSE;
var $property2 = FALSE;
function looseCompare ($obj) {
if (!is_a($obj,'comparableObject')) return FALSE;
return $this->property1 == $obj->property1 && $this->property1 == $obj->property1;
}
function strictCompare ($obj) {
if (get_class($obj) !== 'comparableObject')) return FALSE;
return $this->property1 === $obj->property1 && $this->property1 === $obj->property1;
}
}
$a = new comparableObject;
$b = new comparableObject;
var_dump($a->looseCompare($b)); // TRUE
var_dump($b->strictCompare($a)); // TRUE
$a->property1 = '';
var_dump($a->looseCompare($b)); // TRUE (emtpy string == FALSE)
var_dump($b->strictCompare($a)); // FALSE (emtpy string !== FALSE)
Currently the only way to overload operators is to use the operator
PECL extension. But, for array_diff()
all you need to do is define __toString()
so that the objects can be compared as strings (see notes):
class Point
{
var $x;
var $y;
function __construct($x_, $y_)
{
$this -> x = $x_;
$this -> y = $y_;
}
function __toString()
{
return "x:" . $this->x . " y:" . $this->y;
}
}
Edit:
If you are trying to compare equality of two arrays, array_diff()
is the wrong function. You don't need any overloading or toString()
at all; simply compare the arrays:
$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas3 = array(new Point(0,1),new Point(1,1),new Point(0,1));
if ($mas1 == $mas2) {
echo "MAS1 == MAS2
";
} else {
echo "MAS1 != MAS2
";
}
if ($mas1 == $mas3) {
echo "MAS1 == MAS3
";
} else {
echo "MAS1 != MAS3
";
}
Output:
MAS1 == MAS2
MAS1 != MAS3
In fact, PHP doesn't support overloaded operators. The first comparison tests only array of strings, while the second tests the internal number of the object and not its content.
What you should do here is use the function array_udiff.
This function allows you to compare two arrays using a callback function. In this callback function you can include the logical you want. This function returns an array of differences between the two arrays compared. If you want to check if both are equal, see if the returned array is empty. See array_udiff()
See the example below:
class Point
{
var $x;
var $y;
function _construct($x_, $y_)
{
$this -> x = $x_;
$this -> y = $y_;
}
static function compare(Point $a, Point $b)
{
// Do your logic here.
if ($a->x === $b->x && $a->x === $b->x) {
return 0;
}
return ($a->x > $b->x)? 1:-1;
}
}
$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));
if(count(array_udiff($mas1, $mas2, 'Point::compare')) == 0) {
// Eq
}
else {
// Diff
}
One problem right now is that, in fact, your arrays will always be equal because the Point
class definition is wrong.
A constructor in PHP is __construct
(two underscores), as opposed to what you did: _construct
(single underscore). Therefore, your constructor is never executed, and $x
and $y
are never assigned to your object instance.
If you fix it:
class Point
{
var $x;
var $y;
function __construct($x_, $y_)
{
$this -> x = $x_;
$this -> y = $y_;
}
}
Then you can simply do:
$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas3 = array(new Point(0,1),new Point(0,1),new Point(0,2));
$mas4 = array(new Point(0,1),new Point(0,1),new Point(0,1),new Point(0,1));
var_dump($mas1 == $mas2); // true
var_dump($mas2 == $mas3); // false
var_dump($mas2 == $mas4); // false