【Laravel 5.8 】「こんなとき」のミドルウェア全7実例(ダウンロード可)

さてさて、私がLaravelを使い始めたのはバージョン4.2が出てすぐだったのですが、現在はすでに最新バージョンが5.8になり、ちらほら5.9の話題もニュースとしてみかけるようになりました。

そして、前バージョンをよく使っていた開発者からすると「今は普通に使っているけど、すごく強力な機能」の便利さを再認識する場面が結構あったりします。

そして、その中のひとつが今回の話題「ミドルウェア」です。

ミドルウェアとは、ページにアクセスする直前に実行されるもので、条件によってリダイレクトしたり別のページを見せるといったことが簡単にできるようになっています。(例えば、ログインしたユーザーしか見られないページもミドルウェアのひとつですね)

ということで、今回はこのミドルウェアの基本的な使い方と「こんなとき」に使えるサンプルを実例で紹介してみたいと思います。

ぜひ、皆さんのお役に立てると嬉しいです😊✨
最後にソースコード一式をダウンロードできます!

開発環境: Laravel 5.8

ミドルウェアの基本的な使い方

ミドルウェアの作り方

Laravelにはミドルウェアを作成するコマンドが用意されていますので、これを使います。例えば、管理者だけが見られるようなミドルウェアを作成する場合は次のようになります。

php artisan make:middleware AdminAuth

すると、app/Http/Middleware/AdminAuth.phpが作成され、中身は以下のようになっています。

<?php

namespace App\Http\Middleware;

use Closure;

class AdminAuth
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

そして、この中に管理者だけが表示できるようコードを追加します。例としては以下のようになります。

public function handle($request, Closure $next)
{
    if(auth()->check() && auth()->user()->role === 'admin') {

        return $next($request);

    }

    abort(403, '管理者権限がありません。');
}

つまり、return $next($request);を実行すれば通常通りページが表示されるということになります。

また、条件が合わなかったときにリダイレクトすることもできます。その場合は次のようにしてください。

public function handle($request, Closure $next)
{
    if(auth()->check() && auth()->user()->role === 'admin') {

        return $next($request);

    }

    return redirect('/');
}

ミドルウェアの設置方法

特定のページのみ有効にする

ミドルウェアは作成しただけでは有効になりません。ミドルウェアを有効にするには、app/Http/Kernel.phpに登録をする必要があります。

そして、ある特定のページだけでミドルウェアを有効にしたい場合はこのファイル内の$routeMiddlewareに登録することになります。

protected $routeMiddleware = [

    // 省略

    'admin_auth' => \App\Http\Middleware\AdminAuth::class
];

そして、登録が完了したら、次は実際のルートに適用させます。

Route::get('admin', 'AdminController@index')->middleware('admin_auth');

これでhttp://******/adminにはAdminAuthミドルウェアが適用されることになります。

ただし、この方法ではページが増えていくごとに毎回middleware()を書かなければいけませんので少しめんどうですよね。その場合には次のようにgroup()を使って一気にミドルウェアを指定することができます。

Route::group(['middleware' => 'admin_auth'], function(){

    // この中は、全てミドルウェアが適用されます。
    Route::get('middleware_test', 'HomeController@middleware_test');

});

さらに、実はミドルウェアはコントローラーにも設置することができて、その場合は以下のように__construct()内で指定します。

class HomeController extends Controller
{
    public function __construct() {

        $this->middleware('admin_auth');

        // もしくは、「特定のメソッドだけ」か「特定のメソッド以外」
        $this->middleware('admin_auth')->only(['index', 'create']);
        $this->middleware('admin_auth')->except(['edit', 'destroy']);

    }

全てのページで有効にする

続いて、全てのページでミドルウェアを有効にする方法です。この場合、app/Http/Kernel.php内の$middlewareGroupsに作成したミドルウェアを登録することになります。

protected $middlewareGroups = [
    'web' => [

        // 省略

        \App\Http\Middleware\AdminAuth::class,
    ],

これで全てのページにミドルウェア適用されることになります。

では基本的な使い方は以上ですので、次の項目からは実際のケーススタディで見ていきましょう!

こんなときのミドルウェア・実例

HTTPS接続のみを許可する(自動リダイレクト)

もしHTTPで接続してきた場合は強制的にHTTPSのURLに転送するミドルウェアです。

<?php

namespace App\Http\Middleware;

use Closure;

class OnlyHttps
{
    public function handle($request, Closure $next)
    {
        if(!$request->secure() && env('APP_ENV') === 'production') {

            return redirect()->secure($request->getRequestUri());
            
        }

        return $next($request);
    }
}

IF文の中身としては、

  • HTTPで接続しているか?
  • 実行環境が production(つまり本番環境)か?

をチェックし、もし両方ともtrueであればリダイレクトするという流れになります。

特定のIPアドレスだけ許可する

例えば、ある特定のIPアドレスだけからしかページを見ることができなくなるミドルウェアです。

<?php

namespace App\Http\Middleware;

use Closure;

class IpAddress
{
    public function handle($request, Closure $next)
    {
        if($request->ip() !== '111.111.111.111') {

            return redirect('/');

        }

        return $next($request);
    }
}

なお、IPアドレスを範囲で指定したい場合は以下のようにするといいでしょう。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Str;

class IpAddressRange
{
    public function handle($request, Closure $next)
    {
        if(!Str::startsWith($request->ip(), '111.111.111.')) {

            return redirect('/');

        }

        return $next($request);
    }
}

ユーザータイプで許可/拒否

例えば、usersテーブルにrole(つまりユーザータイプ)のデータが入っていて、これがadminもしくはsuper_adminの場合だけページ閲覧できるようになるミドルウェアです。

<?php

namespace App\Http\Middleware;

use Closure;

class AdminAuth
{
    public function handle($request, Closure $next)
    {
        if(auth()->check()) {

            $role = auth()->user()->role;

            if(in_array($role, ['admin', 'super_admin'])) {

                return $next($request);

            }

        }

        abort(403, '管理者権限がありません。');
    }
}

特定の言語のみ許可する

例えば、あるウェブサイトが日本語だけ対応していてるので日本語が理解できる人たちだけにページ表示をしたい場合です。

<?php

namespace App\Http\Middleware;

use Closure;

class OnlyJapanese
{
    public function handle($request, Closure $next)
    {
        if(!in_array('ja', $request->getLanguages())) {

            abort(403);

        }

        return $next($request);
    }
}

※ ただし、言語情報はブラウザのヘッダーを元にして取得しているので、その気になればブラウザ設定でいくらでも変更は可能です。

スマホの場合はリダイレクト

例えば、あるウェブサイトにはスマートフォン専用のページがあり、もしスマートフォンでアクセスしてきた場合はそちらへリダイレクトさせたい場合です。

<?php

namespace App\Http\Middleware;

use Closure;

class Smartphone
{
    public function handle($request, Closure $next)
    {
        $detect = new \Mobile_Detect();

        if($detect->isMobile() || $detect->isTablet()) {

            return redirect('/smartphone');

        }

        return $next($request);
    }
}

※ なお、スマートフォン(タブレット)の判別は、mobile detectというパッケージを使っています。インストールは以下のコマンドで実行してください。

composer require mobiledetect/mobiledetectlib

特定の国からだけ許可

例えば、日本国内からのアクセスのみを許可するミドルウェアです。

<?php

namespace App\Http\Middleware;

use Closure;

class OnlyInJapan
{
    public function handle($request, Closure $next)
    {
        $geo = unserialize(
            file_get_contents('http://www.geoplugin.net/php.gp?ip='. $request->ip())
        );

        if($geo['geoplugin_countryCode'] !== 'JP') {

            abort(403);

        }

        return $next($request);
    }
}

※ ただし、この方法はgeoplugin.comというサイトのAPIを利用しているため、ページの表示に時間がかかってしまう場合があります。(そのため、もし可能であればnginxなどでIPを範囲で許可するなどの方がいいかもしれません)

特定の曜日のみ表示を許可する

例えば、水曜日だけ商品が割引になる申し込みページを作りたい場合です。

<?php

namespace App\Http\Middleware;

use Carbon\Carbon;
use Closure;

class OnlyWednesday
{
    public function handle($request, Closure $next)
    {
        $dt = new Carbon();

        if($dt->dayOfWeek !== 3) {

            abort('403', '水曜日のみ閲覧できます');

        }

        return $next($request);
    }
}

ソースコードをダウンロードする

今回実際に開発したファイルを以下からダウンロードすることができます。

【Laravel 5.8 】「こんなとき」のミドルウェア全7実例

おわりに

ということで、今回は「こんなとき」に焦点をあててミドルウェアの紹介をしてみました。

使い方によってはより様々な制限やリダイレクトを実装することができますので、ぜひみなさんもいろいろ試してみてはいかがでしょうか。

ではでは〜!

「クラフトビールって美味しいですね」