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

[9.x] Added callable support to operatorForWhere on Collection #41414

Merged
merged 3 commits into from
Mar 10, 2022
Merged

[9.x] Added callable support to operatorForWhere on Collection #41414

merged 3 commits into from
Mar 10, 2022

Conversation

eusonlito
Copy link
Contributor

Added callable support to operatorForWhere.

Currently only Collection methods where and whereFirst are used without callable support.

Adding callable to operatorForWhere allow complex usages as:

$city = $cities->firstWhere(fn ($city) => $city->state->available && ($city->state->id === $stateId));

or

$state = $states->firstWhere(fn ($state) => (bool)$state->cities->firstWhere('id', $cityId));

Added `callable` support to `operatorForWhere`.

Currently only Collection methods `where` and `whereFirst` are used without `callable` support.

Adding callable to `operatorForWhere` allow complex usages as:

```php
$city = $cities->firstWhere(fn ($city) => $city->state->available && ($city->state->id === $stateId));
```
or
```php
$state = $states->firstWhere(fn ($state) => (bool)$state->cities->firstWhere('id', $cityId));
```
@taylorotwell
Copy link
Member

Hmm, what all methods does this affect?

@eusonlito
Copy link
Contributor Author

Only where and firstWhere.

Method every has a previous parameter check when only one argument:

public function every($key, $operator = null, $value = null)
{
if (func_num_args() === 1) {
$callback = $this->valueRetriever($key);

Same as partition:

public function partition($key, $operator = null, $value = null)
{
$passed = [];
$failed = [];
$callback = func_num_args() === 1
? $this->valueRetriever($key)
: $this->operatorForWhere(...func_get_args());

Same sole method on LazyCollection:

public function sole($key = null, $operator = null, $value = null)
{
$filter = func_num_args() > 1
? $this->operatorForWhere(...func_get_args())
: $key;

firstOrFail on LazyCollection:

public function firstOrFail($key = null, $operator = null, $value = null)
{
$filter = func_num_args() > 1
? $this->operatorForWhere(...func_get_args())
: $key;

And contains on LazyCollection:

public function contains($key, $operator = null, $value = null)
{
if (func_num_args() === 1 && $this->useAsCallable($key)) {
$placeholder = new stdClass;

@taylorotwell
Copy link
Member

Would it be safer to just modify where and firstWhere directly instead of this method just to be sure?

@taylorotwell
Copy link
Member

Hmm - I guess this looks OK.

@taylorotwell taylorotwell merged commit 59c27e1 into laravel:9.x Mar 10, 2022
@eusonlito
Copy link
Contributor Author

@taylorotwell I will add a new check, because is_callable can get a string (like trim) and return true.

I will send a new commit changing if (is_callable($key)) { with if ($this->useAsCallable($key)).

Also a new test will be added using a callable string.

@sebdesign
Copy link
Contributor

What's the difference from the first method?

$city = $cities->first(
    fn ($city) => $city->state->available && ($city->state->id === $stateId)
);

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

Successfully merging this pull request may close these issues.

3 participants