@dinya17

Почему не работает связь One-To-Many Doctrine в Postgress поле для связи в camelCase?

Суть проблемы следующая.
Есть 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,
            ];


Я уверен, что я не первый, что с этим столкнулся, но ответов пока не нашел нигде. Ткните куда смотреть.
  • Вопрос задан
  • 48 просмотров
Решения вопроса 1
@dinya17 Автор вопроса
В общем пока никто не ответил. Решил это все просто переименованием полей из верблюда в нижнее подчеркивание, все сразу взлетело. Но вот неужели по другому не решить?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы