Symfony6表单渲染:无法将类App\Entity\User的对象转换为字符串。

huangapple go评论59阅读模式
英文:

Symfony6 Form Render Object of class App\Entity\User could not be converted to string

问题

在这段代码中,出现了一个错误,错误信息是Object of class App\Entity\User could not be converted to string,这个错误通常是因为在表单中尝试将User对象直接转换为字符串时引起的。这是因为Symfony默认情况下会尝试将实体对象转换为字符串,但User实体没有定义如何转换为字符串的方法。

要解决这个问题,您可以通过在TeamType表单类的相应字段上使用EntityType字段类型来明确指定owner字段应该是一个实体选择字段,而不是直接将User对象转换为字符串。以下是如何修改TeamType表单类以解决这个问题:

use Symfony\Bridge\Doctrine\Form\Type\EntityType;

// ...

class TeamType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name')
            ->add('intro')
            ->add('country')
            ->add('balance')
            ->add('created_at')
            ->add('updated_at')
            ->add('owner', EntityType::class, [
                'class' => User::class, // 指定实体类
                'choice_label' => 'username', // 选择一个显示的字段,例如'username'
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Team::class,
        ]);
    }
}

通过以上修改,owner字段将变成一个实体选择字段,用户可以从已有的User实体中进行选择,而不会再引发字符串转换错误。

请确保根据您的实际需要选择正确的choice_label字段,这个字段将显示在表单中供用户选择。

英文:

I am trying to render form of Team entity which is attached to User with ManyToOne relationship. See below Entity Class:

<?php

namespace App\Entity;

class Team
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\ManyToOne(inversedBy: 'teams')]
    #[ORM\JoinColumn(nullable: false)]
    private ?User $owner = null;
...

Below is User entity class code:

<?php

namespace App\Entity;

Class User {

    #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Team::class)]
    private Collection $teams;
....

Here is the controller class code where I am rending form view:

<?php

namespace App\Controller;

class TeamController extends AbstractController
{
    #[Route('/new', name: 'app_team_new', methods: ['GET', 'POST'])]
    public function new(Request $request, TeamRepository $teamRepository): Response
    {
        $team = new Team();
        $form = $this->createForm(TeamType::class, $team);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $teamRepository->save($team, true);

            return $this->redirectToRoute('app_team_index', [], Response::HTTP_SEE_OTHER);
        }

        return $this->render('team/new.html.twig', [
            'team' => $team,
            'form' => $form,
        ]);
    }
...

And here is the TeamType form class

<?php

namespace App\Form;


class TeamType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name')
            ->add('intro')
            ->add('country')
            ->add('balance')
            ->add('created_at')
            ->add('updated_at')
            ->add('owner')
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Team::class,
        ]);
    }
}
...

And lastly, the team/new.html.twig

{% extends 'layouts/base.html.twig' %}

{% block title %}
	New Team
{% endblock %}

{% block body %}
	<main class="container form-signin w-100 m-auto">
		<h1>Add Team</h1>

		{{ form_start(form) }}
		{{ form_widget(form) }}
		<button class="btn">{{ button_label|default('Save') }}</button>
		{{ form_end(form) }}


		<a href="{{ path('app_team_index') }}" class="btn btn-link bi bi-arrow-left text-decoration-none">
			  Back to all teams</a>
	</main>
{% endblock %}

I am getting an error that Object of class App\Entity\User could not be converted to string exactly near the line 'form' => $form,.

What could be a possible issue?

答案1

得分: 2

我找到了解决方法。如果你想将实体用作表单字段,需要在你的表单类型中指定class和choice_label选项。class选项告诉Symfony要为该字段使用哪个实体类,而choice_label选项告诉Symfony要使用哪个属性或方法作为每个选项的标签。要修复这个问题,你需要像这样配置User字段的表单类型:

<?php

namespace App\Form;

use App\Entity\Team;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;


class TeamType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name')
            ->add('intro')
            ->add('country')
            ->add('balance')
            ->add('created_at')
            ->add('updated_at')
            ->add('owner', EntityType::class, [
                'class' => User::class,
                'choice_label' => 'full_name', // 或者任何返回字符串的其他属性或方法
            ]);
        ;
    }
...

希望这对某人有所帮助。

英文:

I found the solution. If you want to use an entity as a form field, you need to specify the class and the choice_label options in your form type. The class option tells Symfony which entity class to use for the field, and the choice_label option tells Symfony which property or method to use as the label for each choice. To fix this, you need to configure your form type for the User field like this:

&lt;?php

namespace App\Form;

use App\Entity\Team;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;


class TeamType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            -&gt;add(&#39;name&#39;)
            -&gt;add(&#39;intro&#39;)
            -&gt;add(&#39;country&#39;)
            -&gt;add(&#39;balance&#39;)
            -&gt;add(&#39;created_at&#39;)
            -&gt;add(&#39;updated_at&#39;)
            -&gt;add(&#39;owner&#39;, EntityType::class, [
                &#39;class&#39; =&gt; User::class,
                &#39;choice_label&#39; =&gt; &#39;full_name&#39;, // or any other property or method that returns a string
            ]);
        ;
    }
...

Hope this help someone.

答案2

得分: 2

Doctrine在尝试显示关系时,例如您的情况下的Team和User类。根据关系的一侧,Doctrine会尝试将这些类转换为字符串,以便在HTML表单中显示选择选项的值。您应该实现__toString方法。

class User
{
  //...
  public function __toString()
  {
    return (string) $this->getUserIdentifier();
  }
}

class Team
{
  //...
  public function __toString()
  {
    return (string) $this->name;
  }
}
英文:

When doctrine tries to display relationships, in your case the Team and User classes. depending on the side of the relationship, doctrine tries to convert these classes to a string, in order to display select with option choice value in html form. You should be to implement __toString methods

class User
{
  //...
  public function __toString()
  {
    return (string) $this-&gt;getUserIdentifier();
  }
}

class Team
{
  //...
  public function __toString()
  {
    return (string) $this-&gt;name;
  }
}

答案3

得分: 0

如果表单仅用于向当前用户添加新的团队,那么您不应该在表单中包括所有者字段。而是在控制器中手动将所有者设置为当前用户。

所以请从您的FormType中省略-&gt;add(&#39;owner&#39;, /*...*/);的调用,并编辑您的处理程序如下(根据您特定的实体方法逻辑进行调整):

    public function new(Request $request, TeamRepository $teamRepository): Response
    {
        $team = new Team();
        $user = $this-&gt;getUser();
        $user-&gt;addTeam($team);
        $team-&gt;setOwner($user);

        /* 创建表单并处理请求 */
    }

作为在处理程序中设置所有者的替代方法,特别是因为所有者不可为空,您可以在Team构造函数中设置所有者。然后,通过传递当前用户来创建一个团队。

英文:

If the form will only be used to add new Teams to the current User, then you should not include the owner field in the form. Instead, manually set the owner to the current User in the Controller.

So omit the -&gt;add(&#39;owner&#39;, /*...*/); call from your FormType and edit your handler to be something like the following (adjust for your specific Entity methods' logic):

    public function new(Request $request, TeamRepository $teamRepository): Response
    {
        $team = new Team();
        $user = $this-&gt;getUser();
        $user-&gt;addTeam($team);
        $team-&gt;setOwner($user);

        /* create form and handle Request */
    }

As an alternative to setting the owner in the handler, and especially since the owner is not nullable, you could set the owner in the Team constructor. You would then create a Team by passing the current User.

huangapple
  • 本文由 发表于 2023年6月15日 20:16:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76482375.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定