我想在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
答案 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
{
修改强>
好的,我现在看到问题所在。
您已将订阅者创建为服务,但在类型类中,您不将其用作服务,而是自己创建新对象。这是一个错误,你应该使用容器来管理依赖关系。请尝试以下方式:
CityType
定义为服务CityType
并使用此注入对象编辑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);
}
}