title: Object wrappers and forms
body: <p>I am developing an ecommerce platform and came across a difficulty. Basically, I have in my scenario a Product, Option and OptionValue. A product might have multiple options which might have multiple values. The problem is how to store it in a way that is easy to create and edit.</p>
  
  <p><img src="https://i.stack.imgur.com/81HBX.png" alt=""></p>
  
  <p>The problem is I've a direct reference to the OptionValue, which is mutable. I need to keep immutable information about the Option and OptionValue (for example, if a order was made and the color was green, even if this option is changed to lime green, the order must keep showing as green). In that case, I need to save some properties of Option (the option name - "Colors" for example) and of each OptionValue (the value of each option - "red" for example). The way I thought, it would require a structure very similar to the existing structure: a new class ItemOption referencing Option and a ItemOptionValue referencing OptionValue.</p>
  
  <p><img src="https://i.stack.imgur.com/zMmbv.png" alt=""></p>
  
  <p>So, this was my attempt:</p>
  
  <p>To create a form to display my options I have:</p>
  
  <pre><code>class OptionSelectorType extends AbstractType {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          foreach ($options['product']-&gt;getOptions() as $option) {
              $builder-&gt;add($option-&gt;getId(), 'choice', array('choice_list' =&gt; new ObjectChoiceList($option-&gt;getValues());));
          }
      }
  }
  </code></pre>
  
  <p>I'm using a DataTransformer to convert a collection of OptionValue in a collection of OrderItemOption:</p>
  
  <pre><code>class OrderItemOptionToOptionValueTransformer implements DataTransformerInterface
  { 
      public function transform($lineOptions)
      {
        if(!$lineOptions) {
          return array();
        }
        $values = array();
        foreach($lineOptions as $lineOption) {
          $lineOption-&gt;getOption()-&gt;getId();
          $values[$id] = array();
  
          foreach($lineOption-&gt;getValues() as $lineOptionValue) {
            $values[$id][] = $lineOptionValue-&gt;getOptionValue();
          }
        }
  
          return $values;
      }
  
      public function reverseTransform($values)
      {
        $collection = new ArrayCollection();
        foreach($values as $optionId =&gt; $optionValues) {
          if(!$optionValues) {
            continue;
          }
  
          $lineOption = new OrderItemOption();
          $optionValues = is_array($optionValues) ? $optionValues : array($optionValues);
          foreach($optionValues as $optionValue) {
            $lineOptionValue = new OrderItemOptionValue();
            $lineOptionValue-&gt;setOptionValue($optionValue);
            $lineOption-&gt;addValue($lineOptionValue);
          }
  
          $lineOption-&gt;setOption($optionValue-&gt;getOption());
          $collection-&gt;add($lineOption);
        }
  
        return $collection;
      }
  }
  </code></pre>
  
  <p>Finally, my OrderItemType form:</p>
  
  <pre><code>class OrderItemType extends AbstractType
  {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
        $builder-&gt;add(
          $builder-&gt;create('options', 'option_selector', array('options' =&gt; $options['options']))
          -&gt;addModelTransformer(new OrderItemOptionToOptionValueTransformer())
        );
      }
  }
  </code></pre>
  
  <p>It works but doesn't seem to me a good approach, once the OptionValue will be always recreated, never updated.</p>
  
  <p>How would you do it?</p>