LoginSignup
4
4

More than 5 years have passed since last update.

laravel-5-boilerplateのルーティング(Backend編)

Last updated at Posted at 2016-01-18

laravel-5-boilerplateのルーティングの続きです

以前の記事で app/Http/route.php は読めたので、
次は app/Http/Routes/Backend/Access.php を読み進めます

//app/Http/Routes/Backend/Access.php

<?php
Route::group([
    'prefix'     => 'access',
    'namespace'  => 'Access',
    'middleware' => 'access.routeNeedsPermission:view-access-management',
], function() {
    /**
     * User Management
     */
    Route::group(['namespace' => 'User'], function() {
        Route::resource('users', 'UserController', ['except' => ['show']]);
        Route::get('users/deactivated', 'UserController@deactivated')->name('admin.access.users.deactivated');
        Route::get('users/deleted', 'UserController@deleted')->name('admin.access.users.deleted');
        Route::get('account/confirm/resend/{user_id}', 'UserController@resendConfirmationEmail')->name('admin.account.confirm.resend');
        /**
         * Specific User
         */
        Route::group(['prefix' => 'user/{id}', 'where' => ['id' => '[0-9]+']], function() {
            Route::get('delete', 'UserController@delete')->name('admin.access.user.delete-permanently');
            Route::get('restore', 'UserController@restore')->name('admin.access.user.restore');
            Route::get('mark/{status}', 'UserController@mark')->name('admin.access.user.mark')->where(['status' => '[0,1]']);
            Route::get('password/change', 'UserController@changePassword')->name('admin.access.user.change-password');
            Route::post('password/change', 'UserController@updatePassword')->name('admin.access.user.change-password');
        });
    });
    /**
     * Role Management
     */
    Route::group(['namespace' => 'Role'], function() {
        Route::resource('roles', 'RoleController', ['except' => ['show']]);
    });
    /**
     * Permission Management
     */
    Route::group(['prefix' => 'roles', 'namespace' => 'Permission'], function() {
        Route::resource('permission-group', 'PermissionGroupController', ['except' => ['index', 'show']]);
        Route::resource('permissions', 'PermissionController', ['except' => ['show']]);
        Route::group(['prefix' => 'groups'], function() {
            Route::post('update-sort', 'PermissionGroupController@updateSort')->name('admin.access.roles.groups.update-sort');
        });
    });
});

Laravelのルーティングの基本

ルートの名前

Route::get('users/deactivated', 'UserController@deactivated')->name('admin.access.users.deactivated');

各ルートに名前をつけることができます
名前を設定すると redirect時などに route('admin.access.users.deactivated')でアクセスできるようになります

Route::resource

Route::resource('users', 'UserController', ['except' => ['show']]);

これで以下のようにコントローラーにアクセスされます

namespace App\Controllers;
class helloController extends BaseController
{
    // getでusers/にアクセスされた場合
    public function index()
    {
        〜
    }

    // getでusers/createにアクセスされた場合
    public function create()
    {
        〜
    }

    // postでusers/にアクセスされた場合
    public function store()
    {
        〜
    }

    //などなど
}

詳しくはこちらの記事で解説されています
http://qiita.com/michiomochi@github/items/de19c560bc1dc19d698c

解説

まず、ルートグループで以下が設定されています
ルートのプレフィックスに /admin を利用
名前空間が App\Http\Controllers\Language~~ のコントローラーを利用
ミドルウェア access.routeNeedsPermission:view-access-management を利用

app/Http/Kernel.phpを見に行きます

//app/Http/Kernel.php

