Skip to content

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

Merged
taylorotwell merged 3 commits into
laravel:9.xfrom
eusonlito:patch-1
Mar 10, 2022
Merged

[9.x] Added callable support to operatorForWhere on Collection#41414
taylorotwell merged 3 commits into
laravel:9.xfrom
eusonlito:patch-1

Conversation

@eusonlito

Copy link
Copy Markdown
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
Copy Markdown
Member

Hmm, what all methods does this affect?

@eusonlito

Copy link
Copy Markdown
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
Copy Markdown
Member

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

@taylorotwell

Copy link
Copy Markdown
Member

Hmm - I guess this looks OK.

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

Copy link
Copy Markdown
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
Copy Markdown
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