Extend Resource Controllers

前提是你 提交于 2020-06-12 07:12:12

问题


I'm doing what I want in a certain way and I'm looking for alternatives or better ways of doing. I'm using Resource Controllers in my application. Also I'm using softdelete in several models, so my routes are as follows:

Route::get('users/deleted', array('uses' => 'UserController@trash'));
Route::put('users/{id}/restore', array('uses' => 'UserController@restore'));
Route::resource('users', 'UserController');

The first route is to display objects that have been deleted. The second allows me to restore these deleted elements. The third maps the traditional methods (create, edit, update, etc.).

I have several controllers that work exactly the same way, I wonder if have any way to tell laravel to work with this two methods (trash and delete) by default without the two extra lines.

Is it possible? Or to give a better way that I'm doing? (sorry for bad english)


回答1:


Keeping things simple and DRY.

You can extend the Router and replace the Route Facade in your app/config/app.php file but seems like a lot of work for not much gain, but don't forget that your routes file is a PHP script and you can do things like:

$routes = [
    ['users' => 'UserController'],
    ['posts' => 'PostController'],
];

foreach ($routes as $key => $controller)
{
    Route::get("$key/deleted", array('uses' => "$controller@trash"));

    Route::put("$key/{id}/restore", array('uses' => "$controller@restore"));

    Route::resource($key, $controller);
}

Extending the router

To extend the router you need to create 3 classes:

The Router extended, where you'll add your new methods:

<?php namespace App\Routing;

class ExtendedRouter extends \Illuminate\Routing\Router {

    protected $resourceDefaults = array(
                'index', 
                'create', 
                'store', 
                'show', 
                'edit', 
                'update', 
                'destroy', 
                'deleted',
                'restore',
    );

    protected function addResourceDeleted($name, $base, $controller)
    {
        $uri = $this->getResourceUri($name).'/deleted';

        return $this->get($uri, $this->getResourceAction($name, $controller, 'deleted'));
    }

    protected function addResourceRestore($name, $base, $controller)
    {
        $uri = $this->getResourceUri($name).'/{resource}/restore';

        return $this->get($uri, $this->getResourceAction($name, $controller, 'restore'));
    }

}

A Service Provider, to boot your new router, using the same IoC identifier Laravel uses ('router'):

<?php namespace App\Routing;

use Illuminate\Support\ServiceProvider;

class ExtendedRouterServiceProvider extends ServiceProvider {

    protected $defer = true;

    public function register()
    {
        $this->app['router'] = $this->app->share(function() { return new ExtendedRouter($this->app); });
    }

    public function provides()
    {
        return array('router');
    }

}

And a Facade, to replace Laravel's one

<?php namespace App\Facades;

use Illuminate\Support\Facades\Facade as IlluminateFacade;

class ExtendedRouteFacade extends IlluminateFacade {

    public static function is($name)
    {
        return static::$app['router']->currentRouteNamed($name);
    }

    public static function uses($action)
    {
        return static::$app['router']->currentRouteUses($action);
    }

    protected static function getFacadeAccessor() { return 'router'; }

}

Then you need to add your Service Provider and Facade to your app/config/app.php file, commenting the Laravel original ones.




回答2:


Im using route model bind.

I do this way.

<?php

namespace App\Http\Router;

use Illuminate\Support\Facades\Route;
use Illuminate\Routing\Router;

class CustomRouter extends Router
{
    public function customResource($routeName, $controllerPath, $routeBindName = null, $routeBindModel = null) {
        $routeBindName = $routeBindName ?? $routeName;

        $routeBindNameTrashed = "{$routeBindName}_trashed";

        if($routeBindModel && $routeBindName) {
            Route::model($routeBindName, $routeBindModel);
            Route::bind($routeBindNameTrashed, function($modelId) use ($routeBindModel) {
                return app($routeBindModel)->newQuery()->onlyTrashed()->findOrFail($modelId);
            });
        }

        Route::put("$routeName/{{$routeBindNameTrashed}}/restore", "{$controllerPath}@restore")->name("{$routeName}.restore");
        Route::delete("$routeName/{{$routeBindNameTrashed}}/force", "{$controllerPath}@forceDelete")->name("{$routeName}.force-delete");
        Route::resource($routeName, $controllerPath);
    }
}

Alter bootstrap/app.php

$app->singleton(
    'router', 
    App\Http\Router\CustomRouter::class
);

Then usage:

Route::customResource('projects', 'ProjectsController', 'project', \App\Models\Project::class);

Route:list




回答3:


Works like a charm

$routes = [
    'posts' => 'PostController',
    'posts.comments' => 'PostCommentController',
];

foreach ($routes as $key => $controller)
{
    Route::get("$key/deleted", array('uses' => "$controller@trash"));

    Route::put("$key/{id}/restore", array('uses' => "$controller@restore"));

    Route::resource($key, $controller);
}


来源:https://stackoverflow.com/questions/22559810/extend-resource-controllers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!