简体   繁体   中英

Laravel: One Controller for multiple Models

I'm currently rebuilding my vanilla-PHP-App with Laravel and I have the following problem. I have multiple database-tables, that represent word categories (noun, verb, adverb, ...). For each table I created a separate Model, a route::resource and a separate resource-Controller. For example:

NomenController.php

public function show($id)
{
    $vocab = Nomen::find($id);
    return view('glossarium.vocab_update', compact('vocab'));
}

and

VerbController.php

public function show($id)
{
    $vocab = Verb::find($id);
    return view('glossarium.vocab_update', compact('vocab'));
}

...which are essentially the same except the Model class.

I don't want to create a separate Controller for each model, that does exactly the same. What would be the most simple and elegant way to solve this? Should I just create a VocabController.php and add a parameter for the Model-name like:

Route::resource('/vocab/{category}', 'VocabController');

and then add a constructor method in this controller like

public function __construct ($category) {
    if ($category == 'nomen') {
        $this->vocab = App\Nomen;
    }
    else if ($category == 'verb') {
         $this->vocab = App\Verb;
    }
}

I wonder if there is a simpler method to do that. Can I somehow do this with Route Model Binding?

Thanks in advance

Simply create a trait like this in App\\Traits , (you can name it anything... Don't go with mine though... I feel its pretty lame... :P)

namespace App\Traits;

trait CommonControllerFunctions {

    public function show($id) {
        $modelObject = $this->model;

        $model = $modelObject::find($id);

        return view('glossarium.vocab_update', compact('model'));
    }

}

and in your NomenController and VerbController , do this:

use App\Traits\CommonControllerFunctions;

class NomenController {

    use CommonControllerFunctions;

    protected $model = Nomen::class;

}

and

use App\Traits\CommonControllerFunctions;

class VerbController {

    use CommonControllerFunctions;

    protected $model = Verb::class;

}

Note: Please note that this example is just a work-around for your particular situation only... Everyone practices code differently, so this method might not be approved by all...

I think the simpliest way it to create only one controller, eg VocabController with methods nomen , verb and whatever you want.

Routes:

Route::get('/vocab/nomen/{nomen}', 'VocabController@item');
Route::get('/vocab/verb/{verb}', 'VocabController@item');

And the model binding:

Route::model('nomen', 'App\Nomen');
Route::model('verb', 'App\Varb');

Then your method shoud look like that:

public function item($item)
{
    return view('glossarium.vocab_update', $item);
}

Keep in mind, that $item is already fetched model from the database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM