Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple routes to same controller

Tags:

rest

php

laravel

I'm trying to build a restfull API and I came to a point where I think, and REST ain't very explicit about it, that one resource should be accessible by more than one URL. Let me put an example.

Route::group(['prefix' => 'forum'], function(){

    Route::resource('categories', 'CategoriesController');

    Route::resource('categories.discussions', 'DiscussionsController');

    Route::resource('discussions', 'DiscussionsController');

});

My intention is to be able to access each discussion either by appending it to the category it belongs:

localhost/forum/categories/{category_id}/discussions

or by this url

localhost/forum/discussions

Has anybody got something like this to work without rewriting the complete controller.

This is my discussions controller:

class DiscussionsController extends ApiController {


public function __construct(DiscussionRepositoryInterface $discussion)
{
    $this->discussions = $discussion;
}

/**
 * Display a listing of the resource.
 *
 * @return Response
 */
public function index($category = null)
{
    $response = $this->discussions->all($category);

    return $this->respond($response->getData());
}

/**
 * Show the form for creating a new resource.
 *
 * @return Response
 */
public function create()
{
    if (!$this->hasPermission('forum.create.discussion'))
    {
        return $this->respondNotAllowed();
    }

    return $this->respondSuccess('Granted');
}

/**
 * Store a newly created resource in storage.
 *
 * @return Response
 */
public function store($category)
{
    if (!$this->hasPermission('forum.create.discussion'))
    {
        return $this->respondNotAllowed();
    }

    return $this->respondSuccess('Granted');

}

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return Response
 */
public function show($categories = null, $discussions)
{
    $discussion =  $this->discussions->find($categories, $discussions);

    if ($discussion == null)
        return $this->respondNotFound('Discussion not found');

    $data = [
        'discussions' => $discussion
    ];

    return $this->respond($data);
}

/**
 * Show the form for editing the specified resource.
 *
 * @param  int  $id
 * @return Response
 */
public function edit($id)
{
    if (!$this->hasPermission('forum.edit.discussion'))
    {
        return $this->respondNotAllowed();
    }

    return $this->respondSuccess('Granted');
}

/**
 * Update the specified resource in storage.
 *
 * @param  int  $id
 * @return Response
 */
public function update($id, $data)
{

    if (!$this->hasPermission('forum.edit.discussion'))
    {
        return $this->respondNotAllowed();
    }

    $data = Input::only('category_id', 'user_id', 'desc', 'title');

    $data = $this->clearNullInput($data);

    if ($this->discussions->update($id, $data))
        return $this->respondError('Couldnt update discussion');

    return $this->respondSuccess('Discussion updated successfully');
}

/**
 * Remove the specified resource from storage.
 *
 * @param  int  $id
 * @return Response
 */
public function destroy($id)
{
    if (!$this->hasPermission('forum.delete.discussion'))
    {
        return $this->respondNotAllowed();
    }

    if (!$this->discussions->delete($id))
        return $this->respondError('Couldnt destroy user');

    return $this->respondSuccess('Granted');
}

}

The index method works, fine in both calls (localhost/forum/categories/id/discussions and localhost/forum/discussions)

But when I try to show the resource, only the long version works the short one throws the following execption:

ErrorException in DiscussionsController.php line 68:
Missing argument 2 for App\Http\Controllers\DiscussionsController::show()

I would say laravel goes crazy because he can't identify the id's, is there any clever workaround or am I gonna have to rewrite controller¿?

Any opinion is highly apreciated, thanks

like image 240
Borjante Avatar asked Apr 22 '15 08:04

Borjante


People also ask

Can a controller have multiple get methods?

Usually a Web API controller has maximum of five actions - Get(), Get(id), Post(), Put(), and Delete(). However, if required you can have additional actions in the Web API controller.

Can we have multiple routes in MVC?

Multiple Routes You need to provide at least two parameters in MapRoute, route name, and URL pattern. The Defaults parameter is optional. You can register multiple custom routes with different names.

Can we map multiple URL's to the same action?

Yes, We can use multiple URLs to the same action with the use of a routing table. foreach(string url in urls)routes. MapRoute("RouteName-" + url, url, new { controller = "Page", action = "Index" });

How many routes can be defined in MVC?

Every ASP.NET MVC application must configure (register) at least one route in the RouteConfig class and by default, the ASP.NET MVC Framework provides one default route. But you can configure as many routes as you want.


1 Answers

You can try something like this

public function show(Category $category, Discussion $discussion)

If you are calling localhost/forum/categories/{categories}/discussions/{discussions} then both variables have their exact values. If you call localhost/forum/discussions/{discussions} then Category will be just new Category

Make sure you will bind the values in your RouteServiceProvider as

$router->model('discussions', 'App\Discussion');
$router->model('categories', 'App\Category');
like image 80
Margus Pala Avatar answered Nov 02 '22 21:11

Margus Pala