Changer les politiques de suivi Symfony2


Table des matières

Référence
Différé implicite
Différé explicite
Notification

Référence

http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/change-tracking-policies.html

Le suivi des modifications est le processus de détermination de ce qui a changé dans les entités gérées depuis la dernière fois qu'ils ont été synchronisées avec la base de données.

Doctrine fournit trois différentes politiques de suivi des modifications, chacun ayant ses avantages et ses inconvénients. La politique de suivi des modifications peut être définie sur une base par classe (ou plus précisément, par hiérarchie).

Différé implicite

La politique implicite est différée, la politique de changement par défaut sur le suivi est la plus commode. Avec cette politique, la doctrine détecte les changements par une comparaison de propriétés à propriétés au moment de la validation et détecte également des modifications à des entités ou des nouvelles entités qui sont référencés par d'autres entités gérées («persistance par accessibilité"). Bien que cela soit la politique la plus pratique, il peut y avoir des effets négatifs sur les performances si vous travaillez avec des grandes unités de travail. Depuis Doctrine ne peut pas savoir ce qui a changé, il doit vérifier l'ensemble des entités gérées pour des changements à chaque fois que vous invoquez EntityManager#flush(), ce qui rend cette opération assez coûteuse.

Différé explicite

La politique explicite est similaire à la politique implicite mais elle est différée. Elle détecte les changements à travers une comparaison de propriété par propriété au moment de l'engager. La différence est que Doctrine considère que deux entités qui ont été explicitement marqué pour la détection du changement à travers un appel à l'EntityManager#persist(entity) ou à travers la sauvegarde une cascade. Toutes les autres entités sont ignorées. Cette politique donne donc des performances améliorées pour les grandes unités de travail tout en sacrifiant le comportement de "vérification automatique".

Par conséquent, les opérations de flush() sont potentiellement moins onéreuses pour cette politique. L'aspect négatif est que si vous avez une application assez large et que vous passiez vos objets à travers plusieurs couches à des fins de traitement et de tâches professionnelles, vous devriez peut-être avoir la même piste pour les entités qui ont changé sur le chemin afin que vous puissiez les transmettre à EntityManager#persist().

Cette politique peut être configuré comme suit:

<?php
/**
 * @Entity
 * @ChangeTrackingPolicy("DEFERRED_EXPLICIT")
 */
class User
{
    // ...
}

Notification

Cette politique est fondée sur l'hypothèse que les entités notifiées informent les "listeners" des modifications de leurs propriétés. À cette fin, une classe qui veut utiliser cette politique doit implémenter l'interface du namespace de Doctrine : NotifyPropertyChanged. À titre indicatif, une telle mise en œuvre peut se présenter comme suit:

<?php
use Doctrine\Common\NotifyPropertyChanged,
    Doctrine\Common\PropertyChangedListener;

/**
 * @Entity
 * @ChangeTrackingPolicy("NOTIFY")
 */
class MyEntity implements NotifyPropertyChanged
{
    // ...

    private $_listeners = array();

    public function addPropertyChangedListener(PropertyChangedListener $listener)
    {
        $this->_listeners[] = $listener;
    }
}

Puis, dans chaque propriété settée de cette classe ou des classes dérivées, vous devez en aviser toutes les instances PropertyChangedListener. À titre d'exemple, nous ajoutons une méthode de convenance sur les MyEntity qui montre ce comportement:

<?php
// ...

class MyEntity implements NotifyPropertyChanged
{
    // ...

    protected function _onPropertyChanged($propName, $oldValue, $newValue)
    {
        if ($this->_listeners) {
            foreach ($this->_listeners as $listener) {
                $listener->propertyChanged($this, $propName, $oldValue, $newValue);
            }
        }
    }

    public function setData($data)
    {
        if ($data != $this->data) {
            $this->_onPropertyChanged('data', $this->data, $data);
            $this->data = $data;
        }
    }
}

Vous devez invoquer _onPropertyChanged à l'intérieur de chaque méthode qui modifie l'état persistant de MyEntity.

La vérification que la nouvelle valeur est différente de l'ancienne n'est pas obligatoire mais recommandée. De cette façon, vous avez également le plein contrôle sur ce qu'on considère qu'une propriété à changé.

Le point négatif de cette politique est évidente: Vous avez besoin d'implémenter une interface et écrire du code. Mais aussi noter que nous nous sommes efforcés de garder ce résumé fonctionnel. Strictement parlant, il n'a rien à voir avec la couche de persistance et de l'ORM Doctrine ou DBAL. Vous pouvez constater que les événements de notification de propriété s'avérent utiles dans de nombreux autres scénarios ainsi. Comme mentionné précédemment, le namespace Doctrine\Common se compose uniquement de très petites classes et interfaces qui n'ont pratiquement aucune dépendance externe (aucun à l'DBAL et aucun à l'ORM) et que vous pouvez facilement emporter avec vous si vous voulez d'échanger les couche de persistance. Cette politique de suivi des modifications ne pas introduire une dépendance sur la Doctrine DBAL/ORM ou la couche de persistance.

Le point positif, et l'avantage principal de cette politique est son efficacité. Il a les meilleures performances des 3 politiques avec les grandes unités de travail et de l'exploitation un flush() n'est pas cher quand rien n'est changé.