RitoLabo

Laravelルーティングの基本とよく使われるルーティングパターン

  • 公開:
  • 更新:
  • カテゴリ: PHP Laravel
  • タグ: PHP,Laravel,5.5,5.4,5.3,Beginner,5.6,Routing

Laravelでコントローラはじめ、何かの機能を作成したら、そこへのアクセスを制御するにはどうしたらよいでしょうか?

Laravelでは、ブラウザからのURLアクセスやAPIによるアクセスに対してのルーティングを設定するファイルがあります。

今回は、Laravelのルーティングの基本と、よく使われるルーティングを見ていきます。

アジェンダ
  1. 開発環境
  2. ルーティングファイル
  3. ルート定義メソッド
  4. クロージャによるルーティング
  5. コントローラへのルーティング
    1. URLからパラメータを取得する
      1. パラメータなしを許容する
      2. パラメータの値に制約を設ける
  6. ビューへのルーティング
  7. リダイレクト
  8. 名前付きルート
    1. リダイレクト
    2. URLの生成
  9. ミドルウェア
  10. ルーティングのグループ化

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Apache 2.4
  • PHP 7.2/7.1
  • Laravel

Laravelのバージョンについては、5.6/5.5/5.4/5.3にて動作確認済みです。

Laravelのルートディレクトリを「laravel/」としています。

ルーティングファイル

Laravelで通常のブラウザからのHTTPリクエストに対するルーティング設定を行う場合は laravel/routes/web.php で行います。

laravel/routes/web.php
<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
return view('welcome');
});

デフォルトでは1つのルーティングのみが設定されています。このルーティングは、Laravelのウェルカムページ(インストール後にブラウザからアクセスして表示されるページ)のルーティングになります。

また一方で、API通信などをルーティングする際は laravel/routes/api.php で行います。

両者の最も大きな違いは、適用されるミドルウェアが違う事です。web.phpは、主にクライアント操作で起こるリクエスト(リンクを押下して画面遷移する・フォームを送信するなど)でのルーティングを行うので、CSRF対策やセッション関係などのミドルウェアがデフォルトでは適用されますが、api.phpの方はもっとミニマムなミドルウェアが適用されます。

もちろん、両者のミドルウェア設定は変更可能です。

今回は基本的なルーティングを行うので、web.phpを編集していきます。

ルート定義メソッド

ルーティングにはRouteファサードを使いますが、HTTPリクエストに対して定義できるメソッドの基本項目は以下になります。

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

上から解説します。

Route::get($uri, $callback);

GETリクエストに対してのルーティングを定義します。主に通常のURL遷移やフォームのGETリクエストに対して用います。

Route::post($uri, $callback);

POSTリクエストに対してのルーティングを定義します。主にフォームのPOSTリクエストに対して用いられます。

Route::put($uri, $callback);

putリクエストに対してのルーティングを定義します。

Route::patch($uri, $callback);

patchリクエストに対してのルーティングを定義します。

Route::delete($uri, $callback);

deleteリクエストに対してのルーティングを定義します。

Route::options($uri, $callback);

optionsリクエストに対してのルーティングを定義します。

put/patch/delete/optionsメソッドに関してはREST APIなどを作成する時に使われたりしますが、基本的に使用するのはGETとPOSTメソッドがほとんどです。

また、post() put() delete()メソッドを用いる際は、送信元からCSRFトークンフィールドを渡す必要があります。

クロージャによるルーティング

ルーティングメソッドの最も基本的なものは、コールバックをクロージャで定義する事です。

Route::get('sample/route', function () {
return 'PHP Framework Laravel Routing!!';
});

上記を設定したら、ブラウザから http://YOUR-DOMAIN/sample/route へアクセスしてみてください。「PHP Framework Laravel Routing!!」という文字列がブラウザに表示されます。

上記のルーティングは、間にコントローラもビューも挟まずに、ただ文字列だけを返す、最もシンプルな形になります。

例えばちょっとした処理を確認したりする場合にはこういった書き方をしてサクッと動作を確認したりに使う事も出来ます。

Route::get('sample/route/1', function () {
$result = 5 * 20;
return $result;
});

例えば上記のような場合は、単純に掛け算を行ってそれを表示します。ブラウザからアクセスすると、「100」と表示されます。

コントローラへのルーティング

ブラウザからどのURLにアクセスした時に、どのコントローラへ処理を渡すかを設定します。コントローラへのルーティングは、以下のように記述します。

laravel/routes/web.php
Route::get('sample', 'SampleController@index');

この場合は、ブラウザから http://YOUR-DOMAIN/sample にアクセスすると、SampleControllerのindex()メソッドへ処理を渡す。という事になります。

例えば以下の場合では

Route::get('sample/member/1', 'SampleController@member');

ブラウザから http://YOUR-DOMAIN/sample/member/1 にアクセスすると、SampleControllerのmember()メソッドへ処理を渡す。という事になります。

URLからパラメータを取得する

URLからコントローラ側へパラメータを渡したい時は以下のように記述します。

laravel/routes/web.php
Route::get('sample/member/{member_id}', 'SampleController@member');

例えば上記のように {member_id} と記述すると、コントローラ側で変数 $member_id としてパラメータを取得する事が出来ます。コントローラ側では以下のようにして取得できます。

laravel/app/Http/Controllers/SampleController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class SampleController extends Controller
{
public function member($member_id)
{
print_r($member_id);
}
}

もちろん、これはいくつでも設定できます。

Route::get('sample/member/{member_id}/group/{group}/type/{type}', 'SampleController@member');

コントローラでは以下のようにして取得できます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class SampleController extends Controller
{
public function member($member_id, $group, $type)
{
$params = [
'member_id' => $member_id,
'group' => $group,
'type' => $type,
];

print_r($params);
=> Array
(
[member_id] => 12
[group] => 1-2
[type] => student
)

}
}

尚、上記の設定の場合はパラメータ部分は必ず渡されなければなりません。例えば、member_idのみを渡すルーティングの場合で、 http://YOUR-DOMAIN/sample/member/ の場合は例外(404)が発生します。

パラメータなしを許容する

パラメータ部分について、入力を任意のものとしたい(パラメータが無くても許容する)場合は以下のように記述します。

Route::get('sample/member/{member_id?}', 'SampleController@member');

{member_id?} とする(末尾にクエスチョンマーク「?」を付ける)事で、パラメータが無くても許容されます。

もちろん、この場合はコントローラ側でパラメータが無い場合の処理も漏れずに記述しましょう。

パラメータの値に制約を設ける

URLからパラメータを受け取るとして、その全てが許容されていると、入力値の評価をいちいちコントローラ側で行わなくてはならなくなります。URLは誰にでも変更できるものなので攻撃の対象にもなりやすく、受け取るパラメータは出来るだけコントローラに渡す前に評価しておきたいものです。

そんな場合は以下のようにする事で、コントローラへ渡すパラメータ値をルーティングの時点で評価する(制限を設ける)事が出来ます。

Route::get('sample/member/{member_id}', 'SampleController@member')
->where('member_id', '[0-9]+');

この場合は、パラメータとしてコントローラに渡されるmember_idは、数字の連続のみ受け付けるという制約が設定されます。それ以外、例えば文字列などが渡された場合は例外(404)が返ります。

複数のパラメータに対して制約を設ける場合は、配列で渡します。

Route::get('sample/member/{member_id}/group/{group}/type/{type}', 'SampleController@member')
->where([
'member_id' => '[0-9]+',
'group' => '[A-Za-z]+',
'type' => '[0-9]{2}'
]);

また、たくさんの制限を設ける必要がある場合に、その全てをルーティングに記述するとルーティングファイルが煩雑になります。それを好まない場合は、ルーティングのサービスプロパイダに制約を定義する事が出来ます。

laravel/app/Providers/RouteServiceProvider.php
public function boot()
{
Route::pattern('member_id', '[0-9]+');
Route::pattern('group', '[A-Za-z]+');
Route::pattern('type', '[0-9]{2}');

parent::boot();
}

boot()メソッド内にて、Routeファサードのpattern()メソッドでそれぞれの制約を定義します。

こうする事で、ルーティング時に記述したパラメータ指定に関しての全てにこのルールが適用される({id}と書くとidプロパティの制約が適用される)ので、ルーティングにいちいち制約を記述しなくて良くなります。

ビューへのルーティング

コントローラではなくビューへルーティングを行いたい場合はview()メソッドで設定します。

Route::view('sample/view', 'sampleview');

上記の場合、コントローラは経由せずに、直接ビューへのルーティングが行われます。

ビューへ値を渡したい場合は、第二引数へ配列で渡します。

Route::view('sample/view', 'sampleview', ['number' => 123456789]);

リダイレクト

ルーティング内でリダイレクトを行う場合は、redirect()メソッドを用いて以下のように記述します。

Route::redirect('/sample/from', '/sample/to', 301);

上記の場合、http://YOUR-DOMAIN/sample/from へのアクセスに対して http://YOUR-DOMAIN/sample/to へ301リダイレクトを行います。

名前付きルート

ルーティングに名前を付ける事ができます。名前をつけると、設定したルート名のみを指定し処理を書けば良くなるので便利です。

Route::get('sample', 'SampleController@index')->name('sample');

リダイレクト

例えば以下のようなルーティングがあったとします。

Route::get('sample/from', 'SampleController@from');

Route::get('sample/to', 'SampleController@to')->name('to');

to()メソッドへのルーティングに対してルート名「to」を設定しています。

その場合、コントローラ側ではリダイレクトを以下のように記述できます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class SampleController extends Controller
{
public function from()
{
// ルート名「to」へリダイレクト
return redirect()->route('to');
}

public function to()
{
print_r('リダイレクト');
}
}

この例では、fromからtoへ名前付きルートでリダイレクトが行われます。

URLの生成

ルート名を使ってURLを作成できます。

public function from()
{
$url = route('to');
print_r($url);
=> http://YOUR-DOMAIN/sample/to
}

ミドルウェア

あるルーティングに対して何らかのミドルウェアを適用させる場合は、以下のように記述します。

Route::get('sample', 'SampleController@index')->middleware('html.minify');

上記は、指定のルーティングに対して、HTMLをminifyするミドルウェアを指定している例になります。

ルーティングのグループ化

ルーティングの際にミドルウェアを適用させたいページがあるとして、それらが複数ページに及ぶ場合(同じミドルウェアを複数のルーティングに挿したい)があります。その時は、それらのルーティングをグループ化し、ミドルウェアを指定する事で、設定をまとめて行えます。

Route::group(['middleware' => 'basic_auth', 'prefix' => ''], function() {
Route::get('/login', 'LoginController@index')->name('login');
Route::get('/member/list', 'MemberController@index')->name('member');
Route::get('/member/add', 'MemberController@add');
Route::get('/member/edit', 'MemberController@edit');
});

上記は、ログインページと、ログイン認証を必要とするページ全てに、Basic認証をかけるミドルウェアを適用させる場合の記述例です。

このように、group()メソッドを用いてミドルウェアを指定し、対象のルーティングをコールバックでラップする事で設定を行う事が出来ます。

Route::middleware('basic_auth')->group(function () {
Route::get('/login', 'LoginController@index')->name('login');
Route::get('/member/list', 'MemberController@index')->name('member');
Route::get('/member/add', 'MemberController@add');
Route::get('/member/edit', 'MemberController@edit');
});

こちらはミドルウェアの設定先に対してグループを指定しているので、前者と後者の例は指定が逆になっているだけで、同じ意味になります。

まとめ

今回触れた部分はほんの基礎部分であり、ルーティングはまだまだたくさんの使い方があります。使いこなせるようになると複雑なルーティングも実現できるようになります。

また、通常ならばコントローラで行っていたような事も、実はルーティングで設定してまえば簡単に処理の流れが実現出来てしまう事などもあるので、上手く使いこなしてみてください。