title: Doctrine2 immutable entities and append only data structures
body: <p>I like the technique described by the Marco Pivetta at PHP UK Conference 2016 (<a href="https://youtu.be/rzGeNYC3oz0?t=2011" rel="nofollow">https://youtu.be/rzGeNYC3oz0?t=2011</a>), he recommends to <strong>favour immutable entities</strong> and instead of changing data structures - <strong>appending them</strong>. History of changes as a bonus is a nice thing to have for many different reasons, so I would like to apply this approach on my projects. Let's have a look at the following use case:</p>
  
  <pre><code>class Task {
      protected $id;
      /**
       * Status[]
       */
      protected $statusChanges;
  
      public function __construct()
      {
          $this-&gt;id = Uuid::uuid4();
          $this-&gt;statusChange = new ArrayCollection();
      }   
  
      public function changeStatus($status, $user){
          $this-&gt;statusChange-&gt;add(new Status($status, $user, $this);
      }
  
      public function getStatus()
      {
          return $this-&gt;statusChange-&gt;last();
      }
  }
  
  class Status {
      protected $id;
      protected $value;
      protected $changedBy;
      protected $created;
  
      const DONE = 'Done';
  
      public function __construct($value, User $changedBy, Task $task)
      {
          $this-&gt;id = Uuid::uuid4();
          $this-&gt;value = $value;
          $this-&gt;changedBy = $changedBy;
          $this-&gt;task = $task;
          $this-&gt;created = new \DateTime();
      }
  }
  
  $user = $this-&gt;getUser();
  $task = new Task();
  $task-&gt;changeStatus(Status::DONE, $user);
  $taskRepository-&gt;add($task, $persistChanges = true);
  </code></pre>
  
  <p>All status changes I'm planning to persist in the MySQL database. So the association will be One(Task)-To-Many(Status).</p>
  
  <p><strong>1) What is the recommended way of gettings tasks by current status? Ie. all currently opened, finished, pending tasks.</strong> </p>
  
  <pre><code>$taskRepository-&gt;getByStatus(Status::DONE);
  </code></pre>
  
  <p><strong>2) What is your opinion on this technique, are there some disadvantages which may appear in the future, as the project will grow?</strong></p>
  
  <p><strong>3) Where it is more practical to save status changes (as a serialized array in a Task field, or in a separate table?</strong></p>
  
  <p>Thanks for opinions!</p>