LaravelでURLを取得する全6項目・実例!

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、Laravelを使った開発ではリダイレクトの場合など、しばしばある特定のURLを取得する必要が出てくる場合があります。

もちろんURLを直接 https://****.com/test1/test2 というように直にコーディングしてもいいのはいいのですが、LaravelにはパラメータつきでURLを取得したりルーティングやコントローラーからもURLが取得できるため、これらのテクニックを知っているとコーディングがとても楽になります。

また、特にルーティング名を使ってURLを取得しておくと、その後サイト構成が変わってしまってもそのままURLは自動的に切り替わりますし保守的にもプラスな部分もあります。

ということで、今回はLaravelでURLを取得する全実例をお届けします。

ぜひ開発の参考にしてください。

※ Laravelのバージョン: 5.7

実行環境について

今回紹介する全てのコードはhttp://example.testというローカルサイトで実行しています。そのため、ご自身の環境で実行した場合とドメイン部分が違ってきますのでご注意ください。

基本的なURLの取得方法: url()

まずLaravelで一番基本的なURLの取得方法はヘルパー関数のurl()を使ったものです。

トップページのURLを取得する

url()の引数に空白、もしくは/を指定するとトップページを取得することができます。

echo url('');
echo url('/');

ページを指定してURLを取得する

例えば、http://example.test/xxx.htmlというURLを取得したい場合です。
この場合、url()の引数に直接xxx.htmlを指定します。

echo url('xxx.html');

階層が深いページを指定してURLを指定する

例えば、http://example.test/xxx/yyy/zzzというURLを取得したい場合です。同じく引数に取得したい階層を指定します。

echo url('xxx/yyy/zzz');

もしくは、次のように第2引数に配列を指定することで取得することもできます。

echo url('/', ['xxx', 'yyy', 'zzz']);

パラメータをつけたURLを取得する

例えば、http://example.test/xxx?key=valueというURLを取得する場合です。

echo url('xxx?key=value');

https://から始まるURLを取得する

例えば、https://example.testというURLを取得する場合です。
この場合、第3引数にtrueを指定します。

echo url('/', null, true);

パラメータを含まない現在のURLを取得する: current()

例えば、現在のURLが"http://example.test/xxx?key=value"だったとして、"http://example.test/xxx"を取得する場合です。

echo url()->current();

パラメータを含む現在のURLを取得する: full()

例えば、現在のURLが"http://example.test/xxx?key=value"だったとして、 そのままパラメータを含めた"http://example.test/xxx?key=value"を取得する場合です。

echo url()->full();

直前にリクエストされたURLを取得する: previous()

echo url()->previous();

ルーティングを使ったURLの取得

全120種類!Laravel5.6ヘルパー関数実例route()でルート名を指定してURLを取得する をご覧ください。

コントローラーを使ったURLの取得

全120種類!Laravel5.6ヘルパー関数実例action()でコントローラーとアクションからURLを取得する をご覧ください。

署名つきURLを取得する

例えば次のような流れを考えてください。

  1. パスワードの変更申請をする
  2. 署名つき(一意な文字列がついた)URLがメール送信されてくる
  3. そのURLにアクセスするとパスワード変更ができる

この場合の2番目の項目で必要になる署名付きURLを作成する方法です。

URLを取得する方法

ではこのURLの取得方法です。
まずルーティングを設定しましょう。

Route::get('user/password_reset', 'User\HomeController@password_reset')->name('user.password_reset');

そして、URL::signedRoute()を実行します。

use Illuminate\Support\Facades\URL;
echo URL::signedRoute('user.password_reset', ['user_id' => 1]);

これを実行すると次のようなURLを発行されることになります。

http://example.test/user/password_reset?user_id=1&signature=757ae5fea4f5b7cecc9aa741a378d4fc25aeaac758c27d9d06f92c562a660faf

このsignatureの部分が署名で、一意な文字列になり後ろのパラメータが変わると文字列は変更になります。