<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{

    // 省略

    protected $routeMiddleware = [

        // 省略

        'access.routeNeedsRole' => \App\Http\Middleware\RouteNeedsRole::class,
        'access.routeNeedsPermission' => \App\Http\Middleware\RouteNeedsPermission::class,
    ];

ミドルウェア名 access.routeNeedsPermission は
app/Http/Middleware/RouteNeedsPermissionを読み込んでいることがわかります

//app/Http/Middleware/RouteNeedsPermission.php

<?php

namespace App\Http\Middleware;

use Closure;

class RouteNeedsPermission
{
    public function handle($request, Closure $next, $permission)
    {
        if (! access()->allow($permission)) {
            return redirect()
                ->route('frontend.index')
                ->withFlashDanger(trans('auth.general_error'));
        }

        return $next($request);
    }
}

このミドルウェアでは以下のことを行っています
1. $request$permission を受け取る
2. access()->allow($permission)を評価する
3. route('frontend.index')へリダイレクトさせる or 次のミドルウェアへ進める

では、access()->allow($permission) の中身を見に行きます
access()はヘルパー関数です
Laravelデフォルトのものではなさそうなのでapp/helper.phpを確認します

<?php

//省略

if (! function_exists('access')) {
    /**
     * Access (lol) the Access:: facade as a simple function
     */
    function access()
    {
        return app('access');
    }
}

//省略

ありましたね
では次は app/Providers/AccessServiceProvider.php を確認

<?php

namespace App\Providers;

use App\Services\Access\Access;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

/**
 * Class AccessServiceProvider
 * @package App\Providers
 */
class AccessServiceProvider extends ServiceProvider
{

    //省略

    private function registerAccess()
    {
        $this->app->bind('access', function ($app) {
            return new Access($app);
        });
    }

    //省略
}

app/Services/Access.phpが正体ですね、見てみましょう

//app/Services/Access

<?php

namespace App\Services\Access;

class Access
{
    public $app;

    public function __construct($app)
    {
        $this->app = $app;
    }

    public function user()
    {
        return auth()->user();
    }

    //省略

    public function allow($permission)
    {
        if ($user = $this->user()) {
            return $user->allow($permission);
        }

        return false;
    }

    //省略
}

allowメソッドは以下の作業を行います
ログイン中のユーザーのUserクラスのインスタンスを取得し、
$user->allow($permission)でパーミッションを所持しているか確認
ユーザーがログインしており、かつ求められたパーミッションを所有している場合のみtrueを返す

では、$user->allow() を見に行きます
userクラスはapp/Models/Access/User.phpに記述されています

//app/Models/Access/User.php

<?php
namespace App\Models\Access\User;
use App\Models\Access\User\Traits\UserAccess;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Models\Access\User\Traits\Attribute\UserAttribute;
use App\Models\Access\User\Traits\Relationship\UserRelationship;

class User extends Authenticatable
{
    use SoftDeletes, UserAccess, UserAttribute, UserRelationship;

    protected $guarded = ['id'];

    protected $hidden = ['password', 'remember_token'];

    protected $dates = ['deleted_at'];
}

allow()が定義されてないませんが、
これは trait (トレイト)として app/Models/Access/User/Traits/UserAccess.phpを読み込んでいるからです

//app/Models/Access/User/Traits/UserAccess.php

<?php

namespace App\Models\Access\User\Traits;

/**
 * Class UserAccess
 * @package App\Models\Access\User\Traits
 */
trait UserAccess
{
    //省略    

    public function allow($nameOrId)
    {
        foreach ($this->roles as $role) {
            //See if role has all permissions
            if ($role->all) {
                return true;
            }

            // Validate against the Permission table
            foreach ($role->permissions as $perm) {

                //First check to see if it's an ID
                if (is_numeric($nameOrId)) {
                    if ($perm->id == $nameOrId) {
                        return true;
                    }
                }

                //Otherwise check by name
                if ($perm->name == $nameOrId) {
                    return true;
                }
            }
        }

        //Check permissions directly tied to user
        foreach ($this->permissions as $perm) {

            //First check to see if it's an ID
            if (is_numeric($nameOrId)) {
                if ($perm->id == $nameOrId) {
                    return true;
                }
            }

            //Otherwise check by name
            if ($perm->name == $nameOrId) {
                return true;
            }
        }

        return false;
    }

    //省略
}

ありました!

詳しくは解説しませんが、ログイン中のユーザーがパーミッションを持っているかforeachでループしながら確認しています。

長くなりましたが、これがミドルウェアaccess.routeNeedsPermissionの正体です

もう一度、app/Http/Routes/Backend/Access.phpを確認します

//app/Http/Routes/Backend/Access.php

<?php
Route::group([
    'prefix'     => 'access',
    'namespace'  => 'Access',
    'middleware' => 'access.routeNeedsPermission:view-access-management',
], function() {

    /*
     * ルーティング
     */

});

access.routeNeedsPermissionにview-access-managementを渡しています
これはミドルウェアaccess.routeNeedsPermission側で$permissionとして受けとり処理を行います

とりあえず以上
気が向いたら追記します

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4