Is there a __equals method in PHP like there is in Java?

前端 未结 5 1032
执念已碎
执念已碎 2021-01-01 09:40

Is there a pattern or magic method you can use in PHP to define when to compare two instances of a class?

For example, in Java I could easily override the equa

5条回答
  •  Happy的楠姐
    2021-01-01 10:05

    First off the == operator is sufficient in most cases, especially if we are talking about value objects. Just be sure to provide a __toString method if you want the ability to compare the instance with scalar values.

    value = $value;
        }
    
        public function __toString() {
            return (string) $this->value;
        }
    
    }
    
    $a = new ValueObject(0);
    $b = new ValueObject(1);
    
    var_dump(
        $a == $b,  // bool(false)
        $a == $a,  // bool(true)
        $b == $b,  // bool(true)
        $a == '0', // bool(true)
        $b == '1'  // bool(true)
    );
    

    There is one gotcha with this, you cannot compare to scalar type other than string (at least not in PHP 5 and 7) because it will complain that the instance could not be converted to the desired value. Hence, you always need to ensure that the value type you compare to is a string.

    If you want more than that, e.g. you want to lowercase the input or handle float value up until a certain accuracy, you need a different approach. One way to handle this is as follows.

    compareTo($b);
    }
    
    final class C implements Comparable {
    
        private $value;
    
        public function __construct(int $value) {
            $this->value = $value;
        }
    
        public function compareTo(Comparable $other): int {
            assert($this instanceof $other && $other instanceof $this);
    
            return $this->value <=> $other->value;
        }
    
    }
    
    $c1 = new C(0);
    $c2 = new C(0);
    
    var_dump($c1->compareTo($c2)); // int(0)
    
    $c0 = new C(0);
    $c1 = new C(1);
    $c2 = new C(2);
    
    $actual = [$c2, $c1, $c0];
    usort($actual, 'class_compare');
    
    var_dump($actual === [$c0, $c1, $c2]); // bool(true)
    

    The assert is important since we have no generics in PHP. This is a pretty sad state of things and there is no pretty way to implement this.

    What I tend to do is the following.

    value = $value;
        }
    
        public static function compare(SomeClass $a, SomeClass $b): int {
            return $a->compareTo($b);
        }
    
        public function compareTo(SomeClass $other): int {
            return $this->value <=> $other->value;
        }
    
        public function isEqual($other): bool {
            return $other instanceof $this && $other->value === $this->value;
        }
    
        public function isIdentical($other): bool {
            return $other instanceof $this && $this instanceof $other && $other->value === $this->value;
        }
    
    }
    

    Simply sticking to these method names by convention allows it to use them appropriately. One could even provide traits to implement the desired default behavior among multiple classes.

提交回复
热议问题