Symfony2的表單事件 FormEventSubscriber

mot發表於2014-05-02

Form事件是動態處理表單動作的一種方式,在buildForm方法裡新增Subscriber:

<?php

namespace DemoAdminBundleFormType;

use SymfonyComponentFormFormBuilderInterface;
use FOSUserBundleFormTypeRegistrationFormType as BaseType;

class RegistrationFormType extends BaseType
{

    private $doctrine;

    public function __construct( $class ,  DoctrineBundleDoctrineBundleRegistry $doctrine)
    {
        parent::__construct( $class);
        $this->doctrine = $doctrine;
    }

    public function buildForm( FormBuilderInterface $builder , array $option )
    {
        parent::buildForm($builder, $option);

        $builder->add(`name`)
                ;
        //這裡傳遞FormFactory到監聽器裡 用來修改表單
        $subscriber = new McAdminBundleEventListenerFormSetDataListener($builder->getFormFactory());
        //新增subscriber
        $builder->addEventSubscriber( $subscriber);

    }
   ...

然後寫一下Subscriber :

<?php
namespace DemoAdminBundleEventListener;

use SymfonyComponentFormFormEvent;
use SymfonyComponentFormFormFactoryInterface;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
use SymfonyComponentFormFormEvents;


class FormSetDataListener implements EventSubscriberInterface
{

    private $factory;

    public function __construct( FormFactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    public static function getSubscribedEvents()
    {
        return array( FormEvents::POST_SET_DATA => `postSetData`);
    }

    public function postSetData( FormEvent $event )
    {   
        $form = $event->getForm();
        $data = $event->getData();

        if( null == $data)
        {
            return ;
        }
        //這裡我的操作是移除原先的密碼框 然後手動給它填充資料 data的資料是從另外一個表單傳遞到這個表單來的 (基於FOSUserBundle做的一個分步註冊的功能 俗稱form wizard) 這個資料來源直接在FormFactory獲取就好了 
        //這樣等於在這裡重建了一下form
        $form->remove(`plainPassword`);

        $form->add(`plainPassword`, `repeated`, array(
                `data` => $data->getPassword() , 
                `type` => `text`,
                `options` => array(`translation_domain` => `FOSUserBundle`),
                `first_options` => array(`label` => `form.password`),
                `second_options` => array(`label` => `form.password_confirmation`),
                `invalid_message` => `fos_user.password.mismatch`,
            )
        );

    }
}

到這裡一個form監聽事件就完成了
這裡的

    public static function getSubscribedEvents()
    {
        return array( FormEvents::POST_SET_DATA => `postSetData`);
    }

還有幾個事件 分別是form的不同時期 都是可以通過監聽來修改它的狀態:

<?php
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentForm;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class FormEvents
{

    const PRE_SUBMIT = `form.pre_bind`;

    const SUBMIT = `form.bind`;

    const POST_SUBMIT = `form.post_bind`;

    const PRE_SET_DATA = `form.pre_set_data`;

    const POST_SET_DATA = `form.post_set_data`;

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link PRE_SUBMIT} instead.
     */
    const PRE_BIND = `form.pre_bind`;

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link SUBMIT} instead.
     */
    const BIND = `form.bind`;

    /**
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link POST_SUBMIT} instead.
     */
    const POST_BIND = `form.post_bind`;

    private function __construct()
    {
    }
}

至於每個事件的先後順序 可以在form一系列的定義裡都可以看到。

相關文章