gpt4 book ai didi

php - Symfony3 使用事件动态修改表单

转载 作者:可可西里 更新时间:2023-11-01 12:37:59 25 4
gpt4 key购买 nike

问题是市政领域没有加载任何东西,它是未定义的。在 AJAX 代码中,我很好地获得了省份的值(value)。但是在addMunicipioField.php类中没有取$province的值,一直为nul

enter image description here

我正在尝试制作一个注册表单,其中部分常用字段(姓名、昵称、密码...)我还添加了两个相关字段 Municipality

编解码 Controller :

class UserController extends Controller {

private $session;

public function __construct() {
$this->session = new Session();
}

public function registerAction(Request $request) {

if (is_object($this->getUser())) {
return $this->redirect('home');
}

$user = new DbUsuario();

$form = $this->createForm(RegistreUserType::class, $user);

$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery('SELECT u FROM BackendBundle:DbUsuario u WHERE u.email = :email OR u.nick = :nick')
->setParameter('email', $form->get("email")->getData())
->setParameter('nick', $form->get("nick")->getData());

$user_isset = $query->getResult();

if (count($user_isset) == 0) {
$factory = $this->get("security.encoder_factory");
$encoder = $factory->getEncoder($user);

$password = $encoder->encodePassword($form->get("password")->getData(), $user->getSalt());

$user->setPassword($password);
$user->setRole("ROLE_USER");
$user->setImagen(null);

$em->persist($user);
$flush = $em->flush();

if ($flush == null) {
$status = "Te has registrado correctamente";
$this->session->getFlashBag()->add("status", $status);
return $this->redirect("login");
} else {
$status = "No te has registrado correctamente";
}
} else {
$status = "Usuario ya esta registrado.";
}
} else {
$status = "No te has registrado correctamente.";
}
$this->session->getFlashBag()->add("status", $status);
}
return $this->render('AppBundle:User:register.html.twig', array(
"form" => $form->createView() # Genera el html del formulario.
));
}

创建表单的实体DbUsuario,它有idMunicipio字段。

/** @var \BackendBundle\Entity\DbMunicipios */
private $idMunicipio;

/**
* Set idMunicipio
* @param \BackendBundle\Entity\DbMunicipio $idMunicipio
* @return DbUsuario
*/
public function setIdMunicipio(\BackendBundle\Entity\DbMunicipio $idMunicipio = null) {
$this->idMunicipio = $idMunicipio;
return $this;
}

/**
* Get idMunicipio
* @return \BackendBundle\Entity\DbMunicipio
*/
public function getIdMunicipio() {
return $this->idMunicipio;
}

然后 DbMunicipioEntity 与“省”连接:

/** @var \BackendBundle\Entity\DbProvincia */
private $provincia;

/**@param \BackendBundle\Entity\DbProvincia $provincia
* @return DbMunicipio
*/
public function setProvincia(\BackendBundle\Entity\DbProvincia $provincia = null){
$this->provincia = $provincia;
return $this;
}

// And implement this function.
public function __toString(){
return $this->getMunicipio();
}

/**@return \BackendBundle\Entity\DbProvincia */
public function getProvincia(){
return $this->provincia;
}

Entity DbProvincia 只有字段 (id (integer), slug (String) and province (String))。

我定义的形式如下:

namespace AppBundle\Form;
use ....

class RegistreUserType extends AbstractType {

public function buildForm(FormBuilderInterface $builder, array $options) {
$factory = $builder->getFormFactory();

$builder->add('nombre', TextType::class, array('label' => 'Nombre',
'required' => 'required',
'attr' => array('class' => 'form-nombre form-control')
));
$builder->add('apellido', TextType::class, array('label' => 'Apellido',
'required' => 'required',
'attr' => array('class' => 'form-apellido form-control')
));
$builder->add('nick', TextType::class, array('label' => 'Nick',
'required' => 'required',
'attr' => array('class' => 'form-nick form-control nick-input')
));

$provinSubscriber = new AddProvinciaField($factory);
$builder->addEventSubscriber($provinSubscriber);

$muniSubscriber = new AddMunicipioField($factory);
$builder->addEventSubscriber($muniSubscriber);

$builder->add('email', EmailType::class, array('label' => 'Correo electrónico',
'required' => 'required',
'attr' => array('class' => 'form-email form-control')
));
$builder->add('password', PasswordType::class, array('label' => 'Password',
'required' => 'required',
'attr' => array('class' => 'form-password form-control')
));

$builder->add('Registrarse', SubmitType::class, array("attr" => array("class" => "form-submit btn btn-success")));

}

public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'BackendBundle\Entity\DbUsuario'
));
}

public function getBlockPrefix() { return 'backendbundle_dbusuario'; }
}

我在 AppBundle\Form\eventListener\AddProvinciaField 中定义了以以下形式调用的类:

namespace AppBundle\Form\EventListener;

use ....
use BackendBundle\Entity\DbProvincia;

class AddProvinciaField implements EventSubscriberInterface {
private $factory;

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

public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit'
);
}

private function addProvinciaForm($form, $provincia) {

$form -> add('provincia', EntityType::class, array(
'class' => 'BackendBundle:DbProvincia',
'label' => 'Provincia',
'placeholder' => '_ Elegir _',
'auto_initialize' => false,
'mapped' => false,
'attr'=> array('class' => 'form-provincia form-control provincia-input'),
'query_builder' => function (EntityRepository $repository) {
$qb = $repository->createQueryBuilder('provincia');
return $qb;
}
));
}

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

if (null === $data) {return;}

$provincia = ($data->getIdMunicipio()) ? $data->getIdMunicipio()->getProvincia() : null ;
$this->addProvinciaForm($form, $provincia);
}

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

if (null === $data) { return;}

$provincia = array_key_exists('provincia-input', $data) ? $data['provincia-input'] : null;
$this->addProvinciaForm($form, $provincia);
}
}

然后我定义AddMunicipioField.php:

namespace AppBundle\Form\EventListener;

use ....
use BackendBundle\Entity\DbProvincia;


class AddMunicipioField implements EventSubscriberInterface {
private $factory;

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

public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::PRE_SUBMIT => 'preSubmit'
);
}

private function addMunicipioForm($form, $provincia) {
$form->add('idMunicipio', EntityType::class, array(
'class' => 'BackendBundle:DbMunicipio',
'label' => 'Municipio',
'placeholder' => '_ Elegir _',
'auto_initialize' => false,
'attr'=> array('class' => 'form-municipio form-control municipio-input'),
'query_builder' => function (EntityRepository $repository) use ($provincia) {
$qb = $repository->createQueryBuilder('idMunicipio')
->innerJoin('idMunicipio.provincia', 'provincia');
if ($provincia instanceof DbProvincia) {
$qb->where('idMunicipio.provincia = :provincia')
->setParameter('provincia', $provincia);

} elseif (is_numeric($provincia)) {
$qb->where('provincia.id = :provincia')
->setParameter('provincia', $provincia);

} else {
$qb->where('provincia.provincia = :provincia')
->setParameter('provincia', null);

}
return $qb;
}
));
}

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

if (null === $data) { return; }

$provincia = ($data->getIdMunicipio()) ? $data->getIdMunicipio()->getProvincia() : null ;
$this->addMunicipioForm($form, $provincia);
}

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

if (null === $data) { return; }

$provincia = array_key_exists('provincia_input', $data) ? $data['provincia_input'] : null;
$this->addMunicipioForm($form, $provincia);
}
}

最后是 AJAX 请求:

$(document).ready(function(){
var $form = $(this).closest('form');
$(".provincia-input").change(function(){
var data = { idMunicipio: $(this).val() };
$.ajax({
type: 'POST',
url: $form.attr('action'),
data: data,
success: function(data) {
for (var i=0, total = data.length; i < total; i++) {
$('.municipio-input').append('<option value="' + data[i].id + '">' + data[i].municipio + '</option>');
}
}
});
});
});

我在代码中添加了 var_dumpalert()。这是输出的方式。

在这种情况下,province 的值始终为 null

 addMunicipioField.php
public function preSetData(FormEvent $event){
$data = $event->getData();
$form = $event->getForm();

if (null === $data) {
return;
}

$provincia = ($data->getIdMunicipio()) ? $data->getIdMunicipio()->getProvincia() : null ;
var_dump('presetdata');
var_dump($provincia);
$this->addMunicipioForm($form, $provincia);
}

Ajax :

$(document).ready(function(){
var $form = $(this).closest('form');
$(".provincia-input").change(function(){
alert($('.provincia-input').val()); // THIS IS CORRECT VALUE, INTEGER.
var data = { idMunicipio: $(this).val() };
$.ajax({
type: 'POST',
url: $form.attr('action'),
data: data,
success: function(data) {
alert(data);
alert(data.length); // THIS IS INCORRECT.
for (var i=0, total = data.length; i < total; i++) {
$('.municipio-input').append('<option value="' + data[i].id + '">' + data[i].municipio + '</option>');
}
}
});
});
});

enter image description here

另一种观点实体是一样的。在这种情况下它可以工作,但我必须按下发送按钮。不按按钮怎么会自动变呢?

RegistreUserType 类扩展了 AbstractType 我添加了以下几行。

$builder -> add('provincia', EntityType::class, array(
'class' => 'BackendBundle:DbProvincia',
'label' => 'Provincia',
'placeholder' => '_ Elegir _',
'auto_initialize' => false,
'mapped' => false,
'attr'=> array('class' => 'form-provincia form-control provincia-input'),
'query_builder' => function (EntityRepository $repository) {
$qb = $repository->createQueryBuilder('provincia');
return $qb;
}
));

$builder->add('idMunicipio', EntityType::class, array(
'class' => 'BackendBundle:DbMunicipio',
'label' => 'Municipio',
'placeholder' => '_ Elegir _',
'auto_initialize' => false,
'mapped' => false,
'attr'=> array('class' => 'form-municipio form-control municipio-input')
));

$builder->addEventSubscriber(new AddMunicipioField());

新类AddMunicpioField():

class AddMunicipioField implements EventSubscriberInterface {

public static function getSubscribedEvents() {
return array(
FormEvents::PRE_SUBMIT => 'preSubmit',
FormEvents::PRE_SET_DATA => 'preSetData',
);
}

public function preSubmit(FormEvent $event){
$data = $event->getData();
$this->addField($event->getForm(), $data['provincia']);
}

protected function addField(Form $form, $provincia){
$form->add('idMunicipio', EntityType::class, array(
'class' => 'BackendBundle:DbMunicipio',
'label' => 'Municipio',
'placeholder' => '_ Elegir _',
'auto_initialize' => false,
'mapped' => false,
'attr'=> array('class' => 'form-municipio form-control municipio-input'),
'query_builder' => function(EntityRepository $er) use ($provincia){
$qb = $er->createQueryBuilder('idMunicipio')
->where('idMunicipio.provincia = :provincia')
->setParameter('provincia', $provincia);

return $qb;
}
));
}

编解码器 Ajax:

$(document).ready(function () {
$('.provincia-input').change(function () {
var $form = $(this).closest('form');
var data = $('.provincia-input').serialize();
$.ajax({
url: $form.attr('action'),
type: 'POST',
data: data,
success: function (data) {
$('.municipio-input').replaceWith($(html).find('.municipio-input'));
}
});
});
});

最佳答案

我在您的实体和主窗体中都没有注意到名为“select_provincia”的字段或属性,所以我会尝试猜测,它可能应该简称为“provincia”,因为这是两者的名称市政实体的属性(property),形式为市政当局的订户。同样在 AddMunicipioField.php 中,您应该更改此代码:

if ($provincia instanceof DbProvincia) {
$qb->where('idMunicipio.provincia = :provincia')
>setParameter('provincia', $provincia);
}

为此:

if ($provincia instanceof DbProvincia) {
$qb->where('idMunicipio.provincia = :provincia')
>setParameter('provincia', $provincia->getId());
}

因为查询时您会将省份与省份 ID 进行比较。

此外,确保您已经在市政当局实体中实现了 __toString() 方法,以便 symfony 知道如何将该对象转换为字符串以便在选择列表中显示它。

希望这有帮助:)


