【问题标题】:changing ZF2 form behavior when retrieving form检索表单时更改 ZF2 表单行为
【发布时间】:2015-07-31 15:49:26
【问题描述】:

我想知道是否有一种方法可以将附加参数传递给构造函数(首选)或检索 Request 对象以从 Form 构造函数中检查标头,以便当我在控制器中执行 getForm 时,表单会根据调用方式来定制吗?

我正在努力将 AngularJs 绑定和模型标签集成到我的表单元素中,但我需要修改提交按钮的工作方式,无论何时从 Ajax 调用表单而不是通过框架将表单拉入 Zend 模板。

因此,我想在提交按钮添加到表单的位置周围抛出条件参数,但我需要知道呈现的表单是在 zend 中查看还是通过 ajax 调用发送。我可以通过使用 isXmlHttpRequest() 查看请求标头来检测控制器中的 ajax 调用,但我不确定如何让表单知道控制器在使用 $this->getForm()

【问题讨论】:

    标签: angularjs zend-framework2 xmlhttprequest zend-form2


    【解决方案1】:

    我的带有辅助函数的 AbstractForm(我刚刚将 getRequest() 添加到底部)。当然,在更广泛的应用程序中,我可能会添加错误检查以确保不会从构造函数调用这些(当服务管理器尚不可用时)

    namespace Application\Form;
    
    use Zend\Form\Form as ZendForm;
    use Zend\Http\Request as HttpRequest;
    use Zend\Stdlib\RequestInterface as Request;
    use Zend\Form\FormElementManager as ZendFormElementManager;
    use Zend\ServiceManager\ServiceLocatorAwareInterface as ZendServiceLocatorAwareInterface;
    use Zend\ServiceManager\ServiceLocatorInterface      as ZendServiceLocatorInterface;
    use Doctrine\ORM\EntityManager as DoctrineEntityManager
    
    class AbstractForm extends ZendForm implements ZendServiceLocatorAwareInterface {
    
        /**
         * @var Request
         */
        protected $request;
    
        /**
         * in form context this turns out to be Zend\Form\FormElementManager
         *
         * @var ZendFormElementManager $service_manager
         */
        protected static $service_manager;
    
        /**
         * @var DoctrineEntityManager $entity_manager
         */
        protected $entity_manager;
    
        /**
         * @var ZendServiceLocatorInterface $service_locator_interface
         */
        protected $service_locator_interface;
    
        public function __construct($name = null)
        {
            parent::__construct($name);
        }
    
        /**
         * in form context this turns out to be Zend\Form\FormElementManager
         *
         * @param ZendFormElementManager $serviceLocator
         */
        public function setServiceLocator(FormElementManager $serviceLocator)
        {
            self::$service_manager = $serviceLocator;
        }
    
        /**
         * in form context this turns out to be Zend\Form\FormElementManager
         *
         * @return ZendFormElementManager
         */
        public function getServiceLocator()
        {
            return self::$service_manager;
        }
    
        /**
         * wrapper for getServiceLocator
         * @return ZendFormElementManager
         */
        protected function getFormElementManager() {
            return $this->getServiceLocator();
        }
    
        /**
         * this returns an actual service aware interface
         *
         * @return ZendServiceLocatorInterface
         */
        protected function getServiceManager() {
            if(!($this->service_locator_interface instanceof ZendServiceLocatorInterface)) {
                $this->service_locator_interface = $this->getFormElementManager()->getServiceLocator();
            }
            return $this->service_locator_interface;
        }
    
        /**
         * @return DoctrineEntityManager
         */
        protected function getEntityManager() {
            if(!($this->entity_manager instanceof \DoctrineEntityManager)) {
                $this->entity_manager = $this->getServiceLocator()->getServiceLocator()->get('Doctrine\ORM\EntityManager');
            }
            return $this->entity_manager;
        }
    
        /**
         * Get request object
         *
         * @return Request
         */
        public function getRequest()
        {
            if (!$this->request) {
                $this->request = $this->getServiceManager()->get('Request');
            }
    
            return $this->request;
        }
    }
    

    【讨论】:

    • 是的,我知道静态变量令人困惑,因为服务管理器的函数返回服务定位器的值,反之亦然 - 我以后可能会更改。
    【解决方案2】:

    您可以使用工厂类注入任何您喜欢的选项。

    use MyModule\Form\MyForm;
    use Zend\ServiceManager\ServiceLocatorInterface;
    use Zend\ServiceManager\FactoryInterface;
    
    class MyFormFactory implements FactoryInterface
    {
        public function createService(ServiceLocatorInterface $formElementManager)
        {
            $serviceManager = $formElementManager->getServiceLocator();
            $request = $serviceManager->get('Request');
    
            // I would recommend assigning the data
            // from the request to the options array
            $options = [
                'is_ajax' => $request->isXmlHttpRequest(),
            ];
    
            // Although you could also pass in the request instance into the form
            return new MyForm('my_form', $options, $request);
        }
    }
    

    如果你注入请求,你需要修改MyForm::__construct

    namespace MyModule\Form;
    
    use Zend\Form\Form;
    use Zend\Http\Request as HttpRequest;
    
    class MyForm extends Form
    {
        protected $request;
    
        public function __construct($name, $options, HttpRequest $request)
        {
            $this->request = $request;
    
            parent::__construct($name, $options);
        }
    }
    

    更新您的module.config.php 以使用工厂

    return [
        'form_elements' => [
            'factories' => [
                'MyModule\Form\MyForm' => 'MyModule\Form\MyFormFactory'
            ]
        ]
    ]
    

    然后确保您向服务经理请求表单(在控制器工厂中)

    $myForm = $serviceManager->get('FormElementManager')->get('MyModule\Form\MyForm');
    

    【讨论】:

    • 好的,很酷,谢谢。仍然在工厂周围环绕我的大脑 - 你可以覆盖或抽象一个 getForm 方法以在所有检索到的表单上注入类似的基本选项吗?比如getTailoredForm?
    • 另外,我记得虽然 $this->getServiceManager 在表单中返回 formManager,但 formManager 的 getServiceManager 返回标准服务定位器,所以我也可以在上下文中根据需要获取值(在构造函数完成后)
    • @Scott 如果您的每个表单都具有相似的依赖关系,您当然可以扩展工厂和/或创建为每个表单扩展的抽象类。理想情况下,要在控制器中获取表单,您应该创建一个 MyControllerFactory,然后将表单注入控制器(就像在我的示例中注入 Request 一样)。
    猜你喜欢
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2017-10-03
    • 2019-08-29
    • 1970-01-01
    • 2011-10-04
    • 2013-09-25
    • 1970-01-01
    相关资源
    最近更新 更多