Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.13.2 - 2.13.3 | Enum column - Object of class x could not be converted to x #10066

Closed
ThomasGoffart opened this issue Sep 26, 2022 · 14 comments

Comments

@ThomasGoffart
Copy link

ThomasGoffart commented Sep 26, 2022

Bug Report

Q A
BC Break yes
Version 2.13.2 - 2.13.3

Summary

When having an enum column like this:

#[ORM\Column(enumType: Color::class)]
private Color $color;

This error occurred when you load the entity from a query from the Query Builder (repository):

Warning: Object of class App\Enum\Color could not be converted to int

Workaround

Downgrade doctrine/orm to 2.13.1 version while waiting for a fix.

@ThomasGoffart ThomasGoffart changed the title 2.13.2 Enum column error 2.13.2 Enum column - Object of class x could not be converted to x Sep 26, 2022
@michnovka
Copy link
Contributor

This is also likely to be fixed with #10058 . Please confirm

@NotionCommotion
Copy link

NotionCommotion commented Sep 26, 2022

I am getting the same error, and when I comment out $this->rsm->addEnumResult($columnAlias, $mapping['enumType']); on line number 1525 added by this commit, I no longer get the error.

namespace Doctrine\ORM\Query;
class SqlWalker implements TreeWalker
{
    public function walkSelectExpression($selectExpression)
    {
                    ...
                    if (! empty($mapping['enumType'])) {
                        $this->rsm->addEnumResult($columnAlias, $mapping['enumType']);
                    }
                    ...
	}
}

Note that for my case, Doctrine tries to typecast PermissionEnum to an integer

namespace Doctrine\DBAL\Types;
class SmallIntType extends Type implements PhpIntegerMappingType
{
    ...
	public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return $value === null ? null : (int) $value;
    }
    ...
}

resulting in error Warning: Object of class App\\Entity\AccessControl\Acl\PermissionEnum could not be converted to int.

However, as shown below, PermissionEnum is never intended to be directly persisted in the database but only as a subpart in Permission.

namespace App\Doctrine\Types;

use App\Entity\AccessControl\Acl\Permission;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;

final class PermissionType extends Type
{
    private const PERMISSION = 'permission';

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration);
    }

    public function convertToPHPValue($value, AbstractPlatform $platform): mixed
    {
        if (null === $value) {
            return null;
        }

        if (\is_int($value)) {
            return Permission::createFromValue($value);
        }

        throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['int', 'null']);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed
    {
        if (null === $value) {
            return null;
        }

        if ($value instanceof Permission) {
            return $value->getValue();
        }

        throw ConversionException::conversionFailedInvalidType($value, $this->getName(), [Permission::class, 'null']);
    }

    public function requiresSQLCommentHint(AbstractPlatform $platform): bool
    {
        return true;
    }

    public function getName(): string
    {
        return self::PERMISSION;
    }
}
class Permission
{
    private const READ      = 0b0000000011;
    private const CREATE    = 0b0000001100;
    private const MODIFY    = 0b0000110000;
    private const DELETE    = 0b0011000000;
    private const COWORKER  = 0b0100000000; // Not currently used.
    private const OWNER     = 0b1000000000; // Not currently used.

    public function __construct(
        private ?PermissionEnum $read=null,
        private ?PermissionEnum $create=null,
        private ?PermissionEnum $modify=null,
        private ?PermissionEnum $delete=null,
        private ?bool $restrictToOwner=null,
        private ?bool $coworkers=null
    ) {
    }

    public function getValue(): ?int
    {
        if($this->hasNullValue()) {
            throw new Exception('Permission has NULL values.');
        }
        $rs = $this->read->value | $this->create->value << 2 | $this->modify->value << 4 | $this->delete->value << 6;
        $rs = $this->coworkers ? $rs | self::COWORKER : $rs & ~self::COWORKER;

        return $this->restrictToOwner ? $rs | self::OWNER : $rs & ~self::OWNER;
    }
}
enum PermissionEnum: int
{
    case public     = 0b00;
    case owner      = 0b01;
    case restrict   = 0b10;
    case extra      = 0b11; 
}

@derrabus
Copy link
Member

@NotionCommotion Please provide a small application or a functional test case that reproduces your issue.

@kshtompel
Copy link

kshtompel commented Sep 27, 2022

I see fix of this issue in this commit
d69a0fa
but it was not released as 2.13.3
when to expect the release?

@devtronic
Copy link

See also #10057

@NotionCommotion
Copy link

@derrabus I spent about 4 hours yesterday trying to isolate the issue so I may provide it, but was unsuccessful. Didn't try everything such as checking whether some 3rd party app such as doctrine extensions is also involved. Any thoughts how one best troubleshoots and isolates issues such as this?

@kshtompel
Copy link

@ThomasGoffart is it resolved now?

@greg0ire greg0ire closed this as completed Oct 9, 2022
@greg0ire
Copy link
Member

greg0ire commented Oct 9, 2022

Let me know if it is not resolved and I will reopen this.

@ThomasGoffart
Copy link
Author

This issue is still on my side (doctrine/orm v2.13.3 )

@ThomasGoffart ThomasGoffart changed the title 2.13.2 Enum column - Object of class x could not be converted to x 2.13.2 - 2.13.3 | Enum column - Object of class x could not be converted to x Oct 11, 2022
@michnovka
Copy link
Contributor

Can you please provide your Color enum definition?

@ThomasGoffart
Copy link
Author

This error occurs with a classic enum.
Here is a common example of enum that causes this problem.

<?php

namespace App\Enum;

enum Color: int {

    case Red = 1;
    case Green = 2;
    case Blue = 3;

}

@michnovka
Copy link
Contributor

Just out of curiosity, when using string backed enums, can you also reproduce the issue?

@ThomasGoffart
Copy link
Author

Yes, I tested it and it also happens.

@michnovka
Copy link
Contributor

michnovka commented Oct 11, 2022

Do these tests you submitted fail - #10111 ?

If they do not, can you please push PR with failing tests? I will work on it then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants