Laravel - несколько маршрутов ресурсов к одному контроллеру с аргументом
Можем ли мы иметь один контроллер для нескольких маршрутов и получить параметр?
В настоящее время у меня есть следующие маршруты:
Route::resource('/customers', 'CustomerController');
Route::resource('/agents', 'AgentController');
И CustomerController
и AgentController
со всеми работающими функциями ресурсов.
Но так как CustomerController
и AgentController
почти одинаковы, за исключением одного поля базы данных, т.Е. group_id
. Я думал использовать один контроллер, т.Е. PartyController
и один маршрут как:
Route::resource('/parties/customers', 'PartyController ');
Route::resource('/parties/agents', 'PartyController ');
Или если кто-то предложит:
Route::resource('/parties/{group}', 'PartyController ');
Я искал некоторое время, но нашел его трудно идти по этому пути. Я добавил этот код в конструктор PartyController
, чтобы проверить маршрут вызова:
$path = Request::capture()->path();
$this->group = ucwords(explode("/", $path)[1]);
echo($this->group );
Кажется, до сих пор все шло хорошо. Но когда в моем index.blade.php
у меня есть это утверждение:
<p>{{ link_to_route('parties.create', 'Add new') }}</p>
Я получаю исключение:
Route [parties.create] not defined.
Я перепробовал несколько комбинаций, без какого-либо успеха, и появилось больше ошибок, например, доступ к /parties/customers/create
сейчас не работает.
Итак, возможно ли это в любом случае или мне следует отказаться от этой идеи?
РЕДАКТИРОВАТЬ: Мой вопрос таков отличается от Одного и того же контроллера ресурсов Laravel для нескольких маршрутов, так как я не использую признак.
5 answers
На вашем месте я бы использовал:
Route::resource('/customers', 'CustomerController');
Route::resource('/agents', 'AgentController');
Теперь вы можете сделать AgentController
расширение CustomerController
(или любой другой контроллер, который вы хотите), чтобы они могли повторно использовать один и тот же код. При необходимости вы можете задать в конструкторе некоторые свойства, например группу, чтобы узнать, имеете ли вы дело с агентами или клиентами.
Чтобы ваши маршруты работали, вы можете передать дополнительную переменную из контроллера в представление, чтобы в вашем блейде было:
<p>{{ link_to_route($group.'.create', 'Add new') }}</p>
<p>{{ link_to_route('parties.create', 'Add new') }}</p>
Вы пропустили добавленный вами переменный параметр, он должен быть
<p>{{ link_to_route('parties.' . $group . '.create', 'Add new') }}</p>
Как я думаю прямо сейчас... Было бы неплохо использовать наследование классов! :D
Вы можете определить PartyController
как родителя обоих CustomerController
и AgentController
(оба они расширяют PartyController
).
Итак, переместите свои общие методы в PartyController
и вызовите их из контроллеров Customer/Agent
. :)
Итак, сначала вы определяете маршруты со следующей строкой:
Route::resource('/parties/agents', PartiesAgentsController::class);
Route::resource('/parties/customers', PartiesCustomersController::class);
Тогда вам может понадобиться несколько вечеринок в стиле REST:
class PartiesController extends BaseController
{
/**
* The Entry Repository
*
* @var EntryRepositoryInterface
*/
protected $repository;
/**
* Create an instance of the RestController class
*
* @param EntryRepositoryInterface $repository
*/
public function __construct(EntryRepositoryInterface $repository)
{
parent::__construct();
if (!$this->request->ajax())
{
return redirect('/');
}
$this->repository = $repository;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store()
{
}
/**
* Display the specified resource.
*
* @param int $slug
* @return \Illuminate\Http\Response
*/
public function show($slug)
{
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
}
}
Внутри метода построения этого контроллера я выполняю некоторые проверки и другие операции, как вы могли видеть. Также я использую репозитории... Это не DDD).
Затем я могу использовать все вышеперечисленное, например:
class PartiesAgentsController extends PartiesController
{
/**
* Create an instance of the PartiesAgentsController class
*
* @param EntryRepositoryInterface $repository
*/
public function __construct(PartyAgentRepositoryInterface $repository)
{
parent::__construct($repository);
}
}
И то же самое было бы для клиентов...
Я сделал это, используя свой собственный подход, я использовал те же маршруты.
Route::resource('/parties/agents', 'PartyController');
Route::resource('/parties/customers', 'PartyController');
И в конструкторе PartyController
$path = Request::capture()->path();
$group = strtolower(explode("/", $path)[1]);
Теперь у меня есть переменная $group, чтобы определить, с какой группой я работаю.
И в моих документах блейда я заменил parties.create на $group.create
<a href="{{ route($group.'.create')}}" > Add new </a>
То же самое для других маршрутов.. Теперь он работает именно так, как я хотел.
Спасибо всем за помощь.