MJ Khan
MJ Khan

Reputation: 1746

Laravel - multiple resource routes to single controller with argument

Can we have a single controller for multiple routes, and get the parameter?

Currently, I have these routes:

Route::resource('/customers', 'CustomerController');
Route::resource('/agents', 'AgentController');

And a CustomerController and a AgentController with all resource functions working.

But as CustomerController and AgentController are almost same except for one database field, i.e. group_id. I was thinking to use one controller i.e. PartyController and one route as:

Route::resource('/parties/customers', 'PartyController ');
Route::resource('/parties/agents', 'PartyController ');

or if someone suggests:

Route::resource('/parties/{group}', 'PartyController ');

I have been searching for a while but finding it hard to follow this path. I've added this code in the constructor of PartyController, to check the calling route:

    $path = Request::capture()->path();
    $this->group = ucwords(explode("/", $path)[1]);
    echo($this->group );

All seems to be going well till here. But when in my index.blade.php, I have this statement:

<p>{{ link_to_route('parties.create', 'Add new') }}</p>

I get an exception:

Route [parties.create] not defined. 

I've tried multiple combinations, without any success and more errors come through, like accessing /parties/customers/create doesn't work now.

So, is it possible anyway or should I abandon this idea?

EDIT: My question is different from Same Laravel resource controller for multiple routes as I am not using a trait.

Upvotes: 4

Views: 5571

Answers (5)

MJ Khan
MJ Khan

Reputation: 1746

I did it by using my own approach, I used the same routes.

Route::resource('/parties/agents', 'PartyController');
Route::resource('/parties/customers', 'PartyController');

and in constructor of PartyController

$path = Request::capture()->path();
$group = strtolower(explode("/", $path)[1]);

Now I've the $group variable to identify which group I am working with.

And in my blade documents I replaced parties.create with $group.create

<a href="{{ route($group.'.create')}}" > Add new </a>

Same for other routes.. Now it is working just as I wanted.

Thank all for help.

Upvotes: 2

Piterden
Piterden

Reputation: 789

So, first you define routes with next line:

Route::resource('/parties/agents', PartiesAgentsController::class);
Route::resource('/parties/customers', PartiesCustomersController::class);

Then you might need some parties in the REST style:

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)
    {
    }

}

Inside the construct method of this controller I am making some checks and other operations as you could see. Also I use repositories... It is No DDD).

Then, I can use all above like:

class PartiesAgentsController extends PartiesController
{

    /**
     * Create an instance of the PartiesAgentsController class
     *
     * @param EntryRepositoryInterface $repository
     */
    public function __construct(PartyAgentRepositoryInterface $repository)
    {
        parent::__construct($repository);
    }

}

And the same would be for customers...

Upvotes: 1

Yaser Khahani
Yaser Khahani

Reputation: 705

As I think right now... It would be nice to using class inheritance! :D

You can define PartyController as a parent of both CustomerController and AgentController (both of them extends PartyController).

So, move your common methods into PartyController and call them from Customer/Agent controllers. :)

Upvotes: 4

N Mahurin
N Mahurin

Reputation: 1446

<p>{{ link_to_route('parties.create', 'Add new') }}</p>

You missed the variable parameter you added, it should be

 <p>{{ link_to_route('parties.' . $group . '.create', 'Add new') }}</p>

Upvotes: 1

Marcin Nabiałek
Marcin Nabiałek

Reputation: 111899

If I were you, I would use:

Route::resource('/customers', 'CustomerController');
Route::resource('/agents', 'AgentController');

Now you can make AgentController extending CustomerController (or any other controller you want) so they can reuse same code. If needed you can set in constructor some properties for example group to know if you are dealing with agents or customers.

To make your routes working you can pass extra variable from controller to view, to have in your blade:

<p>{{ link_to_route($group.'.create', 'Add new') }}</p>

Upvotes: 6

Related Questions