首页 > 解决方案 > 从 symfony2.8 升级到 3.0 的表单的向后兼容性中断

问题描述

所以从 symfony 2.8 升级到 3.0(或者说升级到 3.4,这实际上是现在的目标),我一直在拖延,这和之前的一些小更新一样麻烦。有些框架只是喜欢强迫你重写代码,我猜......

无论如何,我知道这已经在许多其他帖子中得到处理,但我想让它万无一失,就像“傻瓜的 symfony 表单”将你的表单从 symfony 2.8 移动到 3.0。

如果您通过 app_dev.php 运行您的应用程序,您会在页脚中获得关于已弃用的内容的很好提示,换句话说,哪些内容在 3.0 版中不起作用。

此特定问题的弃用消息是:

将类型实例传递给 FormBuilder::add()、Form::add() 或 FormFactory 自 2.8 版以来已弃用,3.0 版将不再支持。改用完全限定的类型类名

我必须对表单做的第一件事是更改从控制器调用它们的方式。symfony 文档很满意地说:

前:

$form = $this->createForm(new MyType());

后:

$form = $this->createForm(MyType::class);

但是等一下,那我该如何传递我的变量呢?我的表单调用看起来更像这样:

$form = $this->createForm(new extraOpeningType($user), $extraOpening);

我传递了与表单匹配的实体,以及一个用于许可目的的附加实体。对于 Sensiolabs 的优秀变更日志人员来说,这个问题甚至不足以评论它。

标签: phpsymfony

解决方案


其他人注意到了这一点并在此处写了一个问题(https://github.com/symfony/symfony/issues/18662),尽管他的示例代码中有一两个错字。这里还有一篇 SO 文章(Passing data to buildForm() in Symfony 2.8, 3.0 and above)对解决这个问题非常有帮助。

所以就我而言,在 pre-symfony3.0 中,我曾经这样调用表单:

$form = $this->createForm(new extraOpeningType($user), $extraOpening);

$user 是我为表单数据中的权限处理目的而传入的变量,而 $extraOpening 是与表单匹配的实际实体。以下是您现在必须如何从现在开始传递这些变量:

use ExtraOpeningBundle\Form\ExtraOpeningType as extraOpeningType; //this goes in the controller head, among your USE statements
...
$form = $this->createForm(extraOpeningType::class, $extraOpening, ['user' => $user]);

如果您不想在头部使用 USE 语句,您可以将完全限定的路径放置到您的类型中,如下所示(注意类型路径上的前导反斜杠):

$form = $this->createForm(\ExtraOpeningBundle\Form\ExtraOpeningType::class, $extraOpening, ['user' => $user]);

在接收端,在你的表单中(类型,正如 symfony 所说的那样),你之前有一个构造函数来拉入传递的变量......

class ExtraOpeningType extends AbstractType
{
    function __construct($user)
    {
        $this->user = $user;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $user = $this->user;

现在它看起来像这样:

class ExtraOpeningType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $this->user = $options['user'];  

尽管您需要将刚刚创建的自定义选项添加到已批准的选项列表中,否则您将面临“用户”不是有效选项的错误。因此,如下修改您的 configureOptions 方法(如果您尚未使用该方法,请创建该方法):

class ExtraOpeningType extends AbstractType
{

...

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'user' => null
        ));
    }

Symfony 经常是一个梦想,但当涉及到更新时,它可能是一场噩梦。许多向后兼容性中断。


推荐阅读