Doctrine - 传递给 __construct 的参数必须是一个数组

Doctrine - Argument passed to __construct must be an array

当我发现这个错误时,我正在尝试创建一个新服务。当我尝试列出可用的学说命令时,它显示了下一个错误:

Doctrine\ORM\Mapping\OneToMany::__construct() 必须是数组或 null 类型,给定的字符串,在 /var/www/html/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php

中调用

我尝试重置对其负责的实体,但没有结果。这是所有跟踪:

TypeError {#478
#message: "Argument 3 passed to Doctrine\ORM\Mapping\OneToMany::__construct() must be of the type array or null, string given, called in /var/www/html/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php on line 971"
  #code: 0
  #file: "./vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php"
  #line: 44
  trace: {
    ./vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php:44 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php:971 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php:719 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php:376 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php:178 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php:155 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php:88 { …}
    ./vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php:98 { …}
    ./vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php:331 { …}
    ./vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/MappingDriverChain.php:79 { …}
    ./vendor/doctrine/doctrine-bundle/Mapping/MappingDriver.php:45 { …}
    ./vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:134 { …}
    ./vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataFactory.php:19 { …}
    ./vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php:382 { …}
    ./vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php:251 { …}
    ./vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:303 { …}
    ./var/cache/dev/ContainerX9n3NQZ/EntityManager_9a5be93.php:94 {
      ContainerX9n3NQZ\EntityManager_9a5be93->getClassMetadata($className)^
      › 
      ›     return $this->valueHolderda610->getClassMetadata($className);
      › }
      arguments: {
        $className: "App\Entity\App\City"
      }
    }
    ./vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php:45 { …}
    ./src/Repository/App/CityRepository.php:26 { …}
    ./var/cache/dev/ContainerX9n3NQZ/getCityRepositoryService.php:27 { …}
    ./var/cache/dev/ContainerX9n3NQZ/App_KernelDevDebugContainer.php:525 { …}
    ./var/cache/dev/ContainerX9n3NQZ/getCityServiceService.php:23 { …}
    ./var/cache/dev/ContainerX9n3NQZ/App_KernelDevDebugContainer.php:525 { …}
    ./var/cache/dev/ContainerX9n3NQZ/getDoctrine_FixturesLoadCommandService.php:43 { …}
    ./var/cache/dev/ContainerX9n3NQZ/App_KernelDevDebugContainer.php:525 { …}
    ./vendor/symfony/dependency-injection/Container.php:422 { …}
    ./vendor/symfony/dependency-injection/Argument/ServiceLocator.php:42 { …}
    ./vendor/symfony/console/CommandLoader/ContainerCommandLoader.php:45 { …}
    ./vendor/symfony/console/Application.php:551 { …}
    ./vendor/symfony/console/Application.php:519 { …}
    ./vendor/symfony/framework-bundle/Console/Application.php:126 { …}
    ./vendor/symfony/console/Application.php:664 { …}
    Symfony\Component\Console\Application->Symfony\Component\Console\{closure}() {}
    ./vendor/symfony/console/Application.php:665 { …}
    ./vendor/symfony/framework-bundle/Console/Application.php:116 { …}
    ./vendor/symfony/console/Application.php:254 { …}
    ./vendor/symfony/framework-bundle/Console/Application.php:82 { …}
    ./vendor/symfony/console/Application.php:166 { …}
    ./bin/console:43 { …}
  }
}

这是城市实体:

<?php

namespace App\Entity\App;

use App\DBAL\Types\Geolocation\Point;
use App\Entity\App\Graveyard;
use App\Repository\App\CityRepository;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

/**
 * @ORM\Entity(repositoryClass=CityRepository::class)
 * @ORM\Table (name="location", schema="app")
 */
