Frage

Ich habe eine Anwendung, wo ich PHP mit Zend Framework und Doctrine2 als ORM verwenden. Meine Frage bezieht sich auf wie viel die Steuerung vorzugsweise über das zugrunde liegende Modell und Persistenz-Schicht wissen sollten. Idealerweise würde ich sagen, dass dies ‚nichts‘ selbst - die Steuerung nichts wissen sollte, wie / wann die Entitäten bestehen bleibt. Ich glaube jedoch, dies ist nicht immer die beste Lösung (?).

Ich habe versucht, die ‚Trennung von Bedenken‘ Designrichtlinien zu folgen. Ich habe dies getan, indem eine Dienstschicht zu schaffen, dass führt Operationen auf meine Modelle CRUD. Siehe das folgende Beispiel:

public function testbuildAction()
{        
    // create section
    $sectionService = new \MyAPP\Model\Service\Acl\SectionService();        
    $sectionA       = $sectionService->createSection('SectionA-NAME');

    // create privilege with the above section
    $privilegeService   = new \MyAPP\Model\Service\Acl\PrivilegeService();
    $privilegeA = $privilegeService->createPrivilege(
                            $sectionA, 
                            \MyAPPFrameWork\Model\Acl\Privilege::PERMISSION_EDIT
                        );

    // create a role with the privilege above. A role must have at least one priv.
    $roleService = new \MyAPP\Model\Service\Acl\RoleService();
    $role        = $roleService->createRole('Role-NAME', $privilegeA); 

    // this loads a managed User object (managed by EntityManager)
    $user = $this->_helper->IdentityLoader(); 
    $user->addRole($role); // add the role to this user
    $userService = new \MyAPP\Model\Service\Core\UserService();        
    $userService->updateUser($user); // persist the updates.
}

Wie Sie den Controller nicht weiß nichts über Persistenz sehen kann, aber dieses Ergebnis zu erhalten Ich brauche beide auszuführen bestehen () und flush () im Inneren eines jeden Aufruf der createXXX () oder updateXXX () Methoden der Serviceschicht . Ich hätte lieber etwas getan wie folgt aus:

public function testbuildAction()
{        
    // create section
    $sectionService = new \MyAPP\Model\Service\Acl\SectionService();        
    $sectionA       = $sectionService->createSection('SectionA-NAME');

    // create privilege with the above section
    $privilegeService   = new \MyAPP\Model\Service\Acl\PrivilegeService();
    $privilegeA = $privilegeService->createPrivilege(
                            $sectionA, 
                            \MyAPPFrameWork\Model\Acl\Privilege::PERMISSION_EDIT
                        );

    // create a role with the privilege above. A role must have at least one priv.
    $roleService = new \MyAPP\Model\Service\Acl\RoleService();
    $role        = $roleService->createRole('Role-NAME', $privilegeA); 

    // this loads a managed User object (managed by EntityManager)
    $user = $this->_helper->IdentityLoader(); 
    $user->addRole($role); // add the role to this user

    // persist it all (all service-classes access the same entitymanager).
    $roleService->flush(); // everything is persisted
}

Aber dies führt Doctrine2 zum Scheitern verurteilt, da sie die Objekte in die Datenbank in der falschen Reihenfolge tun bestehen - Privilegien vor Abschnitten beibehalten werden (weiß nicht, ob ich Lehre anweisen kann dies in geordneter Weise durchzuführen ??). Die Privilegien bekommen falsche ID für die Abschnitte, die noch nicht ist, beibehalten.

Wie auch immer, hier die große Frage ist, ob ich versuchen soll, Spülung zu verschieben, bis alle Objekte erstellt wurden und die Beziehungen gesetzt wurden. Das Ziel ist, eine Transaktion zu haben, die alle Schreiben in die Datenbank tut - die folglich von der Steuerung ausgelöst werden muss (da es sich um das einzige zu wissen, wenn Objekt und Beziehung Gebäude erfolgt), wodurch ‚verunreinigen‘ die Steuerung mit dem Wissen über die Persistenz-Schicht?

War es hilfreich?

Lösung

legt nahe Antony etwas wie Einhaken in __destruct () des EntityManager. Aber da Sie wissen nicht, ob Entitäten raelly geändert Sie nicht bündig rufen jedes Mal wollen, auch wenn Sie nur eine schreibgeschützte Szenario haben.

Daher ist die Service-Schicht sollte nicht bündig, aber der Controller, könnte man leicht die Lehre Eventmanager verwenden, um jede Service-Layer-Aktion haben Versand ein Ereignis „requireFlush“:

$em->getEventManager()->dispatchEvent("requireFlush", new OnFlushEventArgs($em));

Sie sollten wahrscheinlich eine Art von Komfortfunktion für diesen schreiben.

Dann schreiben Sie Ihre eigene Veranstaltung Zuhörer:

class DelayFlushListener
{
    private $requiresFlush = true;
    private $delayFlush = true;

    public function __construct($delayFlush = true) {
       $this->delayFlush = $delayFlush;
    }

    public function requireFlush(EventArgs $args) {
        $this->em = $args->getEntityManager();
        if ($this->delayFlush) {
            $this->requiresFlush = true;
        } else {
            $this->em->flush();
        }
    }

    public function flush() {
         if ($this->requiresFlush) {
             $this->em->flush();
         }
    }
}

registrieren Sie sich jetzt, dass die Zuhörer in der Bootstrap:

 $listener = new DelayFlushListener();
 $em->getEventManager()->addEventListener(array("requireFlush"), $listener);

Und in Ihrem Controller können Sie die Verzögerung bündig, wenn notwendig, in einem postdispatch Rückruf bei jeder einzelnen Anforderung auslösen).

 $listener->flush();

Andere Tipps

Ich werde bereitwillig zugeben, ich weiß absolut nichts über Zend, PHP oder Doctrine2 ...

Aber, klingt das wie Sie eine Implementierung der Arbeitseinheit müssen Muster. Ich arbeite mit MVC mit ASP.NET und C # und hat etwas, was das bedeutet.

Nachdem das nun gesagt, dass meine Controller rufen Sie die Service-Schicht und es ist auf die Dienstschicht zu steuern, wenn die Transaktion an dem persistenten Speicher (Datenbank in meinem Fall) verpflichtet,

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top