看到您添加了新信息,我将更新我的答案:

首先,在 AddMunicipioField.php 中你仍然有基本相同的错误:数组键的命名方式与您命名字段的方式相同,在本例中不是“provincia_input”,而是“provincia”。您可以通过调用“dump($data); die;”查看发布给您的数据。在检查数组键是否存在之前(检查键名称“provincia”,因为您可以看到该名称与您在将字段添加到表单 (AddProvinciaField.php) 时指定的名称匹配):

$form -> add('provincia', EntityType::class

我在您发布的第一个 js 片段中注意到的另一件事是,在这部分代码中:

$(".provincia-input").change(function(){
var data = { idMunicipio: $(this).val() };
$.ajax({
type: 'POST',
url: $form.attr('action'),
data: data,
success: function(data) {
for (var i=0, total = data.length; i < total; i++) {
$('.municipio-input').append('<option value="' + data[i].id + '">' + data[i].municipio + '</option>');
}
}
});
});

您正在从 $(".provincia-input") 获取输入并将其作为值发送给名为“idMunicipio”的字段,我认为在您的情况下这没有任何意义。


最后,我将讨论您发布的最后一段 JS 中出现的错误:

  $(document).ready(function () {
$('.provincia-input').change(function () {
var $form = $(this).closest('form');
var data = $('.provincia-input').serialize();
$.ajax({
url: $form.attr('action'),
type: 'POST',
data: data,
success: function (data) {
$('.municipio-input').replaceWith($(html).find('.municipio-input'));
}
});
});
});

首先,类名不应该用于标识您正在使用的字段。根据定义,它们应该在文档中多次使用并且仅描述样式,这可能会随着代码库的增长而导致一些意外行为。请为您要查询的输入分配正确的 ID 值,尤其是要替换的输入,以便您可以正确识别它们。

其次,请按照此link引用Symfony官方教程中发布的JS代码.如您所见,将数据发回服务器的正确方法不是像您在这一行中尝试的那样发送一个单独的属性:

var data = $('.provincia-input').serialize();

而是通过将属性作为表单数据的一部分发送。因此,在我发布的教程中,请先创建一个空数据对象:

var data = {};

然后向其中添加省份值:

data[$(this).attr('name')] = $(this).val();

第三,这部分代码明显不正确:

success: function (data) {
$('.municipio-input').replaceWith($(html).find('.municipio-input'));
}

如您所见,那部分代码中未定义 html 变量。这当然是因为在这种情况下您应该使用的变量称为数据(您从服务器获得的响应)。所以请将其更改为:

success: function (data) {
$('.municipio-input').replaceWith($(data).find('.municipio-input'));
}

最后,如果您仍在学习 SF 和 Web 编程,我建议您采用自下而上的方法来提高您的编程知识,因为这种情况非常复杂,并且阻止您的代码工作的问题仍然需要更深入的理解您正在使用的技术。我个人建议阅读 HTML 属性用法、Symfony 表单处理,阅读每个 Symfony 表单事件期间可用的数据,也许尝试使用 symfony 的 dumper 组件来调试代码,因为 var_dump 确实是一个非常调试 SF 代码的低效方法(会为您解决很多问题)。

关于php - Symfony3 使用事件动态修改表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42752822/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com