如果你在Symfony中使用表单, 那么你将知道为任何实体实现新的Type多么容易, 因此你可以在应用程序中轻松创建CRUD表单操作。有时, 你可能希望从控制器向表单中添加动态字段, 因为你不希望此字段出现在另一个字段中, 因为在这种情况下只需要它。这可以通过表单字段的映射属性来实现。
假设我们有一个UserType来创建一个Form来在我们的应用程序中注册用户:
<?php
namespace userBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
class UserType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class , array(
"attr" => array(
"class" => "form-control"
)
))
->add('username', TextType::class, array(
"attr" => array(
"class" => "form-control"
)
))
->add('description', TextareaType::class, array(
"attr" => array(
"class" => "form-control", "maxlength" => 255
)
))
->add('password', RepeatedType::class, array(
'type' => PasswordType::class, 'invalid_message' => 'The password fields must match.', 'options' => array(
'attr' => array(
'class' => 'form-control'
)
), 'required' => true, 'first_options' => array('label' => 'Password'), 'second_options' => array('label' => 'Repeat Password'), ))
;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'userBundle\Entity\User'
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'userbundle_user';
}
}
此类型包含5个来自UserEntity的必填字段, 将在我们的控制器中进行处理以创建新用户。在控制器的newAction中, 我们将使用以下代码创建一个表单:
<?php
public function newuserAction(Request $request){
$user = new User();
// Create a form using the UserType
$form = $this->createForm(UserType::class, $user);
// Add dinamically a new multiple select field that isn't in the UserEntity:
$form->add('roles_options', ChoiceType::class, array(
"mapped" => false, "multiple" => true, "attr" => array(
'class' => "form-control"
), 'choices' => array(
'Blogger' => 'ROLE_BLOGGER', 'Administrator' => 'ROLE_ADMIN'
)
));
$form->handleRequest($request);
if ($form->isSubmitted()) {
// Rest of the logic
}
return $this->render('users/new.html.twig', array(
'form' => $form->createView()
));
}
现在, 如果用户访问新路线, 他将看到只需要提交的表单。提交后, 将触发相同的newAction(如果在POST中的routing.yml中进行了配置), 则将执行处理表单的逻辑。创建具有Symfony类型的表单的优点是你可以轻松地将实体持久保存在控制器中, 但是有时你需要通过修改某些值(或将其用于其他目的)使控制器中的处理步骤动态化, 以便使用表单的getData方法可以轻松地检索表单的值:
<?php
if ($form->isSubmitted()) {
$data = $form->getData();
// $data contains an array like:
// array(
// "name" => "The submitted name", // "username" => "The submitted Username", // "description" => "The submitted description", // "password" => "The submitted password"
// );
}
但是, 等等, ****是我们在控制器中动态添加的role_options字段的值?它不在真实形式之内, 只是因为该字段未映射, 所以它不能在真实形式之内, 因为这会触发另一个异常, 即”此形式不应包含额外的字段”。
检索非映射字段的值
而不是访问表单数组数据中的值, 你需要使用表单中的get方法, 该方法将未映射字段的名称作为第一个参数。从返回的对象中, 可以使用getData方法检索值:
<?php
if ($form->isSubmitted()) {
$data = $form->getData();
// Retrieve the value from the extra field non-mapped !
$roles = $form->get("roles_options")->getData();
// Where $data contains an array like:
// array(
// "name" => "The submitted name", // "username" => "The submitted Username", // "description" => "The submitted description", // "password" => "The submitted password"
// );
// and $roles another array in this case with our options (that were selected obviously):
// [
// 0 => "ROLE_BLOGGER"
// 1 => "ROLE_ADMIN"
// ]
}
编码愉快!
评论前必须登录!
注册