【问题标题】:ZF2 - How to add a new Form in an existing Controller?ZF2 - 如何在现有控制器中添加新表单?
【发布时间】:2015-06-28 20:45:24
【问题描述】:

我有一个登录表单LoginForm.php 及其过滤器LoginFilter.php,它有一个视图/login/index.phtml,一个控制器LoginController.php,两个工厂LoginControllerFactory.phpLoginFormFactory.php,它在config.module.php 中被调用并且工作完美。表单已正确显示。

我有一个ViewController.php,它有一个idAction 方法,它通过id 在名为/view/id.phtml 的视图中通过参数从主页传递来显示帖子。我想显示我在这个视图中创建的这个表单,但我不知道如何。首先,我完全按照创建登录表单的方式创建了表单,但我意识到我已经在view 路由内部配置了id 子路由,并在module.config.php 中使用了工厂。

然后,我尝试在idAction 方法中设置表单,就像我在LoginController.php 控制器中的indexAction 中所做的那样,但我收到以下错误:An exception was raised while creating "Rxe\Factory\ViewController"; no instance returned

我现在将向您展示我为显示这个新表单所做的工作。

首先,表单本身:

class CommentForm extends Form
{
    public function buildForm()
    {
        $this->setAttribute('method', 'POST');
        $this->setAttribute('id', 'add-comment-form');
        $this->add(array(
            'name' => 'comment',
            'type' => 'textarea',
            'options' => array(
                'label' => 'Category'
            ),
            'attributes' => array(
                'class' => 'form-control'
            )
        ));

        $this->add(array(
            'name' => 'submit',
            'type' => 'submit',
            'attributes' => array(
                'class' => 'btn btn-success',
                'value' => 'Comment'
            )
        ));
    }
}

Form 的 CommentFormFactory.php 调用其过滤器并构建表单:

class CommentFormFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $form = new CommentForm();
        $form->setInputFilter($serviceLocator->get('Rxe\Factory\CommentFilter'));
        $form->buildForm();

        return $form;
    }
}

ViewControllerFactory.php 调用CommentFormFactory.php,就像在LoginControllerFactory.php 中一样:

class ViewControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $serviceManager = $serviceLocator->getServiceLocator();

        $viewController = new ViewController();
        $viewController->setPostsTable($serviceManager->get('Rxe\Factory\PostsTable'));
        $viewController->setCommentsTable($serviceManager->get('Rxe\Factory\CommentsTable'));
        $viewController->setCommentForm($serviceManager->get('Rxe\Factory\CommentForm'));

        return $viewController;
    }
}

ViewController.php,在其idActionViewModel 中调用表单:

class ViewController extends AbstractActionController
{
    use PostsTableTrait;
    use CommentsTableTrait;

    private $commentForm;

    function setCommentForm($commentForm)
    {
        $this->commentForm = $commentForm;
    }

    public function indexAction()
    {
        $category = $this->params()->fromRoute('category');

        return new ViewModel(array(
            'posts' => $this->postsTable->getPostsByCategory($category),
            'categories' => $category
        ));
    }

    public function idAction()
    {
        $id = $this->params()->fromRoute('id');

        $viewModel = new ViewModel(array(
            'commentForm' => $this->commentForm,
            'commentParams' => $this->params()->fromPost(),
            'messages' => $this->flashMessenger()->getMessages(),
            'posts' => $this->postsTable->getPostById($id),
            'posts' => $this->commentsTable->getNumberOfCommentsByPost($id),
            'comments' => $this->commentsTable->getCommentsByPost($id)
        ));
        $viewModel->setTemplate('rxe/view/id.phtml');

        if ($this->getRequest()->isPost()) {
            $this->commentForm->setData($this->params()->fromPost());

            if ($this->commentForm->isValid()) {
                $this->flashMessenger()->addMessage('Thank you for your comment. :)');
            } else {
                $this->flashMessenger()->addMessage('Your comment wasn\'t sent.');
            }
        }

        return $viewModel;
    }
}

最后是我的module.config.php

'controllers' => array(
    'invokables' => array(
        'Rxe\Controller\Index' => 'Rxe\Controller\IndexController',
        'Rxe\Controller\View' => 'Rxe\Controller\ViewController',
        'Rxe\Controller\Login' => 'Rxe\Controller\LoginController'
    ),
    'factories' => array(
        'Rxe\Factory\LoginController' => 'Rxe\Factory\LoginControllerFactory',
        'Rxe\Factory\ViewController' => 'Rxe\Factory\ViewControllerFactory',
        'Rxe\Factory\IndexController' => 'Rxe\Factory\IndexControllerFactory'
    )
),
'service_manager' => array(
    'factories' => array(
        'Rxe\Factory\LoginForm' => 'Rxe\Factory\LoginFormFactory',
        'Rxe\Factory\LoginFilter' => 'Rxe\Factory\LoginFilterFactory',
        'Rxe\Factory\CommentForm' => 'Rxe\Factory\CommentFormFactory',
        'Rxe\Factory\CommentFilter' => 'Rxe\Factory\CommentFilterFactory',
        'Rxe\Factory\PostsTable' => 'Rxe\Factory\PostsTableFactory',
        'Rxe\Factory\CategoriesTable' => 'Rxe\Factory\CategoriesTableFactory',
        'Rxe\Factory\CommentsTable' => 'Rxe\Factory\CommentsTableFactory',
        'Zend\Db\Adapter\AdapterService' => 'Zend\Db\Adapter\AdapterServiceFactory'
    )
),

