Adding relationship to an Entity couses weird ORM mapping error

492 views Asked by At

In Symfony Api Platform application, using Maker Bundle to add a relationship field "Owner" to "Community" Entity coused all "Get" api calls to return the same error. This is a new project I use all the newest available version.

Request: curl -X 'GET'
'http://127.0.0.1:8000/api/communities?page=1'
-H 'accept: application/ld+json'

//Error

{
  "@id": "/api/errors/500",
  "@type": "hydra:Error",
  "title": "An error occurred",
  "detail": "Attempted to load class \"ClassMetadataInfo\" from namespace \"Doctrine\\ORM\\Mapping\".\nDid you forget a \"use\" statement for another namespace?",
  "status": 500,
  "type": "/errors/500",
  "trace": [
    {
      "file": "\\vendor\\api-platform\\core\\src\\Doctrine\\Orm\\Extension\\EagerLoadingExtension.php",
      "line": 98,
      "function": "joinRelations",
      "class": "ApiPlatform\\Doctrine\\Orm\\Extension\\EagerLoadingExtension",
      "type": "->"
    },
    {
      "file": "\\vendor\\api-platform\\core\\src\\Doctrine\\Orm\\Extension\\EagerLoadingExtension.php",
      "line": 53,
      "function": "apply",
      "class": "ApiPlatform\\Doctrine\\Orm\\Extension\\EagerLoadingExtension",
      "type": "->"
    },
// Community.php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Repository\CommunityRepository;
use Doctrine\DBAL\Types\Types;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\User;


#[ORM\Entity(repositoryClass: CommunityRepository::class)]
#[ApiResource(
    normalizationContext: ['groups' => ['community:read']],
    denormalizationContext: ['groups' => ['community:create', 'community:update']],
)]
#[ORM\Table(name: '`community`')]
#[UniqueEntity('name')]
class Community
{
    const STATUS_PUBLIC = 'public';
    const STATUS_PRIVATE = 'private';
    const STATUS_RESTRICTED = 'restricted';

    #[Groups(['community:read'])]
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[Assert\NotBlank]
    #[Groups(['community:read', 'community:create', 'community:update'])]
    #[ORM\Column(length: 50)]
    
    private ?string $name = null;

    // Address and name of given community
    #[Groups(['community:read', 'community:create', 'community:update'])]
    #[ORM\Column(type: Types::TEXT, nullable: true)]
    private ?string $description = null;

    // Amount of users of given community
    #[ORM\Column]
    #[Groups(['community:read'])]
    private ?int $numberOfUsers = 0;

    // Date of creation of given community
    #[Groups(['community:read'])]
    #[ORM\Column(type: Types::DATETIMETZ_MUTABLE)]
    private ?\DateTimeInterface $creation_time = null;

    // Status of given community; PUBLIC, PRIVATE, RESTRICTED
    #[Groups(['community:read', 'community:create', 'community:update'])]
    #[ORM\Column(type: 'string', length: 10)]
    private ?string $status = self::STATUS_PUBLIC;

    #[Groups(['community:read', 'community:create', 'community:update'])]
    #[ORM\ManyToOne(targetEntity: User::class ,inversedBy: 'owned_communites')]
    #[ORM\JoinColumn(nullable: false)]
    private ?User $owner = null;

    //getters and setters
// User Entity

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use Doctrine\DBAL\Types\Types;
use App\Repository\UserRepository;
use App\State\PasswordHasher;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;

use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\Community;

#[ApiResource(
    operations: [
        new GetCollection(),
        new Post(processor: PasswordHasher::class, validationContext: ['groups' => ['Default', 'user:create']]),
        new Get(),
        new Put(processor: PasswordHasher::class),
        new Patch(processor: PasswordHasher::class),
        new Delete(),
    ],
    normalizationContext: ['groups' => ['user:read']],
    denormalizationContext: ['groups' => ['user:create', 'user:update']],
)]
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')]
#[UniqueEntity('email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
    #[Groups(['user:read'])]
    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    #[Assert\NotBlank]
    #[Assert\Email]
    #[Groups(['user:read', 'user:create', 'user:update'])]
    #[ORM\Column(length: 80, unique: true)]
    private ?string $email = null;

    #[ORM\Column]
    //DEBUG ONLY:
    //#[Groups(['user:read', 'user:create', 'user:update'])]
    private ?string $password = null;

    #[Assert\NotBlank(groups: ['user:create'])]
    #[Groups(['user:create', 'user:update'])]
    private ?string $plainPassword = null;

    #[ORM\Column(type: 'json')]
    private array $roles = [];

    #[Assert\NotBlank]
    #[Groups(['user:read', 'user:create', 'user:update'])]
    #[ORM\Column(length: 25)]
    private ?string $nickname = null;

    #[Assert\NotBlank]
    #[Groups(['user:read', 'user:create', 'user:update'])]
    #[ORM\Column(length: 30)]
    private ?string $login = null;

    #[Assert\NotBlank]
    #[Groups(['user:read', 'user:create', 'user:update'])]
    #[ORM\Column(type: Types::DATETIMETZ_MUTABLE)]
    private ?\DateTimeInterface $birthday = null;

    #[Groups(['user:read'])]
    #[ORM\Column(type: Types::DATETIMETZ_MUTABLE)]
    private ?\DateTimeInterface $creation_time = null;

    #[Groups(['user:read', 'user:create', 'user:update'])]
    #[ORM\OneToMany(targetEntity: Community::class, mappedBy: 'owner')]
    private Collection $owned_communites;
//getters and setters
4

There are 4 answers

1
OmniSensei15 On BEST ANSWER

Something is completely broken in Relationships in the newest version of the stack. The error appears everytime you add connection between entities. You can either try downgrading each component of Doctrine one by one via composer or simply move to Laravel and create your API there. It's much less broken. Cheers!

0
Omar Saad On

I had the same issue. I solved it by changing the version of doctrine/orm from 3.0 to version 2.18.

0
Dr. Gianluigi Zane Zanettini On

There is an issue open for this problem. I think it's related to a BC BREAK: Removed Doctrine\ORM\Mapping\ClassMetadataInfo class in 3.0. Revert to 2.latest should fix it for now.

0
VincentORRU On

I have encountered the same issue when you check the file here

You can watch out in the new release 3.2.16 that this file has been upgraded.

Just upgrade to a apiplatform version equal or higher of 3.2.16 with composer like this :

composer require api-platform/core:3.2.16