如何使用symfony 2.3调用订阅者中的实体管理器类?

时间:2014-09-18 07:12:40

标签: symfony

我想在Event Subscriber中调用repository类功能。有3个表



country : id, name, abbr, is_active
city : id, cityname, is_active
countrycity : id,countryid, cityid.

我应该在管理面板中提供管理城市,其中管理员可以为该国家/地区添加自己的城市。

对于一个应用程序,我创建了一个commonBundle,其中所有公共实体都驻留在管理面板和管理面板中。前端。


表格:D:\ wamp \ www \ cl \ src \ Cl \ CommonBundle \ Form \ CityType.php


namespace Cl\CommonBundle\Form;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    use Symfony\Component\Validator\Constraints;
    use Doctrine\ORM\EntityManager;
    class CityType extends AbstractType
    {
        /**
         * @param FormBuilderInterface $builder
         * @param array $options
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                    ->add("country", "entity", array("class" => "ClCommonBundle:Country", "property" => "countryname", "empty_value" => "-- Select Country --", "required" => false, "constraints" => new Constraints\NotBlank(array("message" => "Country should not be empty"))))
                    ->add("cityname", "text", array("label" => "Name", "required" => false))
                    ->add("isactive", "checkbox", array("required" => false, "label" => "Is active?", "mapped" => true))

            //->add('createdat')
            //->add('updatedat')
            ;
            $builder->addEventSubscriber(new EventListner\ValidateCountryCitySubscriber());

            /* $builder->addValidator(new CallbackValidator(function(FormInterface $form) {
              $country = $form->get("country")->getData();
              if (!$country) {
              $form['country']->addError(new FormError("Country should not be emtpy"));
              }
              }
              )); */
        }

        /**
         * @param OptionsResolverInterface $resolver
         */
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                // "data_class" => "Cl\CommonBundle\Entity\City",
                "csrf_token" => true,
                "csrf_token_name" => "_token",
                "method" => "POST",
                // to generate unique key token per form
                "intention" => "city",
                "country" => true,
                "mapped" => false,
                'allowExtraFields' => true
                    // validation group
                    //"validation_groups" => false,
            ));
        }

        /**
         * @return string
         */
        public function getName()
        {
            return 'Cl_commonbundle_city';
        }

    }

如果该国家/地区的城市名已存在,我会创建事件列表器功能来调用错误。

$builder->addEventSubscriber(new EventListner\ValidateCountryCitySubscriber());
    The code of event listiner is following.

EventListner:D:\ wamp \ www \ Cl \ src \ Cl \ CommonBundle \ Form \ EventListner \ ValidateCountryCitySubscriber.php


namespace Cl\CommonBundle\Form\EventListner;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormError;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\ManagerRegistry;

class ValidateCountryCitySubscriber implements EventSubscriberInterface
{
    private $em;
    /**
     * @param EntityManager
     */
    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }
    public static function getSubscribedEvents()
    {
        return [FormEvents::POST_SUBMIT => 'postSubmit'];
    }
    public function postSubmit(FormEvent $event)
    {
        $data = $event->getData();
        $form = $event->getForm();
        $country = $event->getForm()->getData()->country->getId();
        $cityname = $data->getCityname();
        $this->em->getRepository("CommonBundle:CountryCity")->validateCountryCity($country, $city);
        //$form->addError(new FormError("City is already exists for this country"));
    }
}

在D:\ wamp \ www \ Cl \ app \ config \ config.yml

中创建服务
doctrine.listner:
class: Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber
arguments:
    - @doctrine.orm.entity_manager

::错误::


糟糕,看起来出了问题。

1/1 ContextErrorException: Catchable Fatal Error: Argument 1 passed to Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber::__construct() must be an instance of Cl\CommonBundle\Form\EventListner\EntityManager, none given, called in D:\wamp\www\Cl\src\Cl\CommonBundle\Form\CityType.php on line 27 and defined in D:\wamp\www\Cl\src\Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber.php line 20
in D:\wamp\www\Cl\src\Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber.php line 20
at ErrorHandler->handle('4096', 'Argument 1 passed to Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber::__construct() must be an instance of Cl\CommonBundle\Form\EventListner\EntityManager, none given, called in D:\wamp\www\Cl\src\Cl\CommonBundle\Form\CityType.php on line 27 and defined', 'D:\wamp\www\Cl\src\Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber.php', '20', array()) in D:\wamp\www\Cl\src\Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber.php line 20
at ValidateCountryCitySubscriber->__construct() in D:\wamp\www\Cl\src\Cl\CommonBundle\Form\CityType.php line 27
at CityType->buildForm(object(FormBuilder), array('block_name' => null, 'disabled' => false, 'label' => null, 'attr' => array(), 'translation_domain' => null, 'auto_initialize' => true, 'data_class' => 'Cl\CommonBundle\Entity\City', 'empty_data' => object(Closure), 'trim' => true, 'required' => true, 'read_only' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, 'mapped' => false, 'by_reference' => true, 'error_bubbling' => true, 'label_attr' => array(), 'virtual' => null, 'inherit_data' => false, 'compound' => true, 'method' => 'POST', 'validation_groups' => null, 'error_mapping' => array(), 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'extra_fields_message' => 'This form should not contain extra fields.', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', 'csrf_protection' => true, 'csrf_field_name' => '_token', 'csrf_provider' => object(SessionCsrfProvider), 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'intention' => 'city', 'csrf_token' => true, 'csrf_token_name' => '_token', 'country' => true, 'allowExtraFields' => true, 'action' => '/Cl/web/app_dev.php/admin/city/insert', 'data' => object(City))) in D:\wamp\www\Cl\vendor\symfony\symfony\src\Symfony\Component\Form\ResolvedFormType.php line 158
at ResolvedFormType->buildForm(object(FormBuilder), array('block_name' => null, 'disabled' => false, 'label' => null, 'attr' => array(), 'translation_domain' => null, 'auto_initialize' => true, 'data_class' => 'Cl\CommonBundle\Entity\City', 'empty_data' => object(Closure), 'trim' => true, 'required' => true, 'read_only' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, 'mapped' => false, 'by_reference' => true, 'error_bubbling' => true, 'label_attr' => array(), 'virtual' => null, 'inherit_data' => false, 'compound' => true, 'method' => 'POST', 'validation_groups' => null, 'error_mapping' => array(), 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'extra_fields_message' => 'This form should not contain extra fields.', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', 'csrf_protection' => true, 'csrf_field_name' => '_token', 'csrf_provider' => object(SessionCsrfProvider), 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'intention' => 'city', 'csrf_token' => true, 'csrf_token_name' => '_token', 'country' => true, 'allowExtraFields' => true, 'action' => '/Cl/web/app_dev.php/admin/city/insert', 'data' => object(City))) in D:\wamp\www\Cl\vendor\symfony\symfony\src\Symfony\Component\Form\ResolvedFormType.php line 117
at ResolvedFormType->createBuilder(object(FormFactory), 'Cl_commonbundle_city', array('action' => '/Cl/web/app_dev.php/admin/city/insert', 'data' => object(City))) in D:\wamp\www\Cl\vendor\symfony\symfony\src\Symfony\Component\Form\FormFactory.php line 87
at FormFactory->createNamedBuilder('Cl_commonbundle_city', object(CityType), object(City), array('action' => '/Cl/web/app_dev.php/admin/city/insert')) in D:\wamp\www\Cl\vendor\symfony\symfony\src\Symfony\Component\Form\FormFactory.php line 67
at FormFactory->createBuilder(object(CityType), object(City), array('action' => '/Cl/web/app_dev.php/admin/city/insert')) in D:\wamp\www\Cl\vendor\symfony\symfony\src\Symfony\Component\Form\FormFactory.php line 39
at FormFactory->create(object(CityType), object(City), array('action' => '/Cl/web/app_dev.php/admin/city/insert')) in D:\wamp\www\Cl\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Controller\Controller.php line 163
at Controller->createForm(object(CityType), object(City), array('action' => '/Cl/web/app_dev.php/admin/city/insert')) in D:\wamp\www\Cl\src\Cl\AdminBundle\Controller\CityController.php line 19
at CityController->__processForm(array('entity' => object(City), 'path' => '_admin_city_insert', 'button_label' => 'Add')) in D:\wamp\www\Cl\src\Cl\AdminBundle\Controller\CityController.php line 38
at CityController->addAction(object(Request))
at call_user_func_array(array(object(CityController), 'addAction'), array(object(Request))) in D:\wamp\www\Cl\app\bootstrap.php.cache line 2889
at HttpKernel->handleRaw(object(Request), '1') in D:\wamp\www\Cl\app\bootstrap.php.cache line 2863
at HttpKernel->handle(object(Request), '1', true) in D:\wamp\www\Cl\app\bootstrap.php.cache line 2992
at ContainerAwareHttpKernel->handle(object(Request), '1', true) in D:\wamp\www\Cl\app\bootstrap.php.cache line 2272
at Kernel->handle(object(Request)) in D:\wamp\www\Cl\web\app_dev.php line 28

2 个答案:

答案 0 :(得分:0)

您没有指定EntityManager从哪个命名空间。

只需在您的订阅者中添加use Doctrine\ORM\EntityManager;

namespace Cl\CommonBundle\Form\EventListner;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormError;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\ManagerRegistry;
use Doctrine\ORM\EntityManager; // this was lacking

class ValidateCountryCitySubscriber implements EventSubscriberInterface
{

修改

好的,我现在看到问题所在。

您已将订阅者创建为服务,但在类型类中,您不将其用作服务,而是自己创建新对象。这是一个错误,你应该使用容器来管理依赖关系。请尝试以下方式:

  1. CityType定义为服务
  2. 将订阅者注入CityType并使用此注入对象
  3. 编辑2:

    问题在于这一行:

    $builder->addEventSubscriber(new EventListner\ValidateCountryCitySubscriber());
    

    您创建了新的订阅者对象,但从未传递过EntityManager依赖关系。但您已将订户定义为服务:doctrine.listner。因此,您唯一需要做的就是将其注入CityType类。

    为此,您需要将CityType定义为服务:

    form.type.city:
        class: Cl\CommonBundle\Form\CityType
        arguments: [ @doctrine.listner ]
        tags:
            - { name: form.type, alias: city_type }
    

    当然你需要稍微修改CityType(创建你注入ValidateCountryCitySubscriber类和$doctrineListener属性的构造函数):

    protected $doctrineListener
    
    public function __construct(ValidateCountryCitySubscriber $doctrineListener)
    {
        $this->doctrineListener = $doctrineListener;
    }
    

    然后在类型类中,以这种方式添加订阅者:

    $builder->addEventSubscriber($this->doctrineListener);
    

答案 1 :(得分:0)

两个错误:

1 - 正如Cyprian所述,您应该让ValidateCountryCitySubscriber知道在哪里找到EntityManager

所以use Doctrine\ORM\EntityManager必须在ValidateCountryCitySubscriber

中包含在您的使用定义中

2 - 您应该将config.yml修改为

doctrine.listner:
    class: Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber
    arguments: [ @doctrine.orm.entity_manager ] 

<击>

你的语法似乎还不错

修改

您的FormType也存在问题:您不应该直接设置服务(并且您的ValidateCountryCitySubscriber是)。 因此,您可以通过这种方式修改config.yml

yourbundle.citytype:
    class: Cl\CommonBundle\Form\CityType
    arguments: [ @doctrine.listner ]
    tags:
        - { name: form.type, alias: Cl_commonbundle_city }

您正在将doctrine.listner服务注入表单(现在也是服务)。

修改CityType

use Cl\CommonBundle\Form\EventListner\ValidateCountryCitySubscriber.php;
class CityType extends AbstractType
{
    private $vccs; //validate country city subscriber

    public function __construct(ValidateCountryCitySubscriber $validate_country_city_sub)
    {
        $this->vccs = $validate_country_city_sub;
    }  

    [...]

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        [...]
        $builder->addEventSubscriber($this->vccs);
    }

}