title: Creating object / loading from DB - Factory pattern and validation in setters?
body: <p>I have a question what would be the best approach when object could by created in many ways.</p>
  
  <p>Let's say we have:</p>
  
  <pre><code>class User {
  
      private $id;
      private $name;
      private $surname;
      private $login;
  
      public function setId($id) {
        $id = (int) $id;
        if (!$id) {
          throw new Exception("Wrong ID"); 
        }
        $this-&gt;id = $id;
      }
  
      public function setName($name) {
        $this-&gt;name = trim($name);
        if (strlen($name) &lt; 5) {
          throw new Exception("Name is to short");
        }
      }
  
      public function setSurname($surname) {
        $this-&gt;surname = trim($surname);
        if (strlen($surname) &lt; 5) {
          throw new Exception("Surname is to short");
        }
      }
  
      public function setLogin($login) {
        /* some login validation */
        $this-&gt;login = $login;
      }    
  
  
      /* and other methods */
  
  }
  </code></pre>
  
  <p>No I could use this in several ways:</p>
  
  <p><strong>1. Create new user and save it in DB :</strong></p>
  
  <pre><code>$User = (new User)
    -&gt;setName("John")
    -&gt;setSurname("Kent")
    -&gt;setLogin("JohnK");
  
  $UserSaver = (new UserSaver($User))-&gt;save();
  </code></pre>
  
  <p><strong>2. Load user from DB</strong></p>
  
  <pre><code>class UserFactory {
  
    public function createById($userId, $db) {
      $row = $db-&gt;GetRow("SELECT * FROM users WHERE u_id = {$db-&gt;qstr($userId}");
      $User = (new User)
        -&gt;setId($row['id'])
        -&gt;setName($row['name'])
        -&gt;setSurname($row['surname'])
        -&gt;setLogin($row['login']);
      return $User;
    }
  }
  
  $User = UsersFactory::createByID(7, $db);
  </code></pre>
  
  <p>But my question is about validation in setters. Should it be there?
  It could cause a problem when fetching record from database when for example the login is too short (stored erlier by other application). Then an <code>Exception</code> would be thrown.</p>
  
  <p>I could:</p>
  
  <ol>
  <li><p>Move validation to separate function <strong>$this->validate()</strong> but I thought that better practice is to detect wrong data as soon as possible.</p></li>
  <li><p>Modify setters by adding second parameter: <strong>function setLogin($login, $validate=true)</strong> and then in UsersFactory do (new User)->setLogin($row['login'], <strong>false</strong>)</p></li>
  <li><p>use inheritance insted of factory to skip setters.</p></li>
  </ol>
  
  <p>Like this:</p>
  
  <pre><code>class UserFromDB extends User () {
  
    public function __construct($userId, $db) {
      $row = $db-&gt;GetRow("SELECT * FROM users WHERE u_id = {$db-&gt;qstr($userId}");
      $this-&gt;id = $row['id'];
      $this-&gt;name = $row['name'];
      $this-&gt;surname = $row['surname'];
      $this-&gt;login =  $row['login'];
    } 
  
  }
  </code></pre>
  
  <p>I will be grateful for suggestions for best solution.</p>