如果您需要我向您展示更多代码,请告诉我。提前谢谢你。

编辑#1

如果我删除ViewControllerFactory.php 中调用表单的行,我会收到以下错误:Fatal error: Call to a member function prepare() on a non-object in /home/vol12_3/byethost4.com/b4_16354889/htdocs/module/Rxe/view/rxe/view/id.phtml on line 31

id.phtml 是:

<!-- Comment form -->
<div id="comment-form-area" class="col-xs-3">
    <?php $this->commentForm->prepare() ?>
    <?php echo $this->form()->openTag($this->commentForm); ?>
    <div class="form-group comment-area">
        <?php echo $this->formRow($this->commentForm->get('comment_content')); ?>
    </div>
    <div class="form-group">
        <?php echo $this->formRow($this->commentForm->get('submit')); ?>
    </div>
    <?php echo $this->form()->closeTag(); ?>
</div>
<!-- /Comment form -->

【问题讨论】:

    标签: php forms controller zend-framework2


    【解决方案1】:

    尝试删除这些行

    'invokables' => array(
        'Rxe\Controller\Index' => 'Rxe\Controller\IndexController',
        'Rxe\Controller\View' => 'Rxe\Controller\ViewController',
        'Rxe\Controller\Login' => 'Rxe\Controller\LoginController'
    ),
    

    如果它不起作用,请查看本教程如何创建适当的控制器工厂并传递依赖项。 https://samsonasik.wordpress.com/2015/03/31/zend-framework-2-using-__invokepluginmanager-manager-in-services-factory/

    我如何构建表单的示例:

    namespace Admin\Form;
    
    use Zend\Form\Form;
    use Zend\InputFilter\InputFilterProviderInterface;
    
    class ContentForm extends Form implements InputFilterProviderInterface
    {
        public function __construct()
        {
            parent::__construct("content");
        }
    
        public function init()
        {
            $this->setAttribute('method', 'post');
    
            $this->add([
                'type' => 'Zend\Form\Element\Text',
                'name' => 'title',
                'attributes' => [
                    'required'   => true,
                    'size'        => 40,
                    'id'         => "seo-caption",
                    'placeholder' => 'Title',
                ],
                'options' => [
                    'label' => 'Title',
                ],
            ]);
    
            $this->add([
                'type' => 'Zend\Form\Element\Text',
                'name' => 'text',
                'attributes' => [
                    'class'   => 'ckeditor',
                    'rows'        => 5,
                    'cols'      => 80,
                ],
                'options' => [
                    'label' => 'Text',
                ],
            ]);
    
        }
    
        public function getInputFilterSpecification()
        {
            return [
                [
                    "name"=>"title",
                    "required" => true,
                    'filters' => [
                        ['name' => 'StripTags'],
                        ['name' => 'StringTrim'],
                    ],
                    'validators' => [
                        ['name' => 'NotEmpty'],
                        [
                            'name'    => 'StringLength',
                            'options' => [
                                'encoding' => 'UTF-8',
                                'min' => 1,
                                'max' => 200,
                            ],
                        ],
                    ],
                ],
                [
                    "name"=>"text",
                    "required" => true,
                    'filters' => [
                        ['name' => 'StripTags'],
                        ['name' => 'StringTrim'],
                    ],
                    'validators' => [
                        ['name' => 'NotEmpty'],
                        [
                            'name'    => 'StringLength',
                            'options' => [
                                'encoding' => 'UTF-8',
                                'min' => 1,
                            ],
                        ],
                    ],
                ],
            ];
        }
    }
    

    比我创建一个工厂 命名空间管理员\工厂\控制器;

    use Admin\Controller\ContentController;
    use Zend\Mvc\Controller\ControllerManager;
    
    class ContentFormFactory
    {
        /**
         * @{inheritDoc}
         */
        public function __invoke(ControllerManager $controllerManager)
        {
            return new ContentController(
                $controllerManager->getServiceLocator()->get('FormElementManager')->get('Admin\Form\ContentForm')
            );
        }
    }
    

    在 module.config.php 里面我有这段代码

    'controllers' => [
        'factories' => [
            'Admin\Controller\Content' => "Admin\Factory\Controller\ContentFormFactory",
        ],
        'invokables' => [
            ...
        ],
    ],
    

    请给我们看更多代码。

    【讨论】:

    • 创建一个表单不是问题,而是如何在现有控制器中调用它,比如我的ViewController.php 已经有其他东西,而不是为表单创建一个单独的。
    • 我将我的id.phtml 部分放在我调用要显示的表单的位置,如果我在ViewControllerFactory.php 中删除调用我的表单的行,则会出现错误
    • 我真的不认为您创建表单的方式是正确的。请参阅文档framework.zend.com/manual/current/en/user-guide/…,因为据我所知,您的表单没有返回实例,这就是您收到第一个错误的原因。
    • 嗯,我为登录所做的方式非常有效,但它有自己的控制器和控制器工厂。我想发表的评论我不知道如何处理它们,因为我想从现有的控制器(即视图)中调用它。我真的需要控制器吗?我在哪里以及如何称呼它?那是我的问题。
    • 为 CommentForm 创建一个工厂,并通过 Controller 构造函数方法传递它。之后在你的 module.config.php 文件中将控制器移动到工厂数组中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-28
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多