0

Ich habe einige Codes wie so:Wo platziere ich meinen langen Code, der Domänenobjekte vorbereitet, die in einem Repository aufbewahrt werden sollen?

/* Part of Controller::saveAction() */ 

//create new object instance 
$item = new Item(); 

//populate the Item 
$item->setDescription($description); 
$item->setQuantity($quantity); 
$item->setPrice($price); 

//once we have a fully populated object, 
//send it to Repository pattern, 
//which saves it to persistent storage 
$this->repository->saveItem($item); 

in einer einzigen funciton/Methode, wie die oben mehrere Blöcke Stellen Sie sich vor, und sie werden meine Frage ... Ich bin ziemlich glücklich mit meiner repository Codezeile sehen, aber Ich weiß nicht, wo ich all die "Vorbereitungsarbeiten" platzieren soll, die vor dem Anruf an Repository erledigt werden.

Frage:

Wo finde ich den Großteil des Codes platzieren, die & füllt die Item Objektinstanz erstellt? Es überlagert meine Controller-Methode und ich kann mir keinen anderen Ort vorstellen, an den ich es schreiben könnte.

Tor

Mein Ziel ist eine gute Struktur/Design statt auf rein zu verringern oder minimieren die Anzahl der „Artikel Vorbereitung“ Linien zu finden.

Je nach Controller habe ich etwa 5-7 Item Instanzen, die jeweils 10-16 Zeilen Code erstellen und die Instanzen zu füllen.

+0

Ist es nur die Menge an Codezeilen, um die Sie besorgt sind? Wenn "Item" Konstruktorargumente übergeben werden könnte, die es besser machen würden. Alternativ können Sie die set-Methoden verketten. – Chris

+0

Für die Menge des Codes, nicht wirklich, interessiere ich mich mehr für die richtige Struktur. Aber ich habe ungefähr 100 Zeilen Code in einer einzigen Methode, die das Objekt zum Speichern "erstellt, poliert und vorbereitet". Und ein paar Zeilen Code, die tatsächlich die Objekte speichern. Was das Übermitteln von "Item" über den Konstruktor angeht ... Welches Calling-Code-Konstrukt wird für die Vorbereitung der Objekte verantwortlich sein? Schlägst du vor, ich benutze etwas wie eine 'ControllerFactory', um 'Controller's mit dem' Items' via Konstruktor zu füllen? Ich habe 7 einzelne 'Items', die in einer Methode gespeichert werden, die Anzahl variiert von Controller zu Controller – Dennis

+1

Ich denke @Chris bedeutet, eine Item' ___ construct() 'Methode zu haben, um die Eigenschaften zu setzen und' $ item = new Item ($ description, $ quantity, $ price); ' – AbraCadaver

Antwort

0

Wie Sie erwähnt haben über die richtige Art und Weise zu erreichen so .. wie wäre es mit Delegatoren und Teilen der Controller (Blöcke) in Delegatoren? Es terminologisch wäre es der Fassade [Adapter]

fügen Sie den folgenden zu ./module/MyModule/config/module.config.php sein:

'controllers' => array(
    'invokables' => array(
     'MyModule\CreateController' => 'MyModule\Controller\MyController', 
     'MyModule\ReadController' => 'MyModule\Controller\MyController', 
    ), 
    'delegators' => array(
     'MyModule\CreateController' => array(
      'MyModule\Controller\Delegator\CreateItemDelegatorFactory' 
     ), 
     'MyModule\ReadController' => array(
      'MyModule\Controller\Delegator\ReadItemDelegatorFactory' 
     ), 
    ), 
), 
'form_elements' => array(
    'invokables' => array(
     'item_create' => 'MyModule\Form\CreateForm', 
    ), 
), 

erstellen Delegator Lasten bilden auffüllt es, validates und versucht teh Daten

./module/MyModule/src/MyModule/Controller/Delegator/CreateItemDelegatorFactory.php zu speichern:

namespace MyModule\Controller\Delegator; 

use Zend\ServiceManager\DelegatorFactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 
use MyModule\Entity\Item as Entity; 

