phpconstructor

Hydrate and Constructors in PHP


When instancing an object from a SQL database, I read I should use a hydrate() function to populate my objects rather than the constructor directly.

Is there differences between the codes below ?

With hydrate() :

class User {

    // attributes ...

    public function __construct(array $data = array()) {
            if (!empty($data)) {
                $this->hydrate($data);
            }
    }
    public function hydrate(array $data) {
       foreach ($data as $key => $value) {
          // One gets the setter's name matching the attribute.
          $method = 'set'.ucfirst($key);

          // If the matching setter exists
          if (method_exists($this, $method)) {
             // One calls the setter.
             $this->$method($value);
          }
       }
    }
   // Getters/Setters and methods ...
}

Into constructor directly :

class User {

        // attributes ...

    public function __construct(array $data = array()) {
            if (!empty($data)) {
                foreach ($data as $key => $value) {
                   // One gets the setter's name matching the attribute.
                   $method = 'set'.ucfirst($key);

                   // If the matching setter exists
                   if (method_exists($this, $method)) {
                     // One calls the setter.
                     $this->$method($value);
                   }
                }
            }
    }
   // Getters/Setters and methods ...
}

Solution

  • When you have classes with many attributes, with each attribute possessing its own setter with specific checks, this is a useful way of calling them all, not one by one.

    Its second purpose is if you need to reuse your object (let's say to perform test) with new values. You won't have to reconstruct a new one (or each of the setters), just call again hydrate and your class attributes will be updated.

    Here is a basic example:

    <?php
    class Test
    {
        protected $titre;
        protected $date;
        protected ...
        // And so on
         
        public function __construct($value = array())
        {
            if(!empty($value))
                $this->hydrate($value);
        }
     
        public function hydrate($data)
        {
            foreach ($data as $attribute => $value) {
                $method = 'set'.str_replace(' ', '', ucwords(str_replace('_', ' ', $attribute)));
                if (is_callable(array($this, $method))) {
                    $this->$method($value);
                }
            }
        }
     
        public function setTitle($title)
        {
            // Do specific check
            $this->title = $title;
        }
    
        public function setDate($date)
        {
            // Do specific check
            $this->date = $date;
        }
    }
     
    $test = new Test(array("title" => "hello world", ...));
    // Manipulate the $test var and change stuff
    ...
    $new_values = array("title" => "Hello, I am back", ...);
    $test->hydrate($new_values);
    ?>