The grass is rarely greener, but it's always different

Validating data in PHP objects using magic methods

I've been working with PHP lately and when deserializing a model I wanted to have a generic way of adding validations for its properties, so I thought whether there was a way for hooking into an object's properties while getting/setting them, much like the Proxy object in javascript.

I found that magic methods in PHP would do the trick. Magic methods overwrite the object's default functionality when the event that triggers them happens. The most commonly used is the __construct() method, the constructor for the object.

Using the __get and __set magic methods, we can hook into the property when getting & setting it and run our custom logic. Hence, creating a bunch of validators to verify we're not assigning them any forbidden values:

class User {
   public $allowedProperties = [ 'firstName', 'email' ];	
   private $firstName;
   private $email;

   public function __set($propertyName, $value) {
      if (!in_array($propertyName, $this->allowedProperties)) {
         throw new Exception('Property: ' . $propertyName . ' not supported');
      }

      $validator = $propertyName . 'Validator';
    	$isPropertyValueValid = $this->$validator($value);
    	if (!$isPropertyValueValid) {
    		throw new Exception('Value: ' . $value . ' for: ' . $propertyName);
    	}
    	$this->$propertyName = $value;
    }
    
    public function __get($propertyName) {
    	if (!in_array($propertyName, $this->allowedProperties)) {
    		throw new Exception('Property: ' . $propertyName . ' not supported');
    	}
        return $this->$propertyName;
    }

    private function firstNameValidator($value) {
    	return is_string($value) && strlen($value) < 25;
    }

    private function emailValidator($value) {
    	return filter_var($value, FILTER_VALIDATE_EMAIL);
    }
}


$user = new User();
$user->firstName = 'Ahhhh I am longer than 25 characters nooooooo'; // throw Exception
$user->email = 'esteban@gmail.com';

It is important to point out that by using this strategy we'll lose any static analysis we have, so it's a choice to make.

Have fun!

#PHP #programming