また、制限時間がある署名URLを取得することもできます。(つまり、「このリンクの有効時間は24時間です」という時間制限があるURLになります)

use Illuminate\Support\Facades\URL;
$expire = now()->addHours(24);

echo URL::temporarySignedRoute(
    'user.password_reset',  // ルーティング名
    $expire,                // 有効期限(この場合24時間)
    ['user_id' => 1]        // パラメータ
);

実際にこのコードを実行したものが以下になります。

http://example.test/user/password_reset?expires=1542652227&user_id=1&signature=4bcc7e874128d6f10071f3dd746cde4bf1a92065d44ca2b1ef0ce2c1fe6d4366

取得した署名つきURLが有効かチェックする

ルーティング内でチェックする方法

ルーティング内でhasValidSignature()を使うことでURLが有効かチェックすることができます。

Route::get('user/password_reset', function (\Illuminate\Http\Request $request) {

    if(!$request->hasValidSignature()) {

        return redirect('/'); // 無効の場合はリダイレクト

    }

})->name('user.password_reset');

ミドルウェアを使う方法

ルーティング内でチェックをするとコードが増えてしまい可読性が悪くなる場合がありますので、そんな場合は専用のミドルウェアを使って署名URLが有効か無効かをチェックしましょう。

まず、app/Http/Kernel.phpを開いて$routeMiddlewareValidateSignatureを追加します。(ちなみに私の環境ではすでに登録されていました)

protected $routeMiddleware = [

    // 省略

    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
];

これでsignedが使えるようになりましたので、ルーティングで次のようにするといいでしょう。

Route::get('user/password_reset', 'User\HomeController@password_reset')
    ->name('user.password_reset')
    ->middleware('signed');

この場合、もし無効なURLにアクセスされたら403コードが返されます。

もしリダイレクトしたい場合は以下のように独自のミドルウェアを作成して使うといいでしょう。

<?php

namespace App\Http\Middleware;

use Closure;

class ValidationSignatureRedirect
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->hasValidSignature()) {
            return $next($request);
        }

        return redirect('/');
    }
}

ルーティングのパラメータにに初期値を設定する

例えば、もしログインしているときはURLに以下のようにユーザー名が入ってくるとします。

  • http://example.test/username/xxx.html
  • http://example.test/username/yyy/zzz

この場合、ルーティングは次のようになります。

Route::get('{username}/xxx.html', 'HomeController@xxx')->name('xxx');
Route::get('{username}/yyy/zzz', 'HomeController@yyy_zzz')->name('yyy.zzz');

ではミドルウェアを使ってこのデフォルト値を次のルールで設定しましょう。

  • ログインしている場合 ・・・ ユーザー名
  • ログインしていない場合 ・・・ guest

まず専用のミドルウェアをつくります。

php artisan make:middleware SetDefaultUserName

そして、作成されたapp/Http/Middleware/SetDefaultUserName.phpを開いて中身を以下のように変更します。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\URL;

class SetDefaultUserName
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $username = (auth()) ? auth()->user()->name : 'guest';
        URL::defaults(['username' => $username]);

        return $next($request);
    }
}

そして、このミドルウェアをapp/Http/Kernel.phpへ登録します。

protected $middlewareGroups = [
    'web' => [

        // 省略

        SetDefaultUserName::class,
    ],

    // 省略
];

※ ちなみにドキュメントには “route middleware” と書かれていますが$routeMIddlewareへ登録してもエラーが発生してしまいます。

そして、先ほどのルーティングをグループ化してミドルウェアを適用しましょう。

Route::middleware('default_user_name')->group(function(){

    Route::get('{username}/xxx.html', function(){})->name('xxx');
    Route::get('{username}/yyy/zzz', function(){})->name('yyy.zzz');

});

これで、route()に初期値が設定されました。

echo route('xxx');

これを実行するとパラメータなしでも以下のようになります。

(ログインしていない時)

http://example.test/guest/xxx.html

(ログインしている時)

http://example.test/taro/xxx.html

 

このエントリーをはてなブックマークに追加       follow us in feedly  
開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