/** 
* Class loads the form, checks if form been posted and if is valid. 
* If form is valid it tries to save the item with repository service 
* Class sets the Form per controller, such solution keeps form  
* validation messages 
*/ 
class CreateItemDelegatorFactory implements DelegatorFactoryInterface 
{ 
    /** 
    * Determines name of the form to be loaded with formElementManager 
    * 
    * @var string 
    */ 
    private $form_name = "item_create"; 

    /** 
    * Name of repository service. It may be database, api or other 
    * 
    * @var string 
    */ 
    private $service_repository_name = "service.repository"; 

    public function createDelegatorWithName(
     ServiceLocatorInterface $serviceLocator, 
     $name, 
     $requestedName, 
     $callback 
    ) { 
     // assign serviceManager locally 
     $parentLocator = $serviceLocator->getServiceLocator(); 
     // assign services locally 
     $routerService = $parentLocator->get('router'); 
     $requestService = $parentLocator->get('request'); 
     // get repository service 
     $repositoryService = $parentLocator->get($this->service_repository_name); 

     // read the CreateForm with formElementManager and bind the Entity 
     $callback->setForm(
      $parentLocator->get('FormElementManager')->get($this->form_name) 
     ); 
     $entity = new Entity; 
     $callback->getForm($this->form_name)->bind($entity); 

     // check if data been posted 
     if($requestService->isPost()) { 
      $postData = $requestService->getPost($this->form_name); 
      $callback->getForm($this->form_name)->setData($postData); 
      // validate form 
      if($callback->getForm($this->form_name)->isValid()) { 
       // form is valid 
       $repositoryService->saveItem($entity); 
      } 
     } 
    } 
} 

Mit über Delegator Ihren Controller (My Module \ Controllers \ MyController) müsste die zusätzliche Eigenschaft und zwei Methoden:

/** 
* Holds the form object 
* @var object 
*/ 
private $form 

public function setForm($form=null) 
{ 
    $this->form = $form; 
    return $this; 
} 

public function getForm() 
{ 
    return $this->form; 
} 

./module/MyModule/src/MyModule/Controller/Delegator/ReadItemDelegatorFactory.php:

namespace MyModule\Controller\Delegator; 

use Zend\ServiceManager\DelegatorFactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 
use MyModule\Entity\Item as Entity; 

/** 
* Creates Delegator which tries read item's id from the (segment type) route 
* and read the Item from the repository service 
* 
*/ 
class ReadItemDelegatorFactory implements DelegatorFactoryInterface 
{ 
    /** 
    * Item's ID from route 
    * 
    * @var string 
    */ 
    private $route_identifier = "item_id"; 

    /** 
    * Name of repository service. It may be database, api or other 
    * 
    * @var string 
    */ 
    private $service_repository_name = "service.repository"; 

