简体   繁体   English

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

[英]How to call entity manager class in subscriber using symfony 2.3?

I want to call repository class function in Event Subscriber. 我想在事件订阅服务器中调用存储库类函数。 There are 3 tables 3张桌子


Tables : 桌子


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

I should provide manage city in admin panel where admin can add their own city for that country. 我应该在管理面板中提供管理城市,管理员可以在该国家/地区中添加自己的城市。

For an application I have create a commonBundle in which all common entities reside which will use in both admin panel & frontend. 对于一个应用程序,我创建了一个commonBundle,所有公共实体都驻留在其中,并将在管理面板和前端中使用。


Form : D:\\wamp\\www\\cl\\src\\Cl\\CommonBundle\\Form\\CityType.php 格式: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';
        }

    }

I create function of event listner to call an error if the cityname is already exist for that country. 我创建了事件列表器功能,以在该国家/地区已经存在城市名称时调用错误。

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

EventListner : D:\\wamp\\www\\Cl\\src\\Cl\\CommonBundle\\Form\\EventListner\\ValidateCountryCitySubscriber.php 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"));
    }
}

Service create in D:\\wamp\\www\\Cl\\app\\config\\config.yml 在D:\\ wamp \\ www \\ Cl \\ app \\ config \\ config.yml中创建服务


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

:: Error :: ::错误::


Whoops, looks like something went wrong. 哎呀,看起来像出事了。

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

You didn't specify from which namespace EntityManager is. 您没有指定EntityManager来自哪个名称空间。

So just add use Doctrine\\ORM\\EntityManager; 因此,只需添加use Doctrine\\ORM\\EntityManager; in your subscriber: 在您的订户中:

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
{

EDIT: 编辑:

Ok, I see now where the problem is. 好的,我现在知道问题出在哪里。

You created the subscriber as a service but in type class you don't use it as a service, but instead you created new object by yourself. 您将订户创建为服务,但是在类型类中,您并未将其用作服务,而是自己创建了新对象。 This is a mistake, you should use container for managaing dependencies. 这是一个错误,您应该使用容器来管理依赖项。 Try the following way: 请尝试以下方式:

  1. Define CityType as a service CityType定义为服务
  2. Inject subscriber into CityType and use this injected object 将订户注入CityType并使用此注入的对象

EDIT 2: 编辑2:

The problem is because of this line: 问题是由于此行:

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

You created new subscriber object but never passed EntityManager dependency. 您创建了新的订阅者对象,但从未传递EntityManager依赖项。 But you already have your subscriber defined as a service: doctrine.listner . 但是您已经将订户定义为服务: doctrine.listner So, the only thing you have to do is to inject it inside CityType class. 因此,您唯一要做的就是将其注入CityType类中。

In order to do that, you need define CityType as a service: 为此,您需要将CityType定义为服务:

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

Of course you need to modify CityType a little (create constructor where you inject your ValidateCountryCitySubscriber class and $doctrineListener property): 当然,您需要稍微修改CityType (创建构造函数,在其中注入ValidateCountryCitySubscriber类和$doctrineListener属性):

protected $doctrineListener

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

And then inside the type class you add the subscriber in that way: 然后在类型类内部,以这种方式添加订户:

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

Two errors: 两个错误:

1 - As Cyprian said, you should let ValidateCountryCitySubscriber know where to find EntityManager 1-正如Cyprian所说,您应该让ValidateCountryCitySubscriber知道在哪里可以找到EntityManager

so use Doctrine\\ORM\\EntityManager have to be included into your use definitions into ValidateCountryCitySubscriber class 因此必须use Doctrine\\ORM\\EntityManager包含在ValidateCountryCitySubscriber类的使用定义中

2 - You should modify your config.yml into 2-您应该将 config.yml修改为

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

Also your syntax seems to be fine 另外你的语法似乎很好

Edit 编辑

Problem is also into your FormType : you shouldn't instatiate direclty a service (and your ValidateCountryCitySubscriber is). 问题也出现在您的FormType :您不应使服务的身份无效(而ValidateCountryCitySubscriber就是)。 So you can modify your config.yml that way 因此您可以通过这种方式修改config.yml

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

You are injecting your doctrine.listner service into the form (that now is a service too). 您正在将doctrine.listner服务注入到表单中(现在也是一种服务)。

Than modify CityType 比修改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);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM