Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2727

"Expression" or "Update" API, similar to the Criteria API

    Details

    • Type: New Feature New Feature
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Security Level: All
    • Labels:
      None

      Description

      I created a discussion in the mailing list (https://groups.google.com/forum/#!topic/doctrine-dev/7HfEqOwhkDk) but no answer, so I'm moving the discussion here.


      The Criteria API provides an abstraction to filter collections/repositories, may they be in memory (filtering in PHP) or in a database (filtering using a SQL query).

      I was thinking about an "Expression" API which would work like array_map to apply changes in bulk to entities.

      For example, if you have a collection where entities have a $position field, if I insert an item in the list, I have to increment the position of all the following items. For this, I have 2 options:

      • PHP: loading the entities in memory, iterate over them and increment $position
      • SQL: run a UPDATE position=position + 1 WHERE …

      The second option is much more efficient, but it breaks the abstraction of the model because I have some behavior written explicitely in SQL. Furthermore, the objects loaded in memory will note be updated with the SQL query.

      So the "Expression" API would work like the Criteria API:

      interface Updatable {
          public function apply(Expression $e);
      }
      
      $expression = new Expression();
      
      // For each item after position "10"
      $expression->criteria->where(Criteria::expr()->gt('position', 10));
      // Increment the position
      $expression->set('position', 'position + 1');
      
      $collection->map($expression);
      

      The expression here would be applied:

      • in memory if the collection is already loaded
      • else in database using SQL

      The expression could be applied to a Collection and to a Repository (like the Criteria).


      About the API offered by the Expression class, there are several options:

      // Option 1
      // More powerful, but needs to parse and evaluate the string
      class Expression
      {
          public $criteria;
          public function set($field, $value);
      }
       
      $expression->set('position', 'position + 1');
       
      // Option 2
      // Easier to implement, more limited
      class Expression
      {
          public $criteria;
          public function setValue($field, $value);
          public function setValueFromField($targetField, $sourceField);
          public function add($field, $number);
          public function multiply($field, $number);
          public function divide($field, $number);
      }
       
      // Option 3
      // Like option 2 but more extensible
      class Expression
      {
          public $criteria;
          public function set($field, Operation $operation);
      }
      

      I think I like the third one better because we have full control over the supported operations, and adding support to new kinds of operation is easy. The first one would require defining a whole language of allowed expressions...


      What do you think of all that?

        Activity

        Hide
        Matthieu Napoli added a comment -

        Added option 3 after trying to write a POC

        Show
        Matthieu Napoli added a comment - Added option 3 after trying to write a POC
        Hide
        Matthieu Napoli added a comment -

        Here is a POC on the doctrine/collections side: https://github.com/mnapoli/collections/compare/master...feature;Updatable works with ArrayCollection

        I'm looking at the ORM side.

        Feedback welcome, especially with the class/namespace/method names.

        Show
        Matthieu Napoli added a comment - Here is a POC on the doctrine/collections side: https://github.com/mnapoli/collections/compare/master...feature;Updatable works with ArrayCollection I'm looking at the ORM side. Feedback welcome, especially with the class/namespace/method names.

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Matthieu Napoli
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: