在普通表单类上使用Sonata字段类型 [英] Use Sonata Field Type on normal Form Class

查看:100
本文介绍了在普通表单类上使用Sonata字段类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在首页上而不是在SonataAdmin中插入自定义奏鸣曲表单字段类型,如下所示:

I'm trying to insert custom sonata form field type on the front page, not in SonataAdmin, something like this:

 $form = $this->createFormBuilder($content)
            ->add('titleEs', 'text', array('required' => true, 'label' => 'label.title.spanish', 'attr' => array('class' => 'col-xs-12 form-control input-lg')))
            ->add('contentEs', 'ckeditor', array('required' => true,'label' => 'label.content.spanish', 'attr' => array('class' => 'col-xs-12')))
            ->add('titleEn', 'text', array('required' => true,'label' => 'label.title.english', 'attr' => array('class' => 'col-xs-12 form-control input-lg')))
            ->add('contentEn', 'ckeditor', array('required' => true, 'label' => 'label.content.english', 'attr' => array('class' => 'col-xs-12')))
            ->add('header', 'sonata_type_model', array('required' => true,'label' => 'label.content.headerImage'), array('link_parameters' => array('context' => 'content/front', 'size' => 'big')))
            //->add('coverImage', 'sonata_type_model_list', array('required' => true,'label' => 'label.content.coverImage'), array('link_parameters' => array('context' => 'content/front', 'size' => 'small')))
            //->add('sliderImage', 'sonata_type_model_list', array('required' => false,'label' => 'label.content.sliderImage'), array('link_parameters' => array('context' => 'content/slider', 'size' => 'normal')))
            ->getForm(); 

但是当我执行该操作时,它会引发错误:

But when I execute that, it throws an error:

Catchable Fatal Error: Argument 1 passed to Sonata\AdminBundle\Form\ChoiceList\ModelChoiceList::__construct() must implement interface Sonata\AdminBundle\Model\ModelManagerInterface, null given

如果Sonata表单字段类型是服务,我不明白为什么Symfony会抛出该错误.

I can't understand why Symfony throws that error, if the Sonata Form Field Types are services.

推荐答案

感谢@gabtzi的回答,我在Sonata Admin的源代码中进行了讨论,并提出了一个非常类似的解决方案.假设我们有两个实体MovieGenre之间具有多对多关系(Movie是拥有方),则Symfony 4和Sonata Admin 3.x中的解决方案如下所示:/p>

Thanks to @gabtzi's answer I poked around in the source code of Sonata Admin and came up with a very similar solution. Assuming that we have two entities Movie and Genre with a many-to-many relation between them (Movie is the owning side), the solution in Symfony 4 and Sonata Admin 3.x would look like this:

<?php

namespace App\Form\Type;

use App\Entity\Movie;
use App\Entity\Genre;
use Symfony\Component\Form\AbstractType;
use Sonata\AdminBundle\Form\Type\ModelType;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MovieType extends AbstractType
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // add fields
            ->add('genres', ModelType::class, [
                'multiple' => true,
                'class' => Genre::class,
                'property' => 'name',  // assuming Genre has property name
                'model_manager' => $this->container->get('sonata.admin.manager.orm'),
                'by_reference' => false
            ])
            // add more fields
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Movie::class,
        ));
    }
}

这是一个非常基本的示例,但是应该给出一个如何进一步进行的想法.重要的事情是:

This is a very basic example, but should give an idea how to proceed further. Important things are:

  • 如果使用自动装配,则不必将表单类型注册为服务.检查config/services.yaml中的autowire是否设置为true.请阅读正式的文档以获取更多详细信息;

  • you don't have to register the form type as a service if you use autowiring. Check that autowire is set to true in your config/services.yaml. Read the official documentation for more detailed information;

ContainerInterface传递给构造函数以获取容器;

pass ContainerInterface to the constructor to get the container;

您不再使用sonata_type_model.您必须使用ModelType::class.注意使用声明;

you don't use sonata_type_model anymore. You have to use ModelType::class. Pay attention to the use statements;

您可以将M2M关系的mutiple设置为true,否则默认为false;

you can set mutiple to true for a M2M relation, otherwise it defaults to false;

您必须将实体类传递给class-在这种情况下为Movie::class;

you have to pass the entity class to class - in this case Movie::class;

,您可以指定property以使用Genre的某些属性.如果您在实体类中定义了__toString方法,则不必声明此方法.然后将使用此方法的返回值;

you can specify property to use certain property of Genre. You don't have to declare this if you have defined __toString method in the entity class. Then the return value of this method will be used;

最重要的是:现在您有了容器,获得服务sonata.admin.manager.orm并将其传递给model_manager.没有这些,一切都会掉入水中.

the most important thing: now that you have the container, get the service sonata.admin.manager.orm and pass it to model_manager. Without this everything falls in water.

但是我没有设法显示按钮 +添加新的.值得一提的是,相关属性的admin类必须存在并且可以访问(设置了正确的权限)-在这种情况下,需要GenreAdmin,否则该按钮在理论上甚至无法正常工作.

I haven't however managed to display the button + Add new. It's worth mentioning that admin class for the related property must exist and be accessible (proper permissions set) - in this case GenreAdmin would be required, otherwise the button couldn't even theoretically work.

这篇关于在普通表单类上使用Sonata字段类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