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

[RFC] Follow-up on doctrine/collections Order enum #11313

Open
greg0ire opened this issue Feb 26, 2024 · 14 comments
Open

[RFC] Follow-up on doctrine/collections Order enum #11313

greg0ire opened this issue Feb 26, 2024 · 14 comments

Comments

@greg0ire
Copy link
Member

In doctrine/collections#389, I introduced a new enum: Order

What should we use it for inside the ORM?

  • The OrderBy attribute: this is a clear use case where we should switch to that enum, since it has to do with collections
  • QueryBuilder::orderBy() / addOrderBy(): this one is less clear to me… when you select several entities, you don't get a collection, but a list, right?
  • DQL : I don't think we should allow it inside DQL, it's cumbersome
  • Expr\OrderBy: I'm not sure we should do it here either.

@derrabus @SenseException any thoughts?

Cc @ThomasLandauer

@ThomasLandauer
Copy link
Contributor

QueryBuilder::orderBy() / addOrderBy() was the place where I initially suggested to get rid of those strings (#11263) - so this is a must IMO :-)

@ThomasLandauer
Copy link
Contributor

Anybody who was using ->orderBy('foo', Criteria::ASC) is kinda stuck now (after upgrading to doctrine/collections 2.2.0). PHPStan is going crazy with:

Fetching deprecated class constant ASC of class Doctrine\Common\Collections\Criteria: use Order::Ascending instead

But the enum isn't working yet:

Parameter #2 $order of method Doctrine\ORM\QueryBuilder::orderBy() expects string|null, Doctrine\Common\Collections\Order::Ascending given.

This can be overcome by using Order::Ascending->value (as you said in doctrine/collections#389 (comment)), but if the current situation is going to stay for longer than just a few days, then the deprecation message should be changed to:

... use Order::Ascending or Order::Ascending->value instead

@greg0ire
Copy link
Member Author

greg0ire commented Feb 27, 2024

@ThomasLandauer using Order::Ascending->value would solve the error, but there would still be a deprecation because ultimately, it's a string. We need to modify our public API to allow Order. Worse, it would mean users would have to first migrate to Order::Ascending->value, and then to Order::Ascending. 2 migrations instead of one.

@derrabus in doctrine/collections#389 (comment), I suggested we give the ORM a chance to upgrade, but I failed to make my point, so let me elaborate. What makes that upgrade so special that we should change the way we do things?

I think the main difference with other PRs where we add an API and immediately deprecate the other API is that we expect the users of doctrine/orm to use doctrine/collections's API when interacting with our own API, and don't support (yet) using the non-deprecated API. I suggest we remove the deprecation layer until we and probably the ODM folks (Cc @malarzm) figure out what changes to conduct in the ORM and the ODM. Or at least, the parts that could be referred to by our users, such as the Criteria::* constants.

@derrabus
Copy link
Member

It's a bit unfortunate that the ORM uses constants from a different package in their public API. For ORM 2.19, we could add replacement constants to the ORM codebase. Supporting the Order enum directly is a feature I don't see for ORM 2.x anymore, tbh.

@derrabus
Copy link
Member

Also, we have to be careful: Collections is not the only abstraction that we're dealing with here. When talking about the query builder, we're probably closer to the Persistence abstraction which also declares orderings as strings at the moment:

https://github.com/doctrine/persistence/blob/e7cf418cafe83a75f7a7096cc9fa890b201d28f1/src/Persistence/ObjectRepository.php#L42-L43

It would be a bit weird if the query builder and the repository used different abstractions for ordering stuff.

@NMe84
Copy link

NMe84 commented Feb 28, 2024

The OrderBy attribute: this is a clear use case where we should switch to that enum, since it has to do with collections

I wouldn't switch, I'd support both for a while to give users time to adjust their code. Should be easy enough to accept string|Order as a parameter, right?

That said, the current situation leaves people with either a deprecation (which is very annoying in PhpUnit) or very ugly code in the form of something like this:

#[OrderBy(['id' => Order::Ascending->value])]

...where previously this much shorter and more readable version was usable:

#[OrderBy(['id' => Criteria::ASC])]

Supporting the Order enum directly is a feature I don't see for ORM 2.x anymore, tbh.

Then either the deprecation should go (because you can't fix the deprecation in an acceptable way in 2.x) or the functions requiring a string should also accept the enum, as I just suggested.

@curry684
Copy link

Supporting the Order enum directly is a feature I don't see for ORM 2.x anymore, tbh.

...thus forcing a double migration on all of us, migrating to Order::Ascending->value first in 2.x, and then breaking/deprecating all our code again when making the switch to 3?

@derrabus
Copy link
Member

derrabus commented Feb 28, 2024

I mean, we could un-deprecate the constants, which basically means that Collections 3 would ship two constants it has no use for. I could live with that.

@curry684
Copy link

curry684 commented Feb 28, 2024

Preferably the constants would remain gone in 3 as you're otherwise going to be stuck with them sort of forever. I would just like a better migration path than we have now. For example (without really looking into the current code) we could consider introducing the Order enum as a static final class in 2.x, so Order::Ascending actually is a real string, and then in 3.x leave it as a real enum which is handled correctly as an enum everywhere. With something like that the final 2.x release would present a real upgrade path to 3 while being code-wise compatible.

This would interlock the major versions of Collections and ORM, but I doubt that's really a bad thing (ORM 3.x only works with major X or higher, ORM 2.x only works with major Y or lower).

Alternatively I don't really see why we wouldn't support the enums in 2.x, it can't be that much work to support both...?

@derrabus
Copy link
Member

Preferably the constants would remain gone in 3 as you're otherwise going to be stuck with them sort of forever.

I think, I can live with the maintenance burden of two unused constants, really.

I would just like a better migration path than we have now.

Then don't use the constants for the query builder or metadata mapping. Use strings, as it is officially documented. The constants are part of the Collections package, meant for use with the Criteria class of that package. They just conveniently happen to match the values that the query builder and the mapping attributes accept.

The "migration path" that you're discussing is actually a workaround for people that have used those constants in an undocumented way, outside of their scope.

By keeping the constants around, we would give people who want to remain on ORM 2 (for what reason ever) the possibility keep everything as it is. Why's that a problem?

@curry684
Copy link

The "migration path" that you're discussing is actually a workaround for people that have used those constants in an undocumented way, outside of their scope.

Fair enough, I forgot about that perspective and indeed this will likely not affect that many people 😄

@malarzm
Copy link
Member

malarzm commented Mar 3, 2024

until we and probably the ODM folks (Cc @malarzm) figure out what changes to conduct in the ORM and the ODM.

@greg0ire sorry for taking long to respond, I was on vacations :) You can take ODM out of equation for two reasons:

  1. ODM's query builder is accepting 1 and -1 as well as asc and desc for sorting. Ints are used by MongoDB and are first-class citizens for us
  2. ODM never got Selectable and therefore Criteria implemented (PersistentCollection doesn't have the matching method mongodb-odm#929 to have linked topics) 🙈

So feel free to do whatever is best for ORM here :)

@bobvandevijver
Copy link
Contributor

bobvandevijver commented Mar 4, 2024

The "migration path" that you're discussing is actually a workaround for people that have used those constants in an undocumented way, outside of their scope.

To chime in here: while it might be outside their scope, it is not undocumented. See https://www.doctrine-project.org/projects/doctrine-orm/en/3.0/reference/working-with-associations.html#filtering-collections, where the constant is used in the official documentation.

edit: after submitting this, I see it is actually a Criteria method, and not an ORM method... It is confusing, caused by all those untyped strings 😄 I would love to see either the enum to be supported, or an additional enum in the ORM namespace itself.

@VincentLanglet
Copy link
Contributor

It's a bit unfortunate that the ORM uses constants from a different package in their public API. For ORM 2.19, we could add replacement constants to the ORM codebase.

Just my two cent, but I agree with this point.
doctrine/collections is not, at first sight, a Db-related library so it feel weird to me that doctrine/orm use constants/enums from doctrine/collections fro Db-related directive like "OrderBy".

So far I solved the "deprecated" issue by using again the string value 'ASC' or 'DESC',
but I would have expected a constant directly from doctrine/orm like Expr\Join::WITH,

Doctrine\ORM\Query\Expr\OrderBy::ASC;
Doctrine\ORM\Query\Expr\OrderBy::DESC;

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

8 participants