Symfony ожидает ArrayCollection для атрибута одной сущности - PullRequest
0 голосов
/ 11 января 2019

У меня есть сущность с именем "Post":

/**
 * @ORM\Entity(repositoryClass="App\Repository\PostRepository")
 */
class Post
{

/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\Column(type="text", nullable=true)
 */
private $content;

/**
 * @ORM\ManyToOne(targetEntity="UserSubscriptionTier", inversedBy="posts")
 * @Assert\NotBlank()
 *
 */
private $subscriptionTier;

... and all the various get/set functions 

}

Итак, моя главная мысль здесь заключается в том, что $ subscriptionTier - это не объект коллекции, а просто атрибут одной сущности.

Вот как выглядит класс типа формы:

класс PostType расширяет AbstractType { / ** * @var UserProvider * / защищенный $ userProvider;

public function __construct(UserProvider $userProvider)
{
    $this->userProvider = $userProvider;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('file', FileType::class, [
            'label' => 'File or Files',
            'required' => false,
            'mapped'   => false,
            'multiple' => true,
            'attr'=>array('style'=>'display:none;')
        ])
        ->add('content', TextareaType::class, [
            'required' => false
        ])
        ->add('subscriptionTier', EntityType::class, [
            'class' => UserSubscriptionTier::class,
            'choices'  => $this->userProvider->getCurrentUser()->getSubscriptionTiers(),
            'choice_label' => 'name',
            'required' => false,
            'multiple' => true,
            'expanded' => true
        ])
        ->add('save', SubmitType::class, array(
            'attr' => array('class' => 'save')
        ))
    ;
}

Таким образом, subscriptionTier - это просто отдельный атрибут сущности с множеством вариантов для выбора.

Вот то, на что это похоже, когда я строю это в ветке, из входящей формы:

<select class="custom-select" name="subscriptions" required="required">
    <option disabled selected>Visibility</option>
        {% for key,val in postForm.subscriptionTier.vars.choices %}
            {% if val.data.tierNumber == 1 %}
            <option value="{{ val.value }}" {{  postForm.subscriptionTier.vars.value == '' and key == 0 ? ' selected ' :(val.value == postForm.subscriptionTier.vars.value ? ' selected ' : '') }}>All Subscribers</option>
            {% endif %}
            <option value="{{ val.value }}" {{ postForm.subscriptionTier.vars.value == '' and key == 0 ? ' selected ' :(val.value == postForm.subscriptionTier.vars.value ? ' selected ' : '') }}>{{ val.label | trans }}</option>
        {% endfor %}
</select>

Вот код контроллера после отправки формы:

public function createPostAction(PostRepository $postRepository, Request $request)
    {
        $user = $this->getUser();
        $subscriptionId = $request->request->get('subscriptions');
        $userSubscriptionTier = $this->subscriptionTierRepository->find($subscriptionId);

        $post = new Post();
        $post->setUser($user);
        $post->setSubscriptionTier($userSubscriptionTier);
        $form = $this->createForm(PostType::class, $post);

Именно эта функция createForm вызывает следующую ошибку:

Unable to transform value for property path "subscriptionTier": Expected a Doctrine\Common\Collections\Collection object.

Почему Symfony ожидает объект коллекций для одного атрибута сущности? Разве выбор из нескольких вариантов в форме обманул Symfony в ожидании ArrayCollection?

1 Ответ

0 голосов
/ 11 января 2019

Не уверен на 100%, но не так ли из-за 'multiple' => true здесь:

->add('subscriptionTier', EntityType::class, [
        'class' => UserSubscriptionTier::class,
        'choices'  => $this->userProvider->getCurrentUser()->getSubscriptionTiers(),
        'choice_label' => 'name',
        'required' => false,
        'multiple' => true,
        'expanded' => true
    ])

Я думаю, что он создает выборку с несколькими значениями, которая должна передать коллекцию с несколькими значениями.

Вот что документы говорят об этом поле:

множественным тип: логическое значение по умолчанию: false

Если true, пользователь сможет выбрать несколько вариантов (вместо выбора только одного варианта). В зависимости от значения расширенного параметра, он будет отображать либо тег выбора, либо флажки, если он равен true, и тег выбора или переключатели, если он равен false. Возвращаемое значение будет массивом.

Странно то, что ваш вывод на веточку не содержит выбора с «множеством», так что я немного запутался, но попробовать стоит.

...