How To Extend Laravel's Basic Route Resource In Laravel 6?
I'm using Laravel as an API with many endpoints and many controllers. I'm using Route::resource()
method to define REST endpoints, but in most cases I need to add one more endpoint and now my code is looking like this:
Route::get('product/list', '[email protected]');
Route::resource('product', 'ProductController');
Route::get('property/list', '[email protected]');
Route::resource('property', 'PropertyController');
Route::get('customer/list', '[email protected]');
Route::resource('customer', 'CustomerController');
...and this sample keeps coming up, over and over again. I think there needs to be a practical and better way to define this {resource}/list
URI in one place. Now I need to repeat this sample:
Route::get('{resource}/list', '[email protected]');
Is there a better solution to define this endpoint only once and be available in every controllers? Can I avoid somehow the repetition?
Answer
If you take a look at the resource
method in the Illuminate\Routing\Router
class, you are going to see this:
if ($this->container && $this->container->bound(ResourceRegistrar::class)) {
$registrar = $this->container->make(ResourceRegistrar::class);
} else {
$registrar = new ResourceRegistrar($this);
}
Which means you can bind a ResourceRegistrar
to overwrite the default one provided by Laravel. Therefore, to achieve what you want, you could first make a new class, for instance, app/ResourceRegistrar.php
, which would extends the Illuminate\Routing\ResourceRegistrar
and add a default 'list'
:
<?php
namespace App;
use Illuminate\Routing\ResourceRegistrar as BaseResourceRegistrar;
class ResourceRegistrar extends BaseResourceRegistrar
{
protected $resourceDefaults = [
'index', 'create', 'store', 'show', 'edit', 'update', 'destroy', 'list',
];
/**
* Add the list method for a resourceful route.
*
* @param string $name
* @param string $base
* @param string $controller
* @param array $options
* @return \Illuminate\Routing\Route
*/
public function addResourceList($name, $base, $controller, $options)
{
$uri = $this->getResourceUri($name).'/all';
$action = $this->getResourceAction($name, $controller, 'list', $options);
return $this->router->get($uri, $action);
}
}
And then, you can simply bind the registrar in your AppServiceProvider
:
<?php
namespace App\Providers;
use App\ResourceRegistrar;
use Illuminate\Routing\Router;
use Illuminate\Routing\ResourceRegistrar as BaseResourceRegistrar;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->bind(BaseResourceRegistrar::class, ResourceRegistrar::class);
}
}
And you can register your route like you used to without adding the extra line:
Route::resource('product', 'ProductController');
Route::resource('property', 'PropertyController');
Route::resource('customer', 'CustomerController');
Then if you run the php artisan route:list
, you should see the {resource}/list
route.
Related Questions
- → "failed to open stream" error when executing "migrate:make"
- → October CMS Plugin Routes.php not registering
- → OctoberCMS Migrate Table
- → OctoberCMS Rain User plugin not working or redirecting
- → October CMS Custom Mail Layout
- → October CMS - How to correctly route
- → October CMS - Conditionally Load a Different Page
- → Make a Laravel collection into angular array (octobercms)
- → In OctoberCMS how do you find the hint path?
- → How to register middlewares in OctoberCMS plugin?
- → Validating fileupload(image Dimensions) in Backend Octobercms
- → OctoberCMS Fileupload completely destroys my backend
- → How do I call the value from another backed page form and use it on a component in OctoberCms