首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我在哪里放置我的冗长的代码,准备在存储库中保存域对象?

我在哪里放置我的冗长的代码,准备在存储库中保存域对象?
EN

Stack Overflow用户
提问于 2016-05-17 21:25:38
回答 3查看 78关注 0票数 0

我有这样的代码:

代码语言:javascript
复制
/* 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);

想象一下在一个函数/方法中有几个像上面这样的块,你就会看到我的问题.我对我的repository代码行非常满意,但我不知道在调用Repository之前应该把所有的“准备工作”放在哪里。

问题:

在哪里放置大量创建和填充Item对象实例的代码?它把我的控制器方法弄得乱七八糟,我似乎无法想象有别的地方可以把它放进去。

目标

我的目标是找到好的结构/设计,而不是单纯地减少或减少“项目准备”行的数量。

根据Controller,我有大约5-7个Item实例,每个实例有10-16行代码创建和填充实例。

EN

回答 3

Stack Overflow用户

发布于 2016-05-18 02:54:20

正如你所提到的,实现这一目标的正确途径。如何使用委托者并将控制器(块)分割成委托者?它的术语术语它将是外观适配器

在./module/MyModule/config/module.config.php中添加以下内容:

代码语言:javascript
复制
'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',
    ),
),

创建代理程序加载表单,填充它,验证并尝试保存teh数据

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

代码语言:javascript
复制
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);
            }
        }
    }
}

有了上面的代理程序,您的控制器(MyModule\ controller \MyController)将需要额外的属性和两个方法:

代码语言:javascript
复制
/**
 * 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:

代码语言:javascript
复制
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;
    }

有了上面的代理程序,您的控制器(MyModule\ controller \MyController)将需要额外的属性和方法:

代码语言:javascript
复制
/**
 * Holds the Item object
 * @var object \MyModule\Entity\Item
 */
private $item

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

这种控制器的使用方式有助于代码保持干燥,并且似乎可以控制流程。委托程序被加载为LIFO,因此在将控制器($callback)传递给另一个代理程序之前,有可能预先配置它。

如果ReadController读取项,而CreateController加载表单,则UpdateItemDelegator处理item Update任务的方式很短。

代码语言:javascript
复制
'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'
        ),
    ),
),

代表解释:http://ocramius.github.io/blog/zend-framework-2-delegator-factories-explained/

编辑:

为两个委派者(创建和读取)准备的控制器如下所示:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2016-05-18 15:26:06

观测

$description, $quantity, $price这样的单个值必须来自某个地方。它可以是GET、POST、SESSION、COOKIES或数据库或外部方法。为了清晰起见,我们将其命名为$_SOMEWHERE。然后我们得到:

代码语言:javascript
复制
$description = $_SOMEWHERE['description'];
$quantity = $_SOMEWHERE['quantity'];
$price = $_SOMEWHERE['price'];

定义一个用于为您工作并返回准备好的Item的输入和准备类。

代码语言:javascript
复制
class AcquireItem
{
    function getItem()
    {
        $item = new Item();

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

        return $item;
    }
}

控制器

代码语言:javascript
复制
$item = (new AcquireItem())->getItem();
$this->repository->saveItem($item);

控制器变得更短,有效地将庞大的杂波代码“填塞”到一个与读取和准备输入有关的类中,并将控制器解出。代码必须存在于某个地方,但也可能是不可见的,或者是其他地方。

对于不同类型的Item,可以更改方法,即getItemA()getItemB()

票数 0
EN

Stack Overflow用户

发布于 2016-07-08 04:37:10

我个人认为创建方法应该进入存储库。这是因为我希望存储库包含所有CRUD (创建、读取、更新、删除)方法。

这只是我对这个话题的个人想法..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37286497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档