note 108690 deleted from language.operators.comparison by cmb
| From: | cmb@php.net | Date: | Sun, 11 Aug 2019 11:59:38 +0000 |
| Subject: | note 108690 deleted from language.operators.comparison by cmb | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-211849@lists.php.net to get a copy of this message | ||
Note Submitter: wbcarts at juno dot com
----
COMPARING PHP OBJECTS (compound type)
We have seen that PHP does a lot of type-juggling on its own -- which can wreak havoc in unexpected
ways -- but it is still up to us to produce code that is clear, maintainable AND follows the rules
we want to follow.
When creating a PHP Object, it is sometimes unclear what makes two of them the same. But the good
part is that we can say what is equal and what is not equal. For example, let's say we have a
Student class that includes an equals() method which defines what is equal for this type of object.
<?php
#Student.php
class Student
{
/*
* These variables are protected to prevent outside code
* from tampering with them.
*/
protected $student_id;
protected $student_name;
public function __construct($id, $name)
{
$this->student_id = (int)$id; // cast to integer here
$this->student_name = (string)$name; // cast to string here
}
/*
* This function requires an instance of type Student and
* only evaluates two integers that we set in __construct().
*/
public function equals(Student $student)
{
return ($this->getId() == $student->getId());
}
public function getId()
{
return $this->student_id;
}
public function getName()
{
return $this->student_name;
}
public function __toString()
{
return 'Student [id=' . $this->getId() .
', name=' . $this->getName() . ']';
}
}
?>
With this class, the protected variables cannot be tampered with by outside code. Also, the
__construct() function casts the variables to the PHP primitives WE WANT, while the equals(Student
$student) function, requires an argument of type Student -- which eliminates the need for an
IDENTITY '===' check AND prevents any other data types from coming in. One other note:
notice how the equals() function only evaluates the $student_id, this allows for two students to
have the same name -- which is totally possible.
Here's a short example -- we'll do it correctly AND try to screw it up!
<?php
require('Student.php');
$s1 = new Student(122, 'John Doe');
$s2 = new Student(344, 'John Doe');
echo $s1 . '<br>'; // Student [id=122, name=John Doe]
echo $s2 . '<br>'; // Student [id=344, name=John Doe]
# Check for equality the CORRECT way...
echo ($s1->equals($s2) ? 'EQUAL' : 'NOT EQUAL'); // NOT EQUAL
# Check for equality by HACKING the known value of $student_id...
echo ($s1->equals(122) ? 'EQUAL' : 'NOT EQUAL'); // Catchable fatal error:
Argument 1 passed to Student::equals() must be an instance of Student, integer given... etc, etc.
?>
See what I mean by writing code that follows OUR RULES? The Student class does the kind of
type-juggling we want (and when we want it done) -- NOT when, where, or why PHP does it (not that
there's anything wrong with it).