    public function createDelegatorWithName(
     ServiceLocatorInterface $serviceLocator, 
     $name, 
     $requestedName, 
     $callback 
    ) { 
     // assign serviceManager locally 
     $parentLocator = $serviceLocator->getServiceLocator(); 
     // assign services locally 
     $routerService = $parentLocator->get('router'); 
     $requestService = $parentLocator->get('request'); 
     // get repository service 
     $repositoryService = $parentLocator->get($this->service_repository_name); 
     // get the router match and the item_id 
     $routerMatch = $routerService->match($requestService); 
     $itemId = $routerMatch->getParam($this->route_identifier); 
     // set the data for the target controller 
     $callback->setItem($repositoryService->readItem($itemId)); 

     return $callback; 
    } 

Mit über Delegator Ihr Controller (MyModule \ Controllers \ MyController) würde die zusätzliche Eigenschaft und Methode müssen:

/** 
* Holds the Item object 
* @var object \MyModule\Entity\Item 
*/ 
private $item 

public function setItem($item=null) 
{ 
    $this->item = $item; 
    return $this; 
} 

eine solche Art und Weise der Verwendung des Controllers für den Code hilft, trocken zu bleiben und scheint möglich sein, den Fluss zu steuern. Delegatoren werden als LIFO geladen, daher ist es möglich, den Controller ($ callback) vorzukonfigurieren, bevor er an einen anderen Delegierer übergeben wird.

Wenn der ReadController das Element liest und der CreateController das Formular lädt, ist es ein kurzer Weg für UpdateItemDelegator, den Task Item Update zu bearbeiten.

'controllers' => array(
    'invokables' => array(
     'MyModule\UpdateController' => 'MyModule\Controller\MyController', 
    'delegators' => array(
     'MyModule\ReadController' => array(
      'MyModule\Controller\Delegator\UpdateItemDelegatorFactory', 
      'MyModule\Controller\Delegator\CreateItemDelegatorFactory', 
      'MyModule\Controller\Delegator\ReadItemDelegatorFactory' 
     ), 
    ), 
), 

delegators erklärt: http://ocramius.github.io/blog/zend-framework-2-delegator-factories-explained/

Edit:

Controller für beide delegators vorbereitet (Erstellen und Lesen) würde wie folgt aussehen:

namespace MyModule\Controller; 

use Zend\Mvc\Controller\AbstractActionController; 
use Zend\View\Model\ViewModel; 

class CreateController extends AbstractActionController 
{ 
    /** 
    * Holds the Item object 
    * @var object \MyModule\Entity\Item 
    */ 
    private $item 

    /** 
    * Holds the form object 
    * @var mixed null|object 
    */ 
    private $form; 

    /** 
     * Item's details. It reads item by the `item_id` which is param set in route with same name 
     * @return \Zend\View\Model\ViewModel 
     */ 
    public function readAction() 
    { 
     $v = new ViewModel(); 
     // set item, access it in template as `$this->item` 
     $v->setVariable('item',$this->getItem()); 

     return $v; 
    } 

    /** 
     * The Form preconfigured with CreateItemDelegatorFactory should be av. in template as `$this->form` 
     * @return \Zend\View\Model\ViewModel 
     */ 
    public function createAction() 
    { 
     $v = new ViewModel(); 
     // set form, access the in template as `$this->form` 
     $v->setVariable('form',$this->getForm()); 

     return $v; 
    } 

    /** 
    * Sets the Item object 
    * @var $item \MyModule\Entity\Item 
    * @return $this 
    */ 
    public function setItem($item=null) 
    { 
     $this->item = $item; 
     return $this; 
    } 

    /** 
    * Gets the Item object 
    * @return object \MyModule\Entity\Item 
    */ 
    public function getItem() 
    { 
     return $this->item; 
    } 

    public function setForm($form=null) 
    { 
     $this->form = $form; 
     return $this; 
    } 

    /** 
     * Returns form defined in config and CreateItemDelegatorFactory::form_name 
     * @return \Zend\Form\Form 
     */ 
    public function getForm() 
    { 
     return $this->form; 
    } 
} 
+0

danke. Könnten Sie ein Beispiel dafür geben, wie der Code im Controller aussehen würde? d.h. 'Controller :: action() {....}'? Dieser Teil war mir unklar – Dennis

0

Beobachtung

Einzelne Werte wie $description, $quantity, $price müssen irgendwo herkommen. Es könnte GET, POST, SESSION, COOKIES oder Datenbank oder externe Methoden sein. Nennen wir es aus Gründen der Klarheit $_SOMEWHERE. Wir erhalten dann:

$description = $_SOMEWHERE['description']; 
$quantity = $_SOMEWHERE['quantity']; 
$price = $_SOMEWHERE['price']; 

Definieren Sie eine Eingabe & Vorbereitung Klasse, die die Arbeit für Sie und gibt den vorbereiteten Item.

class AcquireItem 
{ 
    function getItem() 
    { 
     $item = new Item(); 

     $item->setDescription($_SOMEWHERE['description']); 
     $item->setQuantity($_SOMEWHERE['quantity']); 
     $item->setPrice($_SOMEWHERE['price']); 

     return $item; 
    } 
} 

Regler

$item = (new AcquireItem())->getItem(); 
$this->repository->saveItem($item); 

Regler kürzer werden, durch effektiven "Stuffing away" den sperrigen Clutter-Code in eine Klasse, die mit dem Lesen und die Vorbereitung Eingang betrifft, und die Steuerung decluttering. Der Code muss irgendwo existieren, aber auch außerhalb und auch anderswo.

Für verschiedene Arten von Item können Sie die Methode variieren, d. H. getItemA(), getItemB().

0

Ich persönlich glaube, dass Create-Methoden in das Repository gehen sollten. Das ist, weil ich erwarten würde, dass die Repositorys alle CRUD-Methoden (create, read, update, delete) enthalten.

Es ist nur mein persönlicher Gedanke zu diesem Thema ...