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;
}
}
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
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
Ich denke @Chris bedeutet, eine Item' ___ construct() 'Methode zu haben, um die Eigenschaften zu setzen und' $ item = new Item ($ description, $ quantity, $ price); ' – AbraCadaver