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

Add support for routes with nested model binding #725

Merged
merged 1 commit into from
Jan 3, 2025

Conversation

nicodevs
Copy link
Contributor

@nicodevs nicodevs commented Jan 1, 2025

This PR introduces support for defining routes with nested model bindings by specifying a meta.parent attribute in the controller's configuration. The parent attribute identifies the name of the related model.

Example

Given the following draft:

controllers:
  Comment:
    resource: api
    meta:
      parent: post

Blueprint will generate a nested resource route instead of a standard resource route:

-Route::apiResource('comments', App\Http\Controllers\CommentController::class);
+Route::apiResource('posts/{post}/comments', App\Http\Controllers\CommentController::class);

The meta.parent works not only for web or API resources, but for individual routes as well:

Route::get('posts/{post}/comments/foobar', [App\Http\Controllers\CommentController::class, 'foobar']);

The controller methods will automatically inject the parent model as a parameter:

-public function index(Request $request): CommentCollection
+public function index(Request $request, Post $post): CommentCollection

And queries within the controller will utilize the parent model to scope operations. The relationship is inferred using the controller's name, following Laravel conventions:

-Comment::all();
+$post->comments()->get();

-Comment::create($request->validated());
+$post->comments()->create($request->validated());
Click here to see a full controller example
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use App\Models\Comment;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Resources\CommentResource;
use App\Http\Resources\CommentCollection;
use App\Http\Requests\CommentStoreRequest;
use App\Http\Requests\CommentUpdateRequest;

class CommentController extends Controller
{
    public function index(Request $request, Post $post): CommentCollection
    {
        $comments = $post->comments()->get();

        return new CommentCollection($comments);
    }

    public function store(CommentStoreRequest $request, Post $post): CommentResource
    {
        $comment = $post->comments()->create($request->validated());

        return new CommentResource($comment);
    }

    public function show(Request $request, Post $post, Comment $comment): CommentResource
    {
        return new CommentResource($comment);
    }

    public function update(CommentUpdateRequest $request, Post $post, Comment $comment): CommentResource
    {
        $comment->update($request->validated());

        return new CommentResource($comment);
    }

    public function destroy(Request $request, Post $post, Comment $comment): Response
    {
        $comment->delete();

        return response()->noContent();
    }
}

This PR also makes the necessary adjustments to the generated tests, both for Pest and PHPUnit, to fit the changes. You can check examples of these generated tests in tests/fixtures/tests/pest/api-resource-nested.php and tests/fixtures/tests/phpunit/api-resource-nested.php.

Testing

I have added tests to assert the correct generation of the route, controller, and tests when the meta.parent is present. I also added a test in ControllerLexerTest to assert that the parent is being set as expected.

The previous tests are passing, ensuring that the introduction of this feature does not alter the existing functionality.

Let me know if this approach is valid and if you would like to see any changes. It would be great to have this feature in Blueprint. Thank you!

@nicodevs nicodevs force-pushed the nested-controllers branch 2 times, most recently from 34fb465 to 4c17adf Compare January 2, 2025 14:20
@nicodevs nicodevs changed the title Add support for nested controllers Add support for routes with nested model binding Jan 2, 2025
@nicodevs nicodevs force-pushed the nested-controllers branch from 46f8645 to 791bc43 Compare January 2, 2025 14:26
@nicodevs nicodevs marked this pull request as ready for review January 2, 2025 14:27
@jasonmccreary
Copy link
Collaborator

Is this ready? There was like 1000 WIPs.

@nicodevs
Copy link
Contributor Author

nicodevs commented Jan 3, 2025

Yes @jasonmccreary ~ is ready for review.

Yes, I’ve made small commits while the PR was in draft, and squashed them before marking it ready. Sorry if that was unclear!

@jasonmccreary
Copy link
Collaborator

Cool. Thanks.

Just as a bit of inside info, a maintainer may receive notifications for all commits made to a PR (open or draft). So it's best not to open the PR until you feel it's ready to ready.

@jasonmccreary jasonmccreary merged commit eedca26 into laravel-shift:master Jan 3, 2025
25 checks passed
@nicodevs
Copy link
Contributor Author

nicodevs commented Jan 3, 2025

Oh, @jasonmccreary, sorry for the unintentional spam! I'll make sure to open PRs only when they're 100% ready for review.

Thank you so much for the merge!

@nicodevs nicodevs deleted the nested-controllers branch January 5, 2025 12:44
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.

2 participants