Conversation
|
@robertpustulka I remember arguing about this back when I knew nothing. I hope this looks reasonable. |
db87083 to
e8a8e13
Compare
e8a8e13 to
f69662c
Compare
6d5903b to
7c78e5b
Compare
| /** @psalm-suppress ReferenceReusedFromConfusingScope */ | ||
| $options = $options + $opts; | ||
| } else { | ||
| array_unshift($args, $opts); |
There was a problem hiding this comment.
Users will receive a PHP error if they don't have a proper array parameter for options. I can't create exceptions for all edge cases leading to this in all finders so going to rely on PHP errors to tell users their finder can't support options.
| $reflected = new ReflectionFunction($callable); | ||
| $param = $reflected->getParameters()[1] ?? null; | ||
| if ($param?->name === 'options' && !$param->isDefaultValueAvailable()) { | ||
| $args = [[]]; |
There was a problem hiding this comment.
This adds an empty options array when calling find with no arguments and the finder expects $options.
An example of this is Table::findAll() and calling it with ->find().
There was a problem hiding this comment.
It's quite unfortunate that the $options arg doesn't default to an empty array currently. It would have made no practical difference.
Perhaps we can add the default value now to core finders and throw a warning when this if returns true so that we can at least remove this reflection in the future.
There was a problem hiding this comment.
Perhaps we can add the default value now to core finders and throw a warning when this if returns true so that we can at least remove this reflection in the future.
This sounds like a great inclusion into 4.5.0. We could do the detection and deprecation warning there, and in 5.x we can enforce a default options value, or we can start spreading options as named parameters.
I think the point I want to make, is that if we're going to break compatibility why not do what would be best going forward, and then we can figure out how we add deprecations and backporting to 4.5 to make the upgrade process understandable and incrementally adoptable.
7c78e5b to
4c98c21
Compare
| $reflected = new ReflectionFunction($callable); | ||
| $param = $reflected->getParameters()[1] ?? null; | ||
| if ($param?->name === 'options' && !$param->isDefaultValueAvailable()) { | ||
| $args = [[]]; |
There was a problem hiding this comment.
It's quite unfortunate that the $options arg doesn't default to an empty array currently. It would have made no practical difference.
Perhaps we can add the default value now to core finders and throw a warning when this if returns true so that we can at least remove this reflection in the future.
4c98c21 to
23635af
Compare
23635af to
bd790ac
Compare
| if ($opts) { | ||
| if (is_array($options)) { | ||
| /** @psalm-suppress ReferenceReusedFromConfusingScope */ | ||
| $options = $options + $opts; |
There was a problem hiding this comment.
Do we use options after this merge? Or are you relying on the ref from the previous block to mutate the options in-place? We should leave a comment for future us if that is the solution that is used here.
| $options = null; | ||
| if ($args) { | ||
| if (array_key_exists(0, $args)) { | ||
| $options = &$args[0]; | ||
| } elseif (array_key_exists('options', $args)) { | ||
| $options = &$args['options']; | ||
| } | ||
| } | ||
|
|
||
| if ($opts) { | ||
| if (is_array($options)) { | ||
| /** @psalm-suppress ReferenceReusedFromConfusingScope */ | ||
| $options = $options + $opts; | ||
| } else { | ||
| array_unshift($args, $opts); | ||
| } | ||
| } |
There was a problem hiding this comment.
Should there be a function for this? There are a few implementations of this in these changes. Having a function might let us contain the reference tricks into code into that is less frequently changed and easier to remove when the time comes.
| $reflected = new ReflectionFunction($callable); | ||
| $param = $reflected->getParameters()[1] ?? null; | ||
| if ($param?->name === 'options' && !$param->isDefaultValueAvailable()) { | ||
| $args = [[]]; |
There was a problem hiding this comment.
Perhaps we can add the default value now to core finders and throw a warning when this if returns true so that we can at least remove this reflection in the future.
This sounds like a great inclusion into 4.5.0. We could do the detection and deprecation warning there, and in 5.x we can enforce a default options value, or we can start spreading options as named parameters.
I think the point I want to make, is that if we're going to break compatibility why not do what would be best going forward, and then we can figure out how we add deprecations and backporting to 4.5 to make the upgrade process understandable and incrementally adoptable.
| * Here, the finder "findByCategory" does have an `$options` parameter: | ||
| * | ||
| * ``` | ||
| * function findByCategory(SelectQuery $query, array $options, int $category): SelectQuery |
There was a problem hiding this comment.
In the spirit of doing what is best going forward, I would like to propose we drop support for $options entirely. Instead we only support named parameters in 5.x. This is a meaningful break in backwards compatibility, but I think it will provide a long term improvement in developer experience. With named parameters we get typed checked optional parameter support. It's everything we ever wanted from $options.
I feel like deprecating $options in 4.5 is something we can do. Users that would want to upgrade to 5.x will need to upgrade PHP before they can use named parameters. I don't feel bad about this as encouraging them to upgrade PHP will be something they would need to do anyways.
There was a problem hiding this comment.
Making $options options is definitely complicated. It looks like code we don't want to support.
There was a problem hiding this comment.
Are you suggesting we drop $options and force users to call applyOptions() directly? I'm a little confused when you say drop it but then say support it with named parameters.
There was a problem hiding this comment.
I would be okay with dropping $options if we retain a way to still be able to pass values for the query clauses to the find() call. Something like find('foo', select: $a, order: $b, custom: 'bar').
There was a problem hiding this comment.
We could do that. All of the query-specific options would then become reserved keywords for parameter names.
| $query->applyOptions($options); | ||
| /** @psalm-suppress ReferenceReusedFromConfusingScope */ | ||
| $options = $query->getOptions(); |
There was a problem hiding this comment.
We should do this after the options juggling function is completed.
|
We don't want to commit this optional $options implementation. Will look for alternatives. |
refs #12787
This does not remove the$optionsparameter. Users must specify an empty array if they want to by-pass it.The
$optionsparameter is now optional.