Skip to content

Instantly share code, notes, and snippets.

@Ellrion
Last active June 28, 2018 19:53
Show Gist options
  • Save Ellrion/d04a75bf2df10d8e46eccd44be068dda to your computer and use it in GitHub Desktop.
Save Ellrion/d04a75bf2df10d8e46eccd44be068dda to your computer and use it in GitHub Desktop.
<?php
namespace App\Services\Foundation\Routing;
use Illuminate\Routing\ResourceRegistrar;
class ExtendedResourceRegistrar extends ResourceRegistrar
{
/**
* The default actions for a resourceful controller.
*
* @var array
*/
protected $resourceDefaults = ['index', 'trashed', 'create', 'store', 'show', 'edit', 'update', 'destroy', 'restore'];
/**
* Add the index method for a resourceful route.
*
* @param string $name
* @param string $base
* @param string $controller
* @param array $options
*
* @return \Illuminate\Routing\Route
*/
protected function addResourceTrashed($name, $base, $controller, $options)
{
$uri = $this->getResourceUri($name) . '/trashed';
$action = $this->getResourceAction($name, $controller, 'trashed', $options);
return $this->router->get($uri, $action);
}
/**
* Add the destroy method for a resourceful route.
*
* @param string $name
* @param string $base
* @param string $controller
* @param array $options
*
* @return \Illuminate\Routing\Route
*/
protected function addResourceRestore($name, $base, $controller, $options)
{
$uri = $this->getResourceUri($name) . '/{' . $base . '}/restore';
$action = $this->getResourceAction($name, $controller, 'restore', $options);
return $this->router->get($uri, $action);
}
}
<?php
namespace App\Services\Foundation\Routing;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class ModelBindingResolver
{
private $model;
/**
* ModelBindingResolver constructor.
* @param Model $model
*/
public function __construct($model)
{
$this->model = $model;
}
public function resolve($value)
{
return $this->model
->where($this->model->getRouteKeyName(), $value)
->when($this->needTrashed(), function ($q) {
$q->onlyTrashed();
})
->first();
}
protected function needTrashed()
{
return $this->model->hasGlobalScope(SoftDeletingScope::class)
&& $this->trashedRoute();
}
protected function trashedRoute()
{
$route = (string) app('router')->currentRouteName();
return ends_with($route, '.restore');
}
}
<?php
namespace App\Services\Foundation\Routing;
use Illuminate\Routing\Router;
class RouterMixin
{
public function apiRestorableResource()
{
return function ($name, $controller, array $options = []) {
$only = ['index', 'show', 'store', 'update', 'destroy', 'trashed', 'restore'];
if (isset($options['except'])) {
$only = array_diff($only, (array) $options['except']);
}
/** @var Router $router */
$router = $this;
return $router->resource($name, $controller, array_merge([
'only' => $only,
], $options));
};
}
}
<?php
namespace App\Providers;
use App\Services\Foundation\Routing\ExtendedResourceRegistrar;
use App\Services\Foundation\Routing\RouterMixin;
use Illuminate\Routing\ResourceRegistrar;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* This namespace is applied to your controller routes.
*
* In addition, it is set as the URL generator's root namespace.
*
* @var string
*/
protected $namespace = 'App\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
//
parent::boot();
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
parent::register();
$this->registerResourceRegistrar();
$this->registerRouterMacro();
}
/**
* Register resource registrar.
*/
protected function registerResourceRegistrar()
{
$this->app->bind(ResourceRegistrar::class, ExtendedResourceRegistrar::class);
}
/**
* Add macro to router.
*/
protected function registerRouterMacro()
{
Router::mixin(new RouterMixin());
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
//
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
}
@Ellrion
Copy link
Author

Ellrion commented Jun 28, 2018

add to BaseModel method

    public function resolveRouteBinding($value)
    {
        return (new ModelBindingResolver($this))->resolve($value);
    }

and for some model Foo with SoftDeletes trait we can add routes

Route::apiRestorableResource('/foos', 'FoosController');
+--------+-----------+--------------------------+---------------+----------------------------------------------+------------+
| Domain | Method    | URI                      | Name          | Action                                       | Middleware |
+--------+-----------+--------------------------+---------------+----------------------------------------------+------------+
|        | GET|HEAD  | api/foos                 | foos.index   | App\Http\Controllers\FoosController@index     | api        |
|        | POST      | api/foos                 | foos.store   | App\Http\Controllers\FoosController@store     | api        |
|        | GET|HEAD  | api/foos/trashed         | foos.trashed | App\Http\Controllers\FoosController@trashed   | api        |
|        | GET|HEAD  | api/foos/{foo}           | foos.show    | App\Http\Controllers\FoosController@show      | api        |
|        | PUT|PATCH | api/foos/{foo}           | foos.update  | App\Http\Controllers\FoosController@update    | api        |
|        | DELETE    | api/foos/{foo}           | foos.destroy | App\Http\Controllers\FoosController@destroy   | api        |
|        | POST      | api/foos/{foo}/restore   | foos.restore | App\Http\Controllers\FoosController@restore   | api        |
+--------+-----------+--------------------------+---------------+----------------------------------------------+------------+

@andrey-helldar
Copy link

Большое спасибо за помощь!
Оформил все это дело в пакет https://github.com/andrey-helldar/extended-routes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment