【问题标题】:Symfony2 - use Sonata field type outside the bundleSymfony2 - 在包外使用 Sonata 字段类型
【发布时间】:2017-05-04 07:59:56
【问题描述】:

我想为multiple 选择漂亮的EntityType,就像奏鸣曲对sonata_type_model (ModelType) 所做的那样。

问题是,我如何在我的自定义表单上使用sonata_type_model 之外的SonataAdminBundle

我试过了:

->add('countries', 'sonata_type_model', array(
    'label' => 'Countries',
    'property' => 'name',
    'multiple' => true
))

我也试过了:

use Sonata\AdminBundle\Form\Type\ModelType;

...

->add('countries', ModelType::class, array(
    'label' => 'Countries',
    'property' => 'name',
    'multiple' => true
))

但不幸的是,我收到了一个错误:

可捕获的致命错误:参数 1 传递给 Sonata\AdminBundle\Form\ChoiceList\ModelChoiceLoader::__construct() 必须实现接口 Sonata\AdminBundle\Model\ModelManagerInterface,给定 null,调用 C:\xampp\htdocs\trainingexperience_symfony\app\cache\dev\classes.php 在第 18005 行并定义

更新

我遵循了在表单类型选项中定义 model_manager 属性的建议:

protected $modelManager;

function __construct(ModelManager $modelManager)
{
    $this->modelManager = $modelManager;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('preferredCountries', ModelType::class, array(
            'label' => 'Countries',
            'property' => 'name',
            'multiple' => true,
            'model_manager' => $this->modelManager
        ));

    ...
}

我从控制器传递它,例如:

/** @var ModelManager $modelManager */
$modelManager = $this->get('sonata.media.admin.media.manager');
$formType = new FormType($modelManager);

...

但现在我得到一个错误:

类不存在

500 内部服务器错误 - ReflectionException

堆栈跟踪

in vendor\doctrine\common\lib\Doctrine\Common\Persistence\AbstractManagerRegistry.php at line 197   -

   $class = $this->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName; 
        } 
        $proxyClass = new \ReflectionClass($class); 
        if ($proxyClass->implementsInterface($this->proxyInterfaceName)) { 
            if (! $parentClass = $proxyClass->getParentClass()) { 

at ReflectionClass ->__construct ('') 
in vendor\doctrine\common\lib\Doctrine\Common\Persistence\AbstractManagerRegistry.php at line 197   + 
at AbstractManagerRegistry ->getManagerForClass (null) 
in vendor\sonata-project\doctrine-orm-admin-bundle\Model\ModelManager.php at line 272   + 
at ModelManager ->getEntityManager (null) 
in vendor\sonata-project\doctrine-orm-admin-bundle\Model\ModelManager.php at line 64   + 
at ModelManager ->getMetadata (null) 
in vendor\sonata-project\doctrine-orm-admin-bundle\Model\ModelManager.php at line 377   + 
at ModelManager ->getIdentifierFieldNames (null) 
in vendor\sonata-project\admin-bundle\Form\ChoiceList\ModelChoiceLoader.php at line 75   + 
at ModelChoiceLoader ->__construct (object(ModelManager), null, 'name', null, array(), object(PropertyAccessor)) 
in vendor\sonata-project\admin-bundle\Form\Type\ModelType.php at line 113   + 
at ModelType ->Sonata\AdminBundle\Form\Type\{closure} (object(OptionsResolver), null) 
in vendor\symfony\symfony\src\Symfony\Component\OptionsResolver\OptionsResolver.php at line 859   + 
at OptionsResolver ->offsetGet ('choice_loader') 
in vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\Type\ChoiceType.php at line 320   + 
at ChoiceType ->Symfony\Component\Form\Extension\Core\Type\{closure} (object(OptionsResolver), null) 
in vendor\symfony\symfony\src\Symfony\Component\OptionsResolver\OptionsResolver.php at line 965   + 
at OptionsResolver ->offsetGet ('choice_list') 
in vendor\symfony\symfony\src\Symfony\Component\OptionsResolver\OptionsResolver.php at line 791   + 
at OptionsResolver ->resolve (array('label' => 'Countries', 'property' => 'name', 'multiple' => true, 'model_manager' => object(ModelManager))) 
in vendor\symfony\symfony\src\Symfony\Component\Form\ResolvedFormType.php at line 156   + 
at ResolvedFormType ->createBuilder (object(FormFactory), 'preferredCountries', array('label' => 'Countries', 'property' => 'name', 'multiple' => true, 'model_manager' => object(ModelManager))) 
in vendor\symfony\symfony\src\Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy.php at line 89  + 
at ResolvedTypeDataCollectorProxy ->createBuilder (object(FormFactory), 'preferredCountries', array('label' => 'Countries', 'property' => 'name', 'multiple' => true, 'model_manager' => object(ModelManager))) 
in vendor\symfony\symfony\src\Symfony\Component\Form\FormFactory.php at line 114   + 
at FormFactory ->createNamedBuilder ('preferredCountries', 'Sonata\AdminBundle\Form\Type\ModelType', null, array('label' => 'Countries', 'property' => 'name', 'multiple' => true, 'model_manager' => object(ModelManager))) 
in vendor\symfony\symfony\src\Symfony\Component\Form\FormBuilder.php at line 106   + 
at FormBuilder ->create ('preferredCountries', 'Sonata\AdminBundle\Form\Type\ModelType', array('label' => 'Countries', 'property' => 'name', 'multiple' => true, 'model_manager' => object(ModelManager))) 
in vendor\symfony\symfony\src\Symfony\Component\Form\FormBuilder.php at line 269   + 
at FormBuilder ->resolveChildren () 
in vendor\symfony\symfony\src\Symfony\Component\Form\FormBuilder.php at line 215   + 
at FormBuilder ->getForm () 
in vendor\symfony\symfony\src\Symfony\Component\Form\FormFactory.php at line 40   + 
at FormFactory ->create (object(InternshipType), object(Internship), array()) 
in vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Controller\Controller.php at line 282   + 
at Controller ->createForm (object(InternshipType), object(Internship)) 
in src\IndexBundle\Controller\TraineeController.php at line 194   + 
at TraineeController ->internshipsAction (object(Request)) 
at call_user_func_array (array(object(TraineeController), 'internshipsAction'), array(object(Request))) 
in vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php at line 144   + 
at HttpKernel ->handleRaw (object(Request), '1') 
in vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php at line 64   + 
at HttpKernel ->handle (object(Request), '1', true) 
in vendor\symfony\symfony\src\Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel.php at line 69   + 
at ContainerAwareHttpKernel ->handle (object(Request), '1', true) 
in vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Kernel.php at line 185   + 
at Kernel ->handle (object(Request)) 
in web\app_dev.php at line 30   + 

【问题讨论】:

    标签: forms symfony sonata-admin sonata form-fields


    【解决方案1】:

    您应该尝试为该类型提供model_manager 选项。它可能是一项服务,因此请查看debug:container 并尝试发现它。

    【讨论】:

    • 你说得对,我发现它是服务并传递给表单类型,但不幸的是我遇到了错误。你能检查我更新的问题吗?
    • 你必须提供一个完整的堆栈跟踪,我不能只用“ReflectionException”来帮助你
    • 已编辑请检查:)
    • “类不存在”... 试着找出是什么类
    【解决方案2】:

    您收到此错误是因为 sonata_type_model 需要目标管理员的模型管理器来操作实体。

    底线:您不能在没有定义管理服务的实体上使用 sonata_type_model

    这是我使用的解决方法:

    表格类型:

    <?php
    
    namespace Blast\BaseEntitiesBundle\Form\Type;
    
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    use Symfony\Component\OptionsResolver\Options;
    use Blast\CoreBundle\Form\AbstractType;
    
    class NestedTreeableType extends AbstractType
    {   
        public function configureOptions(OptionsResolver $resolver)
        {
            $queryBuilder = function (Options $options) 
            {
                return $options['em']
                    ->getRepository($options['class'])
                    ->getNodesHierarchyQueryBuilder();
            };
    
        $choiceLabel = function($choice)
        {
             return str_repeat(' - ', $choice->getTreeLvl()) . (string) $choice;
        };
    
        $resolver->setDefaults([
            'query_builder' => $queryBuilder,
            'choice_label'  => $choiceLabel,
            'btn_add' => 'link_add',
            'btn_list' => 'link_list',
            'btn_delete' => 'link_delete',
            'btn_catalogue' => 'SonataAdminBundle',
        ]);
    }
    
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        parent::buildView($view, $form, $options);
    
        $object_id = ($view->vars['name'] == 'treeParent') ? $form->getParent()->getData()->getId() : null;
    
        $choices = [];
    
        foreach ($view->vars['choices'] as $choice) {
                if ( $object_id && $choice->data->getId() == $object_id )
                    $choice->attr['disabled'] = 'disabled';
    
            $choices[] = $choice;
        }
    
        $view->vars['choices'] = $choices;
        $view->vars['btn_add'] = $options['btn_add'];
        $view->vars['btn_list'] = $options['btn_list'];
        $view->vars['btn_delete'] = $options['btn_delete'];
        $view->vars['btn_catalogue'] = $options['btn_catalogue'];
    }
    
    public function getParent()
    {
        return 'entity';
    }
    
    public function getBlockPrefix()
    {
        return 'blast_nested_treeable';
    }
    

    }

    如您所见,我正在定义 sonata_type_model 需要的选项和视图变量,现在是表单类型的模板

    {% extends 'SonataDoctrineORMAdminBundle:Form:form_admin_fields.html.twig' %}
    
    {% block blast_nested_treeable_widget %}
        {{ block('sonata_type_model_widget') }}
    {% endblock %}
    

    只需渲染一个 sonata_type_model 块就可以了。 如果你想看看真实的例子:https://github.com/blast-project/BaseEntitiesBundle

    希望有帮助

    【讨论】:

    • 顺便说一句,如果您想通过在 yaml 中配置它来简化 Sonata admin 的使用,请查看 github.com/blast-project/CoreBundle 文档仍然很糟糕,但功能很棒
    【解决方案3】:

    我不知道是否有人还在搜索它,但是,我发现你需要这个才能拥有 modelManager(至少在 2.7 版本的 symfony 中):

    /** @var ModelManager $modelManager */
    $modelManager = $this->get('sonata.admin.manager.orm');
    $formType = new FormType($modelManager);
    
    ...
    

    拜兹

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 2013-06-01
      • 2015-04-29
      • 1970-01-01
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      相关资源
      最近更新 更多