class City
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column (type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $country;

    /**
     * @ORM\OneToMany(targetEntity=Company::class, mappedBy="city", cascade="persist")
     */
    private $companies;

    /**
     * @ORM\OneToMany(targetEntity=Graveyard::class, mappedBy="city", cascade="persist")
     */
    private $graveyards;

    /**
     * @ORM\OneToMany(targetEntity=FuneralParlor::class, mappedBy="city", cascade="persist")
     */
    private $funeralParlors;

    /**
     * @ORM\OneToMany(targetEntity=AdvertisementTransfer::class, mappedBy="city")
     */
    private $advertisementTransfers;

    /**
     * @ORM\OneToMany(targetEntity=Crematorium::class, mappedBy="city")
     */
    private $crematoria;

    /**
     * @ORM\Column(type="point")
     */
    private $coordinate;

    /**
     * @ORM\Column(type="string", length=255, nullable=true, options={"default" : null})
     */
    private $province;

    public function __construct()
    {
        $this->companies = new ArrayCollection();
        $this->graveyards = new ArrayCollection();
        $this->funeralParlors = new ArrayCollection();
        $this->advertisementTransfers = new ArrayCollection();
        $this->crematoria = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getCountry(): ?string
    {
        return $this->country;
    }

    public function setCountry(?string $country): self
    {
        $this->country = $country;

        return $this;
    }

    /**
     * @return Collection|Company[]
     */
    public function getCompanies(): Collection
    {
        return $this->companies;
    }

    public function addCompany(Company $company): self
    {
        if (!$this->companies->contains($company)) {
            $this->companies[] = $company;
            $company->setCity($this);
        }

        return $this;
    }

    public function removeCompany(Company $company): self
    {
        if ($this->companies->removeElement($company)) {
            // set the owning side to null (unless already changed)
            if ($company->getCity() === $this) {
                $company->setCity(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|Graveyard[]
     */
    public function getGraveyards(): Collection
    {
        return $this->graveyards;
    }

    public function addGraveyard(Graveyard $graveyard): self
    {
        if (!$this->graveyards->contains($graveyard)) {
            $this->graveyards[] = $graveyard;
            $graveyard->setCity($this);
        }

        return $this;
    }

    public function removeGraveyard(Graveyard $graveyard): self
    {
        if ($this->graveyards->removeElement($graveyard)) {
            // set the owning side to null (unless already changed)
            if ($graveyard->getCity() === $this) {
                $graveyard->setCity(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|FuneralParlor[]
     */
    public function getFuneralParlors(): Collection
    {
        return $this->funeralParlors;
    }

    public function addFuneralParlor(FuneralParlor $funeralParlor): self
    {
        if (!$this->funeralParlors->contains($funeralParlor)) {
            $this->funeralParlors[] = $funeralParlor;
            $funeralParlor->setCity($this);
        }

        return $this;
    }

    public function removeFuneralParlor(FuneralParlor $funeralParlor): self
    {
        if ($this->funeralParlors->removeElement($funeralParlor)) {
            // set the owning side to null (unless already changed)
            if ($funeralParlor->getCity() === $this) {
                $funeralParlor->setCity(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|AdvertisementTransfer[]
     */
    public function getAdvertisementTransfers(): Collection
    {
        return $this->advertisementTransfers;
    }

    public function addAdvertisementTransfer(AdvertisementTransfer $advertisementTransfer): self
    {
        if (!$this->advertisementTransfers->contains($advertisementTransfer)) {
            $this->advertisementTransfers[] = $advertisementTransfer;
            $advertisementTransfer->setCity($this);
        }

        return $this;
    }

    public function removeAdvertisementTransfer(AdvertisementTransfer $advertisementTransfer): self
    {
        if ($this->advertisementTransfers->removeElement($advertisementTransfer)) {
            // set the owning side to null (unless already changed)
            if ($advertisementTransfer->getCity() === $this) {
                $advertisementTransfer->setCity(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|Crematorium[]
     */
    public function getCrematoria(): Collection
    {
        return $this->crematoria;
    }

    public function addCrematorium(Crematorium $crematorium): self
    {
        if (!$this->crematoria->contains($crematorium)) {
            $this->crematoria[] = $crematorium;
            $crematorium->setCity($this);
        }

        return $this;
    }

    public function removeCrematorium(Crematorium $crematorium): self
    {
        if ($this->crematoria->removeElement($crematorium)) {
            // set the owning side to null (unless already changed)
            if ($crematorium->getCity() === $this) {
                $crematorium->setCity(null);
            }
        }

        return $this;
    }

    public function getCoordinate(): Point
    {
        return $this->coordinate;
    }

    public function setCoordinate($coordinate): self
    {
        $this->coordinate = $coordinate;

        return $this;
    }

    public function toJsonArray(): array
    {
        $coordinate = $this->getCoordinate();
        return [
            "id" => $this->getId(),
            "name" => $this->getName(),
            "country" => $this->getCountry(),
            "coordinate" => $coordinate->toJsonArray()
        ];
    }

    public function getProvince(): ?string
    {
        return $this->province;
    }

    public function setProvince(?string $province): self
    {
        $this->province = $province;

        return $this;
    }
}

城市资料库:

<?php

namespace App\Repository\App;

use App\DBAL\Types\Geolocation\Point;
use App\Entity\App\City;
use App\Exception\City\CityAlreadyExistException;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\DBAL\FetchMode;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @method City|null find($id, $lockMode = null, $lockVersion = null)
 * @method City|null findOneBy(array $criteria, array $orderBy = null)
 * @method City[]    findAll()
 * @method City[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CityRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, City::class);
    }

    /**
     * Get all cities on DDBB
     * @return int|mixed|string
     */
    public function getAllCities() {
        return $this->createQueryBuilder("c")->where('')->orderBy('name')->getQuery()->getResult();
    }

    public function getCityById(int $id): City {
        return $this->createQueryBuilder('c')->where('id = :id')->setParameter('id', $id)->getQuery()->getResult();
    }

    public function getCityByName(string $name): ?City
    {
        $city = $this->createQueryBuilder('c')->where('name = :name')->setParameter('name', $name)->getQuery()->getResult();
        return $city === null ? null : $city;
    }

    /**
     * @throws CityAlreadyExistException
     */
    public function createCity(City $city): ?City
    {
        try {
            $entityManager = $this->getEntityManager();
            $entityManager->persist($city);
            $entityManager->flush();
            return $city;
        } catch (ORMException $e) {
            throw new CityAlreadyExistException(sprintf("City %s already exist", $city->getName()));
        }
    }

    public function calculateDistance(City $city, $lat, $lon)
    {

        $SQL = "
            SELECT (ST_Distance(ST_MakePoint({$lat}, {$lon})::geography, ST_MakePoint(coordinate[0], coordinate[1])::geography) / 1000) as distance
            FROM app.location
            WHERE id = {$city->getId()}
        ";

        return $this->executeSQL($SQL);
    }

    public function calculateDistanceBetweenPointInKm(Point $origin, Point $destiny)
    {
        $SQL = "
            SELECT (ST_DISTANCE
            (
                ST_MakePoint({$origin->getLongitude()}, {$origin->getLatitude()})::geography,
                ST_MakePoint({$destiny->getLongitude()}, {$destiny->getLatitude()})::geography
            ) / 1000) as distance
        ";

        return $this->executeSQL($SQL)[0];
    }

    private function executeSQL(string $SQL)
    {
        $em = $this->getEntityManager();
        $stmt = $em->getConnection()->prepare($SQL);
        $stmt->execute();
        return $stmt->fetchAll(FetchMode::COLUMN);
    }
}

服务实体存储库(这是 doctrine 和 symfony 的默认设置):

class ServiceEntityRepository extends EntityRepository implements ServiceEntityRepositoryInterface
{
    /**
     * @param string $entityClass The class name of the entity this repository manages
     * @psalm-param class-string<T> $entityClass
     */
    public function __construct(ManagerRegistry $registry, string $entityClass)
    {
        $manager = $registry->getManagerForClass($entityClass);

        if ($manager === null) {
            throw new LogicException(sprintf(
                'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata.',
                $entityClass
            ));
        }

        parent::__construct($manager, $manager->getClassMetadata($entityClass));
    }
}

已解决 - 经过时间和耐心的搜索,我发现了一个 ORM 符号错误。 composer json 文件被队友更新了,新版本的级联必须带括号,有一个地方是打开的但不是关闭的。