【Laravel】ルーティングファイル(web.php)の中でリダイレクト設定する方法（パラメータ付きURLに条件分岐で適用する実例）

使わなくなったページをweb.phpの中でリダイレクトする方法について。比較的自由度が高いので、同じ処理でも書き方がいくつか存在する。

**302転送と301転送それぞれの指定方法**および、

パラメータ付きのURIの転送設定をする場合は、意図しない転送を防ぐために個別にURLを指定することが推奨となる。これを**配列とforeachを使って簡潔に記述する方法**について。


##目次

1. [リダイレクト先をURIで指定する方法](#1-リダイレクト先をuriで指定する方法)
1. [リダイレクト先をルート名で指定する方法](#2-リダイレクト先をルート名で指定する方法)
1. [Route::getとreturnを使う方法](#3-routegetとreturnを使う方法)
1. [パラメータ付きURIの転送設定（条件の設定）](#4-パラメータ付きurlの転送設定条件の設定)



<br>
##1. リダイレクト先をURIで指定する方法

デフォルトの転送設定は302（一時的な転送）。
301（永続的な転送）にしたい場合は記述する必要がある。

```php:web.php（302転送）
Route::redirect('/old-url', '/new-url');
```

<br>
###301転送の設定

```php:web.php（301転送）
Route::redirect('/old-url', '/new-url', 301);
```

または`permanentRedirect`メソッドを使う。

```php:web.php（301転送）
Route::permanentRedirect('/old-url', '/new-url');
```



<br>
##2. リダイレクト先をルート名で指定する方法

```php:web.php（302転送）
//転送先ルート
Route::get('/user', 'UserController@index')->name('user');

//リダイレクト設定
Route::redirect('/old-url', route('user') );
```


<br>
###301転送の設定

```php:web.php（301転送）
//転送先ルート
Route::get('/user', 'UserController@index')->name('user');

//リダイレクト設定
Route::redirect('/old-url', route('user'), 301 );
```

または`permanentRedirect`メソッドを使う。

```php:web.php（301転送）
//転送先ルート
Route::get('/user', 'UserController@index')->name('user');

//リダイレクト設定
Route::permanentRedirect('/old-url', route('user') );
```



<br>
##3. Route::getとreturnを使う方法
コントローラ@アクションや、return viewを指定している部分の戻り値にredirectを指定する。

```php:web.php（302転送）
Route::get('/old-url', function(){
  return redirect('/new-url');
});
```

###ルート名で指定する場合

```php:web.php（302転送）
//転送先ルート
Route::get('/user', 'UserController@index') -> name('user');

//リダイレクト設定
Route::get('/old-url', function(){
  return redirect() -> route('user');
});
```

または

```php:web.php（302転送）
//リダイレクト設定
Route::get('/old-url', function(){
  return redirect( route('user') );
});
```


<br>
###301転送の設定

```php:web.php（301転送）
Route::get('/old-url', function(){
   return redirect( '/new-url', 301 );
});
```

####ルート名で指定する場合

```php:web.php（301転送）
//転送先ルート
Route::get('/user', 'UserController@index') -> name('user');

//リダイレクト設定
Route::get('/old-url', function(){
  return redirect( route('user'), 301 );
});
```


<br>
##4. パラメータ付きURLの転送設定（条件の設定）
パラメータ付きのURIの転送設定をする場合は、個別にURLを指定することが推奨される。

**▼個別に指定する理由**

- リダイレクト対象のURLを明確にする。
- 意図しないリダイレクトが発生するリスクを防ぐ。


##実例
例えば、以下のようにproduct/{prd_slug}で特定の製品名の詳細ページを`/product`にリダイレクトする処理は以下のようになる。

```php:web.php（元のルーティング）
Route::get('product/{prd_slug}', 'ProductController@show')
   -> name('product.show');
```

<br>
###リダイレクトの設定
###1. 正規表現で指定する
whereメソッドと正規表現を使って指定する。

`->where( 'パラメータ名', '正規表現' )`

```php:正規表現の例
Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
```

https://readouble.com/laravel/7.x/ja/routing.html#parameters-regular-expression-constraints


###配列から正規表現を作成する方法
対象のslugが複数ある場合は配列から正規表現を作成すると簡単。

```php:web.php
$removed_slugs = [ 'iphone5', 'iphon6',  'iphone6s' ];
$removed_slugs = implode( '|', $removed_slugs );
$regexs['removed_slugs'] = '(' . $removed_slugs . ')';
```

**・`implode( '繋ぐ文字列', 配列 )`**
配列を指定した文字列で繋ぎ合わせて、一つの文字列に変換する。


この処理で、`[ 'iphone5', 'iphon6',  'iphone6s' ]`を`( 'iphone5' | 'iphon6' | 'iphone6s' )`に変換できる。

正規表現で`( 'aaa' | 'bbb' )`の形は、aaaかbbb
という意味。

これをwhereメソッドの第２引数で指定する。


```php:web.php
$removed_slugs = [ 'iphone5', 'iphon6',  'iphone6s' ];
$removed_slugs = implode( '|', $removed_slugs );
$regexs['removed_slugs'] = '(' . $removed_slugs . ')';

Route::get('product/{product_slug}', function() use ($regexs) {
    return redirect( route('product'), 301 );
    })->where('product_slug', $regexs['removed_slugs']  );
});
```


**・`function() use ($変数名)`**
functionの外で定義した変数を使う場合には`use ($変数名)`で宣言する必要がある。

これがないとエラーになる。






<br>
###2. foreachで指定する
おすすめではないがforeachを使って記述することも可能。
リダイレクト対象となるパラメータの値を配列に入れて、foreachで抜き出し一つ一つリダイレクト設定をかける。

```php:web.php（リダイレクト設定301）
//転送先ルート
Route::get('/product', 'ProductController@index') -> name('product');


//リダイレクト設定
$removedSlugs = [ 'iphone5', 'iphon6',  'iphone6s' ];
   foreach ( $removedSlugs as $removedSlug ){
     Route::get('product/' . $removedSlug, function(){
        return redirect( route('product'), 301 );
     });
};
```

以下と同じになる。

```php:web.php（リダイレクト設定301）
Route::get('product/iphone5', function(){
  return redirect( route('product'), 301 );
});
Route::get('product/iphone6', function(){
  return redirect( route('product'), 301 );
});
Route::get('product/iphone6s', function(){
  return redirect( route('product'), 301 );
});
```

対象ページが多い場合は、配列とforeachを使うことで記述をかなり省略できる。


<br>
###よくない事例
パラメータ付きルート自体にリダイレクト設定をかけてしまうと、本来リダイレクト対象でないページまで301転送がかかってしまう。

```php:web.php
Route::get('product/{prd_slug}', function(){
  return redirect( route('product'), 301 );
});
```


<br>
##参考リンク

https://readouble.com/laravel/8.x/ja/routing.html

<br>
以上。