Laravel ルーティングについて

作成日:2019-03-25, 更新日:2019-04-01

基本

FuelPHPと違って結構面倒な感じ。

▼ざっくり3種。
・ルーティングと同時に出力内容を記載(クロージャー)
・ルーティングでコントローラーを呼びだす
・ルーティングでビューを呼びだす
※「routes/web.php」に記載

ルーティングと同時に出力内容を記載(クロージャー)

▼ブラウザで「/hello」を叩くと「hello world」が表示される

Route::get('hello', function () {
  return 'hello world';
});

ルーティングでコントローラーを呼びだす

▼ブラウザで「/hello」を叩くと「コントローラー:HelloController」の「アクション:index」を実行

Route::get('hello', 'HelloController@index');

※「コントローラー:HelloController」は「app\Http\Controllers\HelloController.php」

→コントローラーでビューを呼び出したりする。

ルーティングでビューを呼びだす

▼ブラウザで「/hello」を叩くと「ビュー:resources\views\hello.blade.php」を表示(実行)

Route::view('hello', 'hello');

※「Route::get()」じゃなく「Route::view()」になる

ルーティング時に値を渡したい

・「hello/〇〇〇」で「〇〇〇」を渡したい
→適当な文字列を「{}」で囲む。囲んだ文字列を引数で受取る
※コントローラを呼び出すときも同じ感じ

Route::get('hello/{name}', function ($name) {
  return 'hello ' . $name;
});

※「hello/」でアクセスがあったら値が無いので「404」になる。
※「{name}」を「$name」で受取っているけど単語の関連性は見やすさのみ。

▼「{name}」を「$name」じゃなくて別の変数名で受取る

Route::get('hello/{name}', function ($hoge) {
  return 'hello ' . $hoge;
});

▼複数の値を受け取る

Route::get('hello/{name}/{age}', function ($name, $age) {
  return 'hello ' . $name . ':' . $age;
});

▼どこに値をセットさせても大丈夫っぽい

Route::get('hello/{name}/home', function ($name) {
  return 'hello ' . $name;
});

▼コントローラを呼び出すとき

■ルーティング
Route::get('hello/{name}', 'HelloController@index');

■コントローラ
class HelloController extends Controller {
  public function index($name) {
  }
}

値が無くてもOKにしたい

・「hello/〇〇〇」でも「hello/」でもOKにしたい
→「{}」の中を「?」で終わらせる

Route::get('hello/{name?}', function ($name='everone') {
  return 'hello ' . $name;
});

※引数で初期値をセットせずに「/hello」でアクセスするとエラーになる。

値を正規表現で指定

・「Route::get()」に「where()」を追加(正規表現で指定)
※条件に合わない場合は「404」

▼「a~z」だけで構成されている場合

Route::get('hello/{name}', function ($name) {
  return 'hello ' . $name;
})->where('name', '[a-z]+');

※「^」「$」は必要ないみたい
※前述の「{name?}」と値が無くてもOKとしていると正規表現が無効になるっぽい。

使いそうなのは・・・
・数字のみ - where(〇〇〇, '[0-9]+')
・任意の文字と数字 - where(〇〇〇, 'post_[0-9]+')
・任意の文字と数字(8桁) - where(〇〇〇, 'news_[0-9]{8}')
・特定の単語のみ - where(〇〇〇, '(hoge|foo)')

▼複数あるとき

Route::get('hello/{name}/{age}', function ($name, $age) {
  return 'hello ' . $name . ':' . $age;
})->where([
   'name' => '[a-z]+',
   'age'  => '[0-9]+'
]);

「app\Http\Controllers」直下じゃなくて「app\Http\Controllers\〇〇〇」の下のコントローラーを使いたい

・「app\Http\Controllers\HelloController.php」ではなくて、
・「app\Http\Controllers\Zebra\HelloController.php」としたい。

▼ルーティング

Route::get('hello/{name?}', 'Zebra\HelloController@index');

▼コントローラー(app\Http\Controllers\Zebra\HelloController.php)

<?php
//namespace App\Http\Controllers;
namespace App\Http\Controllers\Zebra;

略
//class HelloController extends Controller {
class HelloController extends \App\Http\Controllers\Controller {
以下、略

※「use App\Http\Controllers\Controller」とかしたほうがいいんだろうけど「use」が好きになれないので継承時に絶対PATH指定

ルーティング内でリダイレクト

▼「/hoge」でアクセスがあったら「/foo」に301リダイレクト

Route::redirect('/hoge', '/foo', 301);

※使わなくなったページやメンテ中のページなどで使えそう。

コントローラーからリダイレクト

後述の「名前付きルート」参照。

名前付きルート

▼ルーティングで名前をつけておく

//// 名前付きルーティング
//route::get(〇〇〇, 〇〇〇)->name('profile');

// URLの生成してリダイレクト
$url = route('profile');
return redirect()->route('profile');
//// パラメータを付けたURLの生成
//Route::get('user/{id}/profile', function ($id) {
//    //
//})->name('profile');
$url = route('profile', ['id' => 1]);

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

ルーティングの記述をネストさせたい。

▼いくつか種類がある
・middleware - ?
・namespace - namespaceを使う
・domain - サブドメインを使う
・prefix - URLを使う
・name - ?

domaineでグループ化

例えば、サブドメインで見せたい・見せたくないページを指定したい。

▼「kushi.example.com/chicken」「kushi.example.com/zebra」をOKだけど「sake.example.com/chicken」「sake.example.com/zebra」はNGな例

Route::domain('kushi.example.com')->group(function(){
  Route::get('chicken', 'KushiController@chicken');
  Route::get('zebra',   'KushiController@zebra');
});
Route::domain('sake.example.com')->group(function(){
  Route::get('sake', 'SakeController@sake');
  Route::get('beer', 'SakeController@beer');
});

※「sake.example.com」は「/sake」「/beer」がOKになる。

prefixでグループ化

特定のフォルダ以下をまとめて設定したい

// ▼こういう風に書くのがイヤだってとき
// Route::get('kushi/chicken', 'KushiController@chicken');
// Route::get('kushi/zebra',   'KushiController@zebra');

Route::prefix('kushi')->group(function(){
  Route::get('chicken', 'KushiController@chicken');
  Route::get('zebra',   'KushiController@zebra');
});

domaineとprefixを組み合わせたい

// 「http://hoge.example.com/kushi/〇〇〇」のルーティング
Route::domain('hoge.example.com')->prefix('kushi')->group(function(){
  Route::get('chicken', 'KushiController@chicken');
  Route::get('zebra',   'KushiController@zebra');
});

ルーティング:RESTful

未調査。

「Route::resource()」ってヤツを使えばいいそうだ。

HTTPメソッド指定

「Route::get()」のトコが「post」や「put」「delete」などにする

GET ただのget送信
Route::get('〇〇〇', function(){ return 'Methodは「get」です'; });
POST 新規作成(insert)
Route::post('〇〇〇', function(){ return 'Methodは「post」です'; });
PUT 更新 or 新規作成(update or insert)
Route::put('〇〇〇', function(){ return 'Methodは「put」です'; });
PATCH PUTの範囲限定の更新
Route::patch('〇〇〇', function(){ return 'Methodは「patch」です'; });
DELETE データの削除時に使うmethod
Route::delete('〇〇〇', function(){ return 'Methodは「delete」です'; });
OPTIONS
Route::options('〇〇〇', function(){ return 'Methodは「options」です'; });

※POSTとPUTの違いがよく分からん。「POST:新規」「PUT:更新」とかなら分かりやすいのに・・・。

複数のメソッドに対応させる

「Route::get()」のトコが「match」になり、第一引数にメソッド名を追加する

▼「Route::match([メソッド], 〇〇〇, function(){})」・・・「post、put」のみ対応したいとき

Route::match(
  ['post', 'put'],
  '〇〇〇',
  function() {
    return 'Methodは「post」or「put」です';
  }
);

form送信をさせるとき

▼formタグが「PUT」「PATCH」「DELETE」「OPTIONS」に対応していないので「_method」を使う

<form method="POST">
  <input type="hidden" name="_method" value="PUT" />
</form>

API関連

・「http://〇〇〇/api/〇〇〇」は「ルーティング:routes/api.php」を使う

▼routes/api.php(「api/chicken」というURLの場合)

Route::get('chicken', 'KushiController@chicken');

※URLは「api」を省略して「chicken」以下を記載

URLの「api」を変更したい

「http://〇〇〇/api/〇〇〇」というURLが気に入らない場合「app/Providers/RouteServiceProvider.php」の「mapApiRoutes()」を書き換える
→「prefix('api')」を変更。

試していないけど使うミドルウェアやルーティングのファイルを変更したいときも同じ「mapApiRoutes()」の中を修正でいけるはず。