Суть проблемы следующая.
Есть 2 сущности и они связаны One-To-Many
class Shipping
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var ShippingStatus
*
* @ORM\Column(type="shipping_status")
*/
private $status;
/**
* @var OrderId
*
* @ORM\Column(name="orderId", type="order_id", unique=true)
*/
private $orderId;
/**
* @var \DateTimeImmutable
* @ORM\Column(name="createDate", type="datetimetz_immutable")
*/
private $createDate;
/**
* История
*
* @var Collection
* @ORM\OneToMany(targetEntity="PointHistory", mappedBy="shipping", cascade={"all"}, orphanRemoval=true)
*
*/
private $pointsHistory;
public function __construct(OrderId $orderId)
{
$this->orderId = $orderId;
$this->createDate = new \DateTimeImmutable();
$this->status = new ShippingStatus(ShippingStatus::IN_PROGRESS);
$this->pointsHistory = new ArrayCollection();
}
/**
* Добавить запись в историю.
*
* @param int $pointId
* @param \DateTimeImmutable $createDate
* @param PointStatus $pointStatus
*
* @throws ValidationError
*/
public function addPointHistory(int $pointId, \DateTimeImmutable $createDate, PointStatus $pointStatus): void
{
$history = new PointHistory($pointId, $createDate, $this, $pointStatus);
$this->pointsHistory->add($history);
}
/**
* @return PointHistory[]
*/
public function getHistory(): array
{
return $this->pointsHistory->toArray();
}
}
class PointHistory
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var PointStatus
*
* @ORM\Column(type="point_status")
*/
private $status;
/**
* @ORM\Column(name="pointId", type="integer")
*/
private $pointId;
/**
* @var \DateTimeImmutable
* @ORM\Column(name="createDate", type="datetimetz_immutable")
*/
private $createDate;
/**
* @ORM\ManyToOne(targetEntity="driverApp\src\modules\Order\entities\shipping\Shipping", inversedBy="pointsHistory")
* @ORM\JoinColumn(name="shippingId", nullable=false, onDelete="CASCADE")
*/
private $shipping;
public function __construct(int $pointId, \DateTimeImmutable $createDate, Shipping $shipping, PointStatus $status)
{
$this->pointId = $pointId;
$this->shipping = $shipping;
$this->createDate = $createDate;
$this->status = $status;
}
}
Возникала проблема с кавычками, но я ее решил вот таким магическим способом
class QuotedStrategy implements QuoteStrategy
{
private function quote($token, AbstractPlatform $platform)
{
switch ($platform->getName()) {
case 'postgresql':
default:
return $this->quoteIdentifier($token);
}
}
private function quoteIdentifier($str)
{
if (strpos($str, '.') !== false) {
$parts = array_map([$this, 'quoteSingleIdentifier'], explode('.', $str));
return implode('.', $parts);
}
return $this->quoteSingleIdentifier($str);
}
private function quoteSingleIdentifier($str)
{
$c = '"';
return $c . str_replace($c, $c . $c, $str) . $c;
}
// add quoting to appropriate methods
public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform)
{
return $this->quote($class->fieldMappings[$fieldName]['columnName'], $platform);
}
public function getTableName(ClassMetadata $class, AbstractPlatform $platform)
{
return $class->table['name'];
}
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform)
{
return $definition['sequenceName'];
}
public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
{
return $this->quote($joinColumn['name'], $platform);
}
public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
{
return $joinColumn['referencedColumnName'];
}
public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform)
{
return $association['joinTable']['name'];
}
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform)
{
return $class->identifier;
}
public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null)
{
return $platform->getSQLResultCasing($columnName . '_' . $counter);
}
}
Но на этом проблемы не закончились. Сейчас при попытке получить данные связанной сущности
PointHistory, вылетает ошибка
An exception occurred while executing 'SELECT t0.\"id\" AS id_1, t0.\"status\" AS status_2, t0.\"pointId\" AS pointid_3, t0.\"createDate\" AS createdate_4, t0.\"shippingId\" AS shippingid_5 FROM da_point_status_history t0 WHERE t0.shippingId = ?' with params [35]:\n\nSQLSTATE[42703]: Undefined column: 7 ERROR: column t0.shippingid does not exist\nLINE 1: ...hippingid_5 FROM da_point_status_history t0 WHERE t0.shippin...\n ^\nHINT: Perhaps you meant to reference the column \"t0.shippingId\"
вот тут подробнее
SELECT t0.\"id\" AS id_1, t0.\"status\" AS status_2, t0.\"pointId\" AS pointid_3, t0.\"createDate\" AS createdate_4, t0.\"shippingId\" AS shippingid_5 FROM da_point_status_history t0 WHERE t0.shippingId
Т.е. Доктрина при построении criteria не проставляет кавычки для названий полей, в моем случае
shippingId
Как завтавить доктрину это делать? Я не нашел в документации ничего подобного.
Зато нашел код , где это все делается
BasicEntityPersister.php
$field = $sourceClass->fieldNames[$sourceKeyColumn];
$value = $sourceClass->reflFields[$field]->getValue($sourceEntity);
$criteria[$tableAlias . "." . $targetKeyColumn] = $value;
$parameters[] = [
'value' => $value,
'field' => $field,
'class' => $sourceClass,
];
Я уверен, что я не первый, что с этим столкнулся, но ответов пока не нашел нигде. Ткните куда смотреть.