简体   繁体   English

Symfony2 - 在包外使用Sonata字段类型

[英]Symfony2 - use Sonata field type outside the bundle

I would like to have good looking EntityType for multiple selection as Sonata does with sonata_type_model ( ModelType ). 我希望有一个好看的EntityType用于multiple选,因为Sonata使用sonata_type_modelModelType )。

The question would be, how can I use sonata_type_model outside SonataAdminBundle on my custom form? 问题是,如何在我的自定义表单上使用sonata_type_model之外的SonataAdminBundle

I tried: 我试过了:

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

Also I tried: 我也尝试过:

use Sonata\AdminBundle\Form\Type\ModelType;

...

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

But unfortunately I am getting an error: 但不幸的是我收到了一个错误:

Catchable Fatal Error: Argument 1 passed to Sonata\\AdminBundle\\Form\\ChoiceList\\ModelChoiceLoader::__construct() must implement interface Sonata\\AdminBundle\\Model\\ModelManagerInterface, null given, called in C:\\xampp\\htdocs\\trainingexperience_symfony\\app\\cache\\dev\\classes.php on line 18005 and defined 可捕获致命错误:传递给Sonata \\ AdminBundle \\ Form \\ ChoiceList \\ ModelChoiceLoader :: __ construct()的参数1必须实现接口Sonata \\ AdminBundle \\ Model \\ ModelManagerInterface,null给定,在C:\\ xampp \\ htdocs \\ trainingexperience_symfony \\ app \\ cache中调用\\ dev \\ classes.php在18005行并定义

UPDATE UPDATE

I followed an advice to define model_manager property inside form type options: 我按照建议在表单类型选项中定义了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
        ));

    ...
}

I pass it from controller like: 我从控制器传递它,如:

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

...

But now I get an error: 但现在我收到一个错误:

Class does not exist 类不存在

500 Internal Server Error - ReflectionException 500内部服务器错误 - ReflectionException

Stack Trace 堆栈跟踪

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   + 

You should try providing the model_manager option to the type. 您应该尝试为该类型提供model_manager选项。 It might be a service, so have a look at debug:container and try to spot it. 它可能是一个服务,所以看看debug:container并尝试发现它。

You are getting this error because sonata_type_model needs the modelmanager of the targeted admin to manipulate the entities. 您收到此错误是因为sonata_type_model需要目标管理员的modelmanager来操作实体。

Bottom line: you can not use sonata_type_model on entities that do not have an admin service defined 结论:您不能在未定义管理服务的实体上使用sonata_type_model

Here is a workaround i used : 这是我使用的解决方法:

Form type: 表格类型:

<?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';
}

} }

as you can see i am defining the options and view variables that sonata_type_model needs and now the template for the form type 正如您所看到的,我正在定义选项并查看sonata_type_model需要的变量,现在是表单类型的模板

{% extends 'SonataDoctrineORMAdminBundle:Form:form_admin_fields.html.twig' %}

{% block blast_nested_treeable_widget %}
    {{ block('sonata_type_model_widget') }}
{% endblock %}

Just render a sonata_type_model block and your good to go. 只需渲染一个sonata_type_model块就可以了。 if you want to take a look at the real example : https://github.com/blast-project/BaseEntitiesBundle 如果你想看看真实的例子: https//github.com/blast-project/BaseEntitiesBundle

Hope that helps 希望有所帮助

I don't know if someone is still searching that, but, I've found that you need this to have the modelManager (at least in 2.7 version of symfony): 我不知道有人还在搜索那个,但是,我发现你需要这个才能拥有modelManager(至少在2.7版本的symfony中):

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

...

byez byez

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM