@martinbean The story of my problem.
In my project, I had a lot of almost similar tables (clients, contracts, ... languages, ... users) and all these tables had their own controller. I passed the IDs to the methods: client, contract, ... language, ... user, and in the controller I received and processed the models (Language $language).
All the controllers were similar, some had additional logic, but if I needed to make some general change, I edited all the controllers (again, I'm a beginner) and constantly thought about OOP!
One day I couldn't stand it anymore and decided to rewrite almost the entire backend.
I made a basic controller:
class BaseController extends Controller
{
protected Request $request; // The request instance
protected ?string $front_theme; // Frontend theme
protected ?string $back_theme; // Backend theme
protected Language $current_lang; // Current content language
protected string $itemModel; // Model of the current item
protected string $itemRequest; // Request validation for the current item
protected ?bool $editRequest; // EditRequest differs from Request (null - use the basic Request)
protected ?string $whoseCategory; // The name ('Post') of the item for which this category was created
protected ?string $categoryModel; // Item category model
protected bool $itemHasOwner; // The item has an owner
public function __construct(Request $request)
{
$this->request = $request;
$this->front_theme = Cookie::get('front_theme');
$this->back_theme = Cookie::get('back_theme');
$this->current_lang = $this->setContentLang($request->language);
$this->editRequest = false;
$this->whoseCategory = null;
$this->categoryModel = null;
$this->itemHasOwner = false;
}
// Сontroller methods for processing resource routes
And then most of my controllers got rid of the code altogether:
class MemberController extends BaseController
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->itemModel = Member::class;
$this->itemRequest = MemberRequest::class;
}
}
or, if there is additional logic:
class ClientController extends BaseController
{
public function __construct(Request $request)
{
parent::__construct($request);
$this->itemModel = Client::class;
$this->itemRequest = ClientRequest::class;
$this->itemHasOwner = true;
}
protected function itemQuery(Builder $query): void
{
if (!Auth::user()->isAdmin()) {
$query->where('user_id', Auth::user()->id);
}
}
public function store(): RedirectResponse
{
$response = parent::store();
$request = app($this->itemRequest);
$item = $request->validated();
$latestItem = $this->itemModel::latest()->first();
if (isset($item['user_id'])) {
$latestItem->update(['user_id' => $item['user_id']]);
}
return $response;
}
}
But I was unable to make a universal method that receives different models. I naively hoped for:
public function index(Model $item): View
You understand that I was expecting disappointment here. This is a mistake.
And then I decided that my problem was solved only by transferring the ID:
public function index(int $itemId): View
Everything worked very well until I started testing the language.edit route. Everything worked very well until I started testing the language.edit route. It returned a 404 error without entering either the controller or the middleware. I tried to manage it even in the RouteServiceProvider. I couldn't change anything, so I abandoned the resource routes for the Language model and wrote custom ones. I was already afraid of "route model binding" and therefore used the {id} parameter instead of {language} in the routes.
The language.edit route started working as expected. It was then, under the influence of (perhaps a misunderstanding of) route model binding, that I changed the route parameter in all routes:
...*LanguageController*::class)->parameters(['language' => 'id']);
But I did it after I addressed the community in this post.