Open xkzl opened 3 months ago
I have restore the minimal code to make use of comment hint to detect EnumType based on (DC2Type:[xxx])
information as it was implemented before 4134b86cb986f6fc68fe9ba7c8a7416debfa22bd
.
It allows to fix this issue implementing EnumType using EventListener::postGenerationSchema()
.
Please consider it, this was very useful feature and removed without much information to fix it.
But can't you solve your problem by creating custom types? https://www.doctrine-project.org/projects/doctrine-dbal/en/4.0/reference/types.html#custom-mapping-types
I use EnumType
extensively in my project through custom types, and when testing with dbal4, I had no problems, and there shouldn't be any, because for Doctrine, it will still be int or string (depending on which EnumType you use).
The only thing you need to do when creating a type is to inherit from the parent Type and implement convertToDatabaseValue()
, convertToPHPValue()
, getSQLDeclaration()
, and getBindingType()
.
Adding the type to doctrine is not a problem, this is standard in the documentation.
The problem lies in the conversion back from doctrine to type. Previous behavior was to look for (DC2Type:XXX) in the comment hint. At the moment, the field gets back into 'StringType' instead of the correct 'EnumType', so on request the db schema gets indefinitely upgraded as the diff is triggering update.
Sorry if I misunderstood you, but the Doctrine looks at the type in the same way as it did with DC2Type, that is, you need to create and register the type you need (custom type).
UPD: If you are getting StringType
, it means that you did not create your custom type or did not update it after switching to DBAL4.
Could you please provide an example?
I already highlighted the suppressed lines that are problematic. I don't think there are strong motivations to explain why comment hints have been removed. Looking at the commit there is actually not much explanation of that part and why comment hint has been removed. It seems to be a mixed modification wrapped up in another commit.
I cannot get this EnumType working, but I am sure there must be a way if you say so. I would be happy to give it a try. I added the EnumType to Doctrine configuration, I can use EnumType but this issue is taking place when going from Doctrine to Type. If you can suggest a doctrine event to listen to I would be happy to use it and to have this configured in time, but without this, the only solution I have is to use comment hint.
Comment hint is a quite reasonable feature and using hints in various context is a common practice including for queries. I don't see why we should remove a useful feature if it gives some flexibility to the implementation.
All checks passed but codecov. (is that some key i should be providing ?) Any maintainer please advice 🙏
Regarding CodeCov, you have nothing to do, I reported it here: https://github.com/codecov/codecov-action/issues/1487
Regarding your issue, I think it might have been fixed with last week's 3.8.5 and 4.0.3 release. Have you tried upgrading, and disabling type comments?
@greg0ire As I understand he uses DBAL4, not DBAL3.
@xkzl There is my custom type for int Enums.
enum Status: int
{
case ACTIVE = 1;
case SUSPENDED = 2;
case ARCHIVED = 3;
#[Pure]
public function label(): string
{
return self::getLabel($this);
}
private function getLabel(self $value): string
{
return match ($value) {
self::ACTIVE => 'STATUS_ACTIVE',
self::SUSPENDED => 'STATUS_SUSPENDED',
self::ARCHIVED => 'STATUS_ARCHIVED',
};
}
public static function lists(): array
{
$cases = self::cases();
$statuses = [];
foreach ($cases as $status) {
$statuses[$status->value] = $status->label();
}
return $statuses;
}
}
final class StatusType extends Type
{
final public const string NAME = 'user_user_status';
#[\Override]
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): int
{
return $value instanceof Status ? $value->value : $value;
}
#[\Override]
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Status
{
return !empty($value) ? Status::from($value) : null;
}
#[\Override]
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getSmallIntTypeDeclarationSQL($column);
}
#[\Override]
public function getBindingType(): int
{
return ParameterType::INTEGER;
}
public function getName(): string //I left this method for Symfony phpstorm plugin
{
return self::NAME;
}
}
It works perfectly in DBAL4/ORM3, but I have to extend Type instead of SmallInt how it was in DBAL3, because they moved to strict types.
@berkut1 just to be on the same baseline here is the EnumType definition as proposed by Doctrine documentation https://www.doctrine-project.org/projects/doctrine-orm/en/3.2/cookbook/mysql-enums.html#solution-2-defining-a-type
I am interested to the registration type part and which doctrine event should be used, not really in your custom EnumType definition. How/where do you registered? I think this is the main point.
@greg0ire I just checked and in my latest checks I am using dbal 4.0.3, with orm 3.2.0. Could you advise how to disable type comment ?
Additionally, here is the latest reference to type comment I can find in the documentation and it is from dbal 3.8.5 https://www.doctrine-project.org/projects/doctrine-dbal/en/3.8/explanation/dc2type-comments.html Having a page for 4.0 might be nice such that it would provide smooth example how to transition if not required anymore.
How/where do you registered? I think this is the main point.
I register it through Symfony https://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types
Having a page for 4.0 might be nice such that it would provide smooth example how to transition if not required anymore.
There is no need transition, it just should work if you correctly created your custom types, especially getSQLDeclaration
Types are always disabled in 4.0.x
How/where do you registered? I think this is the main point.
I register it through Symfony
https://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types
Ok so you are not directly using the registration command mentioned in https://www.doctrine-project.org/projects/doctrine-dbal/en/4.0/reference/types.html#custom-mapping-types . Then, I think this is a different situation and it is done via doctrine configuration in your case. I think I better understand the differences between the two situations. My EnumType is part of a bundle. I don't think I can do it your way and I need à to listen to an event. I registered the type at the boot of my bundle using the initial command provided in the custom mapping type (basically Type::addType)
So according to my investigations, this issue is still here for 4.0.3 @greg0ire. So at this time, the only solution I can see is to use comment hints unless I missed something. Would you consider merging this PR @greg0ire, if it doesn't hurt current revisions/progress? If needed, I can additionally provide a test to make sure comment hints can get extracted so it will not be forgotten anymore.
Would you consider merging this PR
DC2 comments are supposed to be completely gone in 4.0.x so… no?
What would be the alternative if we cannot add EnumType to bundles by registering manually through Type:addType on time for correct construction of columns...
Use the enumType
column attribute?
Thanks for trying.
No worries. Also, it seems you can even avoid dealing with enumType
if you use a recent enough version of PHP and the ORM:
As of version 2.11 Doctrine can also automatically map typed properties using a PHP 8.1 enum to set the right type and enumType.
I have yet to find a solution to the issue. Is there any plan to fix or address it? So far, the only fix I've found is the provided file.
Additionally, I'd like to highlight the use case of SetType handling SET() in databases, on top of EnumType.
@xkzl can you check this theory? https://github.com/doctrine/migrations/issues/1441#issuecomment-2227444186 Of course if you use ORM.
yes I can do that, maybe in few days only.
Bug Report
Summary
I add/register my custom EnumType at early stage to doctrine and then I am used to add proper comment hint for EnumType to allow for conversion from StringType to correct EnumType using DC2Type at
EnumSubscriber::postGenerateSchema
event stage; Doctrine was using CommentHint and it was useful. This has been removed from dbal in the commit4134b86cb986f6fc68fe9ba7c8a7416debfa22bd
for some reasons.I cannot find any alternative, but rolling back a minimal code reintroducing comment hint to DC2Type detection for Doctrine to Type conversion. Not doing so creates a diff in the DB schema resulting in a systematic update of the database scheme every time I launch a
doctrine:schema:update
command, due to fictive difference in the type of the columns.Current behaviour
Current behavior, makes db schema update infinitely refreshing.
How to reproduce
Just create a EnumType following; and use
postGenerateSchema
subscriber.Expected behaviour
I would expect to restore in
AbstractSchemaManager.php
:Then restore on every platform,
Unless this was suppressed on purpose, it was very useful feature to incorporate EnumType. If an alternative is possible, please advice.