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

[8.x] Adds firstOrFail to Illuminate\Support\Collections and Illuminate\Support\LazyCollections #38420

Merged
merged 14 commits into from
Aug 19, 2021

Conversation

powellblyth
Copy link
Contributor

@powellblyth powellblyth commented Aug 17, 2021

This PR recreates the FirstOrFail methods from Eloquent collections into the Illuminate Support Collection and LazyCollection, which makes writing code a little more fluent

e.g.
OLD

 $collectionFromUser = new Collection([
            ['name' => 'foo'],
            ['name' => 'foo'],
            ['name' => 'bar'],
        ]);
// Slightly obscure code and hard to scan
if ($collectionFromUser->where('name', 'fish')->count() === 0){
    $collectionFromUser->add('fish');
}

$this->doSomethingWith($collection);

NEW

 $collectionFromUser = new Collection([
            ['name' => 'foo'],
            ['name' => 'foo'],
            ['name' => 'bar'],
        ]);

try {
   $collectionFromUser->where('name', 'fish')->firstOrFail()
}
// An Exception? This must be important, I'm glad I scanned it
catch (ItemNotFoundException){
    // Ensure user has 'fish' in their collection
    $collectionFromUser->add('fish');
}

$this->doSomethingWith($collectionFromUser);

@powellblyth
Copy link
Contributor Author

Not sure why the checks were cancelled. I think I submitted the style fixes too early

@GrahamCampbell GrahamCampbell changed the title Adds firstOrFail to illuminate\Support\Collections and illuminate\Support\LazyCollections [8.x] Adds firstOrFail to Illuminate\Support\Collections and Illuminate\Support\LazyCollections Aug 17, 2021
@JosephSilber
Copy link
Member

JosephSilber commented Aug 18, 2021

Are we OK that firstOrFail() on a query returns a 404, whereas this (when unhandled) will return a 500?

I mean, it kinda does makes sense, but the inconsistency can catch people by surprise.

Copy link
Member

@JosephSilber JosephSilber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs a test ensuring it's actually lazy, akin to the lazy test for the Sole method.

powellblyth and others added 2 commits August 18, 2021 15:36
Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>
Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>
@powellblyth
Copy link
Contributor Author

Thanks @JosephSilber , I'm not so familiar with Lazy Collections, I'll look further later and try and get that test in you suggest.

@powellblyth powellblyth marked this pull request as draft August 18, 2021 14:42
@JosephSilber
Copy link
Member

Whoops. Seems like unless doesn't yet support the higher order proxy (it does in Laravel 9).

Guess we should just revert it back to when, and change it later in master.

Sorry.

@powellblyth
Copy link
Contributor Author

Whoops. Seems like unless doesn't yet support the higher order proxy (it does in Laravel 9).

Guess we should just revert it back to when, and change it later in master.

Sorry.

Thought I was going mad! I'll revert tonight, but I'll add the tests. Thanks for your feedback.

@powellblyth
Copy link
Contributor Author

Hi @JosephSilber I've added the test as requested. If I'm honest, I don't understand Lazy Collections, so I can promise I've made the tests pass, but I can't tell you that the test is correct, and I value your feedback

@powellblyth powellblyth marked this pull request as ready for review August 18, 2021 21:27
Comment on lines 993 to 997
try {
$collection->firstOrFail();
} catch (ItemNotFoundException $e) {
//
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you expect this to throw? Why?

Comment on lines 1007 to 1013
try {
$collection->firstOrFail(function ($item) {
return $item % 2 === 0;
});
} catch (ItemNotFoundException $e) {
//
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Why would this fail?

And really, you're not testing an actual failure, and ensuring it enumerates the whole collection once.

@powellblyth
Copy link
Contributor Author

Further changes made. I hope I have Managed to match your suggestions @JosephSilber

@@ -2,6 +2,7 @@

namespace Illuminate\Tests\Support;

use Illuminate\Collections\ItemNotFoundException;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #38449

@JosephSilber
Copy link
Member

JosephSilber commented Aug 19, 2021

Nice work @powellblyth 👍

LGTM now.

Only outstanding question is about the inconsistency of the HTTP response. I honestly don't know what the right answer should be here.

@powellblyth
Copy link
Contributor Author

Nice work @powellblyth 👍

LGTM now.

Only outstanding question is about the inconsistency of the HTTP response. I honestly don't know what the right answer should be here.

Thank you. Not sure who can help about the HTTP aspect though. However, since it's not necessarily a resource, maybe the exception is ok, as you should only use this when you are expecting it. I do understand where it could confuse though.

I'm not familiar with the framework enough to even contemplate, but could the system that shows a 404 not be altered to catch both ModelNotFound as well as ItemNotFound? . I'm just throwing that one out there.

@driesvints
Copy link
Member

Please rebase and mark as ready.

@driesvints driesvints marked this pull request as draft August 19, 2021 13:38
@powellblyth powellblyth marked this pull request as ready for review August 19, 2021 13:47
@powellblyth
Copy link
Contributor Author

Only outstanding question is [about the inconsistency of the HTTP response]

Further to this, if you have this in a http controller, you also get a 500

    /**
     * Display a listing of the resource.
     *
     * @return Response|View
     */
    public function index(Request $request)
    {

        $users = collect(
            [
                User::factory()->make(),
                User::factory()->make(),
            ]
        );
        return view('users.index', ['users'=>$users->sole()]);
}

so it's an existing inconsistency....

@powellblyth
Copy link
Contributor Author

@driesvints I've re-based

@taylorotwell taylorotwell merged commit 0633b9e into laravel:8.x Aug 19, 2021
@JosephSilber
Copy link
Member

[sole() return a 500] so it's an existing inconsistency

sole() should never return a 404; that doesn't even make sense.

So that's not an inconsistency at all.

Krisell pushed a commit to Krisell/framework that referenced this pull request Aug 20, 2021
…te\Support\LazyCollections (laravel#38420)

* Add firstOrFail method to Collections and LazyCollections

* Restore test that got moved, fixed some grammaticals in test names

* Style fixes

* Make take(2) as take(1) instead

* use unless instead of when

Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>

* Use Unless instead of When

Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>

* Revert L9 changes, add test requested by @JosephSilber

* Remove unneeded try catch

* Remove unneeded include

* Test that when an enumeration does not contain an item, that firstOrFail enumerates the full collection

* Style fix

* Update Collection.php

* Update LazyCollection.php

Co-authored-by: Toby Powell-Blyth <tobypowell-blyth@elasticstage.com>
Co-authored-by: Joseph Silber <contact@josephsilber.com>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
Krisell pushed a commit to Krisell/framework that referenced this pull request Aug 20, 2021
…te\Support\LazyCollections (laravel#38420)

* Add firstOrFail method to Collections and LazyCollections

* Restore test that got moved, fixed some grammaticals in test names

* Style fixes

* Make take(2) as take(1) instead

* use unless instead of when

Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>

* Use Unless instead of When

Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>

* Revert L9 changes, add test requested by @JosephSilber

* Remove unneeded try catch

* Remove unneeded include

* Test that when an enumeration does not contain an item, that firstOrFail enumerates the full collection

* Style fix

* Update Collection.php

* Update LazyCollection.php

Co-authored-by: Toby Powell-Blyth <tobypowell-blyth@elasticstage.com>
Co-authored-by: Joseph Silber <contact@josephsilber.com>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
victorvilella pushed a commit to cdsistemas/framework that referenced this pull request Oct 12, 2021
…te\Support\LazyCollections (laravel#38420)

* Add firstOrFail method to Collections and LazyCollections

* Restore test that got moved, fixed some grammaticals in test names

* Style fixes

* Make take(2) as take(1) instead

* use unless instead of when

Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>

* Use Unless instead of When

Per Joseph Silber's suggestion

Co-authored-by: Joseph Silber <contact@josephsilber.com>

* Revert L9 changes, add test requested by @JosephSilber

* Remove unneeded try catch

* Remove unneeded include

* Test that when an enumeration does not contain an item, that firstOrFail enumerates the full collection

* Style fix

* Update Collection.php

* Update LazyCollection.php

Co-authored-by: Toby Powell-Blyth <tobypowell-blyth@elasticstage.com>
Co-authored-by: Joseph Silber <contact@josephsilber.com>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
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.

6 participants