2

Is there a way to "safely" chain methods in PHP and simply return null if some previous method returns null? Otherwise, an error would be thrown: trying to get property on non-object;

For example, the following code checks whether a customer's phone number has changed using a QuickBooks SDK. I don't have control over these methods.

$customer->getPrimaryPhone() will always return an object since the form wouldn't have been submitted otherwise, but $old->getPrimaryPhone() may return null if no phone number existed previously.

The following is required to get the phone number:

$old->getPrimaryPhone()->getFreeFormNumber()

If getPrimaryPhone() returns null, then an error would be thrown.

My question is: How would I avoid code repition in the following case?

if (!empty($old->getPrimaryPhone())) {
    if ($customer->getPrimaryPhone()->getFreeFormNumber() !== $old->getPrimaryPhone()->getFreeFormNumber()) {
        // Repetive code here
    }   
} else {
        // Repetive code here
}
Raphael Rafatpanah
  • 19,082
  • 25
  • 92
  • 158
  • `if ($oldPrimaryPhone = $old->getPrimaryPhone()) ... !== $oldPrimaryPhone->getFreeFormNumber()` – Phil Jul 01 '15 at 23:21
  • Even though those methods have the same name, and even if both objects have the same value for `getFreeFormNumber()`, sometimes the property is stored in an array at index 0, and sometimes is stored as a primitive value. Therefore, I can't compare the higher level objects. Again, not in my control. – Raphael Rafatpanah Jul 01 '15 at 23:23
  • 1
    Depending on the practical chain combinations, returning a NullObject sometimes makes sense. – mario Jul 01 '15 at 23:23
  • @mario, Exactly. I would like to find a way to get `$old->getPrimaryPhone()->getFreeFormNumber()` to return null, or an empty object rather than throw an error `trying to get property on non object` – Raphael Rafatpanah Jul 01 '15 at 23:25

1 Answers1

4

I'd be inclined to implement an equals method on your PhoneNumber class (or whatever it's called). For example

public function equals(PhoneNumber $otherNumber) {
    return $otherNumber !== null && $this->getFreeFormNumber() === $otherNumber->getFreeFormNumber();
}

Then you can simply use

if (!$customer->getPrimaryPhone()->equals($old->getPrimaryPhone())

If you've got other logic that needs to be applied (as indicated in your comment about arrays), you can easily implement that in the equals method.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Interesting. I have several fields with this problem. I could of course create a method for each field, but is there a generic way to do this without knowing the second level method names? If so, I can use only one function to compare other fields like `address`, `email`, etc. – Raphael Rafatpanah Jul 01 '15 at 23:32
  • You could have all your *field* classes with the `equals` method implement then just call `return $this->field->equals($other->field) &&..` in the parent class `equals` method – Phil Jul 01 '15 at 23:45