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
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.
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.
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" });
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.
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');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With