The same Laravel resource controller for multiple routes

I am trying to use a trait as a type for my Laravel resource controllers.

Controller Method:

public function store(CreateCommentRequest $request, Commentable $commentable)

Which Commentableis the type of attribute type that my Eloquent models use.

The symptom is Commentableas follows:

namespace App\Models\Morphs;

use App\Comment;

trait Commentable
{
   /**
    * Get the model comments.
    *
    * @return \Illuminate\Database\Eloquent\Relations\MorphMany
    */
    public function Comments()
    {
        return $this->morphMany(Comment::class, 'commentable')->orderBy('created_at', 'DESC');
    }
}

In my routing, I have:

Route::resource('order.comment', 'CommentController')
Route::resource('fulfillments.comment', 'CommentController')

Both orders and executions may have comments, so they use the same controller, since the code will be the same.

However, when I send a message to order/{order}/comment, I get the following error:

Lighten \ Contracts \ Container \ BindingResolutionException
The purpose of [App \ Models \ Morphs \ Commentable] is not real.

Is this even possible?

+3
source
2

, , . .

Matthew , , . , , , , Commentable. .

. , ,

interface Commentable 
{
    public function comments();
}

class Order extends Model implements Commentable
{
    use Commentable;

    // ...
}

, typehintable. .

Laravel . , .

, , . . - :

# AppServiceProvider::register()
$this->app
    ->when(CommentController::class)
    ->needs(Commentable::class)
    ->give(function ($container, $params) {
        // Since you're probably utilizing Laravel route model binding, 
        // we need to resolve the model associated with the passed ID using
        // the `findOrFail`, instead of just newing up an empty instance.

        // Assuming this route pattern: "order|fullfilment/{id}/comment/{id}"
        $id = (int) $this->app->request->segment(2);

        return $this->app->request->segment(1) === 'order'
            ? Order::findOrFail($id)
            : Fulfillment::findOrFail($id);
     });

, CommentController Commentable, .

:

# AppServiceProvider::register()
$this->app->bind(Commentable::class, function ($container, $params) {
    $id = (int) $this->app->request->segment(2);

    return $this->app->request->segment(1) === 'order'
        ? Order::findOrFail($id)
        : Fulfillment::findOrFail($id);
});

, , . πŸ‘

                                   

, , , , , URL-. .

- . .

# App\Http\Controllers\CommentController
abstract class CommentController extends Controller
{
    public function store(CreateCommentRequest $request, Commentable $commentable) {
        // ...
    }

    // All other common methods here...
}

# App\Http\Controllers\OrderCommentController
class OrderCommentController extends CommentController
{
    public function store(CreateCommentRequest $request, Order $commentable) {
        return parent::store($commentable);
    }
}

# App\Http\Controllers\FulfillmentCommentController
class FulfillmentCommentController extends CommentController
{
    public function store(CreateCommentRequest $request, Fulfillment $commentable) {
        return parent::store($commentable);
    }
}

# Routes
Route::resource('order.comment', 'OrderCommentController');
Route::resource('fulfillments.comment', 'FulfillCommentController');

, .

Arrrgh,

:

OrderCommentController:: store (CreateCommentRequest $request, Order $commentable) CommentController:: store (CreateCommentRequest $request, Commentable $commentable).

, , ! .

. , Laravel typehints, .

, , .

                           

, ?

, Commentable, CommentController. Laravel (, {order}) . , CommentController, . , typehint .

, Route::resource. artisan route:list, .

, :

# App\Providers\RouteServiceProvider::boot()
public function boot()
{
    // Map `{order}` route placeholder to the \App\Order model
    $this->app->router->model('order', \App\Order::class);

    // Map `{fulfillment}` to the \App\Fulfilment model
    $this->app->router->model('fulfillment', \App\Fulfilment::class);

    parent::boot();
}

:

# App\Http\Controllers\CommentController
class CommentController extends Controller
{
    // Note that we have dropped the typehint here:
    public function store(CreateCommentRequest $request, $commentable) {
        // $commentable is either an \App\Order or a \App\Fulfillment
    }

    // Drop the typehint from other methods as well.
}

.

, , URL, , . , {order} \App\Order {fulfillment} App\Fulfillment.

URL. , .

, , .

+5

.

. , , . , .

: @Stefan, , , , . , , . , / , .

+1

Source: https://habr.com/ru/post/1688673/


All Articles