Skip to content

Incorrect work with custom type in class table inheritance #7561

Open
@voodoo-dn

Description

@voodoo-dn

Bug Report

App\Domain\Payment\Model\AbstractOrder:
    type: entity
    repositoryClass: App\Domain\Payment\Repository\OrderRepository
    table: payment_orders
    inheritanceType: JOINED
    discriminatorColumn:
        name: type
        type: string
    discriminatorMap:
        card: App\Domain\Payment\Model\CardOrder
        withdraw: App\Domain\Payment\Model\WithdrawOrder
    id:
        id:
            type: uuid
            unique: true
    fields:
        operation:
            type: order_operation
            nullable: false
        status:
            type: order_status
            nullable: false
        description:
            type: string
            nullable: true
        createdAt:
            type: datetime_immutable
            nullable: false
        updatedAt:
            type: datetime_immutable
            nullable: true
        clientIp:
            type: string
            nullable: true
        clientUserAgent:
            type: string
            nullable: true
    manyToOne:
        user:
            targetEntity: App\Domain\User\UserCore\Model\User
            onDelete: CASCADE
        paymentSystem:
            targetEntity: App\Domain\Payment\Model\PaymentSystem
            onDelete: CASCADE
App\Domain\Payment\Model\CardOrder:
    type: entity
    table: payment_card_orders
    fields:
        amount:
            type: decimal
            precious: 10
            scale: 2
            nullable: false
    manyToOne:
        currency:
            targetEntity: App\Domain\Payment\Model\Currency
            onDelete: CASCADE
App\Domain\Payment\Model\WithdrawOrder:
    type: entity
    table: payment_withdraw_orders
    fields:
        amount:
            type: decimal
            precious: 10
            scale: 2
            nullable: false
        confirmationStatus:
            type: withdraw_order_confirmation_status
            nullable: false
    manyToOne:
        currency:
            targetEntity: App\Domain\Payment\Model\Currency
            onDelete: CASCADE
        confirmedBy:
            targetEntity: App\Domain\User\UserCore\Model\User
            onDelete: CASCADE
<?php

declare(strict_types=1);

namespace App\Representation\Database\Payment\Doctrine\DBAL\Type;

use App\Domain\Payment\Model\ConfirmationStatus;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;

class ConfirmationStatusType extends Type
{
    /**
     * @param mixed            $value
     * @param AbstractPlatform $platform
     *
     * @return string
     *
     * @throws ConversionException
     */
    public function convertToDatabaseValue($value, AbstractPlatform $platform): string
    {
        if (!$value instanceof ConfirmationStatus) {
            throw new ConversionException(\sprintf(
                'Value must be instance of "%s", instance "%s" given',
                ConfirmationStatus::class,
                \is_object($value) ? \get_class($value) : \gettype($value)
            ));
        }

        /* @var ConfirmationStatus $value */
        return $value->getValue();
    }

    /**
     * @param mixed            $value
     * @param AbstractPlatform $platform
     *
     * @return ConfirmationStatus
     *
     * @throws ConversionException
     */
    public function convertToPHPValue($value, AbstractPlatform $platform): ConfirmationStatus
    {
        try {
            return new ConfirmationStatus($value);
        } catch (\Throwable $e) {
            throw new ConversionException($e->getMessage(), $e->getCode(), $e);
        }
    }

    /**
     * @param array            $fieldDeclaration
     * @param AbstractPlatform $platform
     *
     * @return string
     */
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        return 'withdraw_order_confirmation_status';
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return 'withdraw_order_confirmation_status';
    }
}

When I fetch order by ID, CardOrder must be returned. But in Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator::hydrateRowData in $sqlResult argument passed array with columns from WithdrawOrder(e.g. confirmation_status = null, confirmed_by = null), and Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator::hydrateRowData(row 130), throws exception, because my custom doctrine type not expects null value.

Q A
BC Break yes/no
Version 2.6.2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions