Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

hdwebpros's avatar

Best practices on controllers and routing on multiple similar sources

I have our developer developing a 'reporting' app on Laravel 5. We've used it before, and it's sweet.

On this app, there are 10 different data-sets (what I envision as rows in the db). They are fairly simple in nature. All require just ID and name.

I'm conceptualizing, trying to wrap my head around the controllers and routes. I'm trying to avoid redundancies and lean on Laravel as much as possible. Admittedly I'm not experienced with in depth development within Laravel, but I want to point my dev the right way. I'm looking for suggestions and guidance and seeing if I'm on the right path.

  • Is it possible to have one 'master' create, read, update, delete function in the controller for those 10 instances of similar data? Do I somehow pass a variable to each master function, if so, is there a best method for doing this?
  • With routing should I make 10 different routes, or should we get somewhat dynamic with that? What's the best methods?

These may seem like newb questions, but you are the pros! Much respect to all of you.

I'm looking forward to hearing your advice on this. :)

0 likes
22 replies
pmall's avatar

Ive posted a solution to this a long time ago. It is long so try to search it in the forum.

The point is to have only one controller, and to inject an instance of a model according to the url. /foo/create, inject an instance of foo, /bar/create inject an instance of bar, etc.

1 like
hdwebpros's avatar

Thanks @El_Matella that helps. If I understand you right, you're suggesting one controller and registering resource routes to that controller.

If we do that, how will our app know which dataset in our DB to manipulate? Example: if we choose to register this resource route: Route::resource('drivers', 'appController'); How will it know to use it to create, read, update and delete entries in the 'drivers' table?

hdwebpros's avatar

@pmall Thanks for replying. Your method makes sense. So, pass variables via the URL and use that controller to do the dirty work. Makes sense to me :)

El_Matella's avatar

Hi, the point is, with "resource", Laravel makes the routes for you. The thing is, you are a little less free to name your controller methods.

The other thing is that, the methods provided for those controllers are generally the right ones, I generally don't use other ones, or I just register them with a new route.

EDIT: And then you have a controller per resource:

// ProductsController
public function show($id){
    $product = Product::find($id);
    return view('products.show',compact('product'));
}

// CustomersController
public function show($id){
    $customer = Customer::find($id);
    return view('customers.show',compact('customer'));
}
hdwebpros's avatar

Hey @pmall (or anyone), sorry to bug you, but if we use your method, and pass 'foo' instance of a model to the controller via the URL, is that dependency injection, method injection, or something else? Is it through binding? I'm having a bugger of a time figuring that out, and can't find anything on here or Google :(

luddinus's avatar

Well, you could do an abstract controller:

abstract class ModelController extends Controller {

    // GET /users/1
    public function show($model_name, $id)
    {
        $model = $this->makeModel($model_name);
        
        $entity = $model->findOrFail($id);

        return view('your-view', compact('entity')); 
    }

    protected makeModel($model_name)
    {
        $model_class = 'App\\'.str_singular($model_name); // App\User;

        return app($model_class);
    }

}
1 like
mehany's avatar

@hdwebpros "Route model binding"

Laravel model binding provides a convenient way to inject class instances into your routes. For example, instead of injecting a user's ID, you can inject the entire User class instance that matches the given ID.

Route Model Binding

P.S.

public function boot(Router $router)
        {
            parent::boot($router);
            $router->model('model1', 'App\model1');
            $router->model('model2', 'App\model2');
            $router->model('model3', 'App\model3');
            $router->model('model4', 'App\model4');
        }
        // Routes.php
        Route::resource('action/model1', 'OnlyOneController')
        Route::resource('action/model2', 'OnlyOneController')
        Route::resource('action/model3', 'OnlyOneController')
        Route::resource('action/model4', 'OnlyOneController')

Then goes the above abstract ModelController class

hdwebpros's avatar

Update. It's working well so far.

Okay, last part to this puzzle. We have our routes and controller setup nicely. The controller gets the model injection via the URL. Seems simple, but how would that controller then send that (model name) to the view? We'd like to put in a heading that this is a section for whatever is in the URL.

Example: url: mydomain.com/trucks

route passes 'trucks' as the model to use to the controller. Controller then should pass 'trucks' to the view somehow.

We'd like the view to have

trucks

. Just not sure what variable I can grab from the controller to get that.

That is where I'm stuck :(

rotanadan's avatar

also @mehany how would you get the model that is being bound in the index and create functions?

pmall's avatar

@mehany this has nothing to do with route model binding.

@hdwebpros You inject an interface representing a model in the constructor of your controller. Then in your app service provider you bind this interface to a concrete model according to the first segment of the url (containing the model "name").

For the views, you can have a subdirectory for each models views, name it like the first segment of the url. Then by using this you can construct the right path for your model's views.

hdwebpros's avatar

@pmall thank you. You're saying to inject the model interface in the controller instructor like http://laravel.com/docs/5.0/controllers#dependency-injection-and-controllers.

Then bind the interface to a model: http://laravel.com/docs/5.1/container#binding $this->app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher'); But modify that to be according to the first segment of the URL.

Then create views that are named identical with the model names, and from that I can add routes. Am I on the right path?

luddinus's avatar

@pmall That way it would have to implement the injected interface to ALL the models.

@hdwebpros I think you could do something like this

$model = app('App\User');

$var_name = str_plural(class_basename($model)); // users

return view('your-view', [
    $var_name => $model->getAll()
]);

1 like
luddinus's avatar

@pmall As I Understand, you mean this:

// somewhere in your app
App::bind('ResolvedModelFromUrl', function() {

    // some code to get the parameter of the request you need

    return $model; // App\User
    // if App\User does not implements "ResolvedModelFromUrl", it will throw an error.

});


abstract class OnlyOneController extends Controller {

    protected $model;

    public function __construct(ResolvedModelFromUrl $model)
    {
        // ResolvedModelFromUrl is an interface
        // that "returns" one model (via Container), but this model must implement "ResolvedModelFromUrl"

        $this->model = $model;
    }

}
1 like
pmall's avatar

but this model must implement "ResolvedModelFromUrl"

So what's the problem ?

martinbean's avatar

Admittedly I'm not experienced with in depth development within Laravel, but I want to point my dev the right way.

@hdwebpros I don’t mean to be insulting, but why are you wanting to be the one to point your developer the “right way” when you’ve admitted you’re probably not the best person to be doing so?

mehany's avatar

hey @pmall, I noticed you mentioned earlier that this has nothing to do with Route Model Binding which I thought it did. Based on your recommendations, what would be the correct answer for this:

if we use your method, and pass 'foo' instance of a model to the controller via the URL, is that dependency injection, method injection, or something else?
I think the OP was following your first advice at the top of the thread which i seem to misunderstood! I am thinking you are referring to this solution:
You inject an interface representing a model in the constructor of your controller. Then in your app service provider you bind this interface to a concrete model according to the first segment of the url (containing the model "name").
pmall's avatar

Yes I always speak about the same solution here.

Please or to participate in this conversation.