LoginSignup
5
5

More than 5 years have passed since last update.

laravel5のリクエストURLに変数を用いる方法

Last updated at Posted at 2016-07-21

やりたいこと

  • サブナビを実装したい
  • Viewの中にincludeフォルダを作って、共通パーツとして読み込ませる
  • 一覧,新規登録,詳細,編集,削除のリンクをつける
  • 一覧,新規登録画面では一覧,新規登録だけをリンクに表示
  • 詳細,編集,削除画面では上記に加え詳細,編集,削除のリンクを表示
  • 自分自身のURLにアクセスした際にはactiveクラスをつける。
  • 例えば新規登録にアクセスしたらサブナビの新規登録の部分にactiveクラスがつく。
  • 後はそれをCSSで装飾するなりなんなり。Bootstrapならactiveクラスをつけたら色がつくはず。

インクルード方法

ドキュメント見たらわかる話だけど念のため説明

View 「subnavi.blade.php」
パスは views/admin/items/include/subnavi.blade.php とする。
別にディレクトリ名は inc でも includes でもいいけど私はこれにしてます。

<ul>
    <li><a href="#">リンク名</a></li>
    <li><a href="#">リンク名</a></li>
</ul>

View 「index.blade.php」
パスは views/admin/items/index.blade.php とする

<html>
<head></head>
<body>
    <ul>
        <li><a href="#">リンク名</a></li>
        <li><a href="#">リンク名</a></li>
    </ul>
</body>
</html>

↓

<html>
<head></head>
<body>
@include('admin.items.include.subnavi')
</body>
</html>

あとはcreate.blade.phpとかshow.blade.phpとかそういうのにも同じように@includeの記述を書く

失敗例

View 「subnavi.blade.php」

<ul>
    <li class="{{ Request::is('admin/items') ? 'active' : '' }}">
        <a href="/admin/items">一覧</a>
    </li>
    <li class="{{ Request::is('admin/items/create') ? 'active' : '' }}">
        <a href="/admin/items/create">新規登録</a>
    </li>
    @if(!empty($item -> id))
    <li class="{{ Request::is('admin/items/{{$item -> id}}') ? 'active' : '' }}">
        <a href="/admin/items/{{$item -> id}}">詳細</a>
    </li>
    <li class="{{ Request::is('admin/items/{{$item -> id}}/edit') ? 'active' : '' }}">
        <a href="/admin/items/{{$item -> id}}/edit">編集</a>
    </li>
    <li class="{{ Request::is('admin/items/{{$item -> id}}/delete') ? 'active' : '' }}">
        <a href="/admin/items/{{$item -> id}}/delete">削除</a>
    </li>
    @endif
</ul>

上のコードは動作しない。原因はこれ。

{{ Request::is('admin/items/{{$item -> id}}') ? 'active' : '' }} // これが動かない


{{ Request::is('admin/items/{!!$item -> id!!}') ? 'active' : '' }} // これも動かない

{{ Request::is('admin/items/$item -> id') ? 'active' : '' }} // これも動かない

<?php $id = $item -> id ?>
{{ Request::is('admin/items/$id') ? 'active' : '' }} // 変数に代入しても動かない

// これは動くが、これだとワイルドカードなので期待動作にはならない。編集画面なのに詳細と編集の両方にactiveクラスがつくみたいなのが起きる。
{{ Request::is('admin/items/*') ? 'active' : '' }}

// これは /admin/items/create にアクセスした時に動く。念のため。
{{ Request::is('admin/items/create') ? 'active' : '' }}

何とかして変数を使いたい。。変数というか、数値が可変する部分を表現できたらいいなって

実装

次のようにする。

View 「subnavi.blade.php」

<?php
if( ! function_exists('is_route'))
{
    /**
     * Alias for Request::is(route(...))
     *
     * @return mixed
     */
    function is_route()
    {
        $args = func_get_args();
        foreach($args as &$arg)
        {
            if(is_array($arg))
            {
                $route = array_shift($arg);
                $arg = ltrim(route($route, $arg, false), '/');
                continue;
            }
            $arg = ltrim(route($arg, [], false), '/');
        }
        return call_user_func_array(array(app('request'), 'is'), $args);
    }
}
?>

<ul>
    <li class="{{ is_route(['admin.items.index']) ? 'active' : '' }}">
        <a href="/admin/items">一覧</a>
    </li>
    <li class="{{ is_route(['admin.items.create']) ? 'active' : '' }}">
        <a href="/admin/items/create">新規登録</a>
    </li>
    @if(!empty($item -> id))
    <li class="{{ is_route(['admin.items.show', $item -> id]) ? 'active' : '' }}">
        <a href="/admin/items/{{ $item -> id }}">詳細</a>
    </li>
    <li class="{{ is_route(['admin.items.edit', $item -> id]) ? 'active' : '' }}">
        <a href="/admin/items/{{ $item -> id }}/edit">編集</a>
    </li>
    <li class="{{ is_route(['admin.items.delete', $item -> id]) ? 'active' : '' }}">
        <a href="/admin/items/{{ $item -> id }}/delete">削除</a>
    </li>
    @endif
</ul>

UIKitへの対応について

私の環境はBootstrapじゃなくてUIKitなのでそちらでの記述方法も説明。おとなしくBootstrap使ってくれればいいものを。。

View 「subnavi.blade.php」

<?php
if( ! function_exists('is_route'))
{
    /**
     * Alias for Request::is(route(...))
     *
     * @return mixed
     */
    function is_route()
    {
        $args = func_get_args();
        foreach($args as &$arg)
        {
            if(is_array($arg))
            {
                $route = array_shift($arg);
                $arg = ltrim(route($route, $arg, false), '/');
                continue;
            }
            $arg = ltrim(route($arg, [], false), '/');
        }
        return call_user_func_array(array(app('request'), 'is'), $args);
    }
}
?>

<div class="uk-margin uk-grid">
    <div class="uk-width-medium-1-1">
        <div>
            <ul class="uk-tab">
                <li class="{{ is_route(['admin.items.index']) ? 'uk-active' : '' }}">
                    <a href="/admin/items">一覧</a>
                </li>
                <li class="{{ is_route(['admin.items.create']) ? 'uk-active' : '' }}">
                    <a href="/admin/items/create">新規登録</a>
                </li>
                @if(!empty($item -> id))
                <li class="{{ is_route(['admin.items.show', $item -> id]) ? 'uk-active' : '' }}">
                    <a href="/admin/items/{{ $item -> id }}">詳細</a>
                </li>
                <li class="{{ is_route(['admin.items.edit', $item -> id]) ? 'uk-active' : '' }}">
                    <a href="/admin/items/{{ $item -> id }}/edit">編集</a>
                </li>
                <li class="{{ is_route(['admin.items.delete', $item -> id]) ? 'uk-active' : '' }}">
                    <a href="/admin/items/{{ $item -> id }}/delete">削除</a>
                </li>
                @endif
            </ul>
        </div>
    </div>
</div>

エラーが起きるんですけど

Route [admin.items.delete] not defined. とか出る場合。

ルーティング時にNameをつけ忘れていることが原因。
以下のコードで調べる

php artisan route:list
+--------+-----------+--------------------------+---------------------+----------------------------------------------------+------------+
| Domain | Method    | URI                      | Name                | Action                                             | Middleware |
+--------+-----------+--------------------------+---------------------+----------------------------------------------------+------------+
|        | POST      | admin/items              | admin.items.store   | App\Http\Controllers\Admin\ItemsController@store   | web        |
|        | GET|HEAD  | admin/items              | admin.items.index   | App\Http\Controllers\Admin\ItemsController@index   | web        |
|        | GET|HEAD  | admin/items/create       | admin.items.create  | App\Http\Controllers\Admin\ItemsController@create  | web        |
|        | GET|HEAD  | admin/items/{id}/delete  |                     | App\Http\Controllers\Admin\ItemsController@delete  | web        |
|        | DELETE    | admin/items/{id}/delete  |                     | App\Http\Controllers\Admin\ItemsController@destroy | web        |
|        | DELETE    | admin/items/{items}      | admin.items.destroy | App\Http\Controllers\Admin\ItemsController@destroy | web        |
|        | GET|HEAD  | admin/items/{items}      | admin.items.show    | App\Http\Controllers\Admin\ItemsController@show    | web        |
|        | PUT|PATCH | admin/items/{items}      | admin.items.update  | App\Http\Controllers\Admin\ItemsController@update  | web        |
|        | GET|HEAD  | admin/items/{items}/edit | admin.items.edit    | App\Http\Controllers\Admin\ItemsController@edit    | web        |
+--------+-----------+--------------------------+---------------------+----------------------------------------------------+------------+

deleteのネームルーティングができてなかった

app/routes.php

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/admin/items', function () {
    return view('.admin.items.index');
});

Route::resource('/admin/items', 'Admin\\ItemsController');

Route::get('/admin/items/{id}/delete','Admin\\ItemsController@delete');
Route::delete('/admin/items/{id}/delete','Admin\\ItemsController@destroy');

次のように修正

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/admin/items', function () {
    return view('.admin.items.index');
});

Route::resource('/admin/items', 'Admin\\ItemsController');

Route::get('/admin/items/{id}/delete','Admin\\ItemsController@delete')->name('admin.items.delete');
Route::delete('/admin/items/{id}/delete','Admin\\ItemsController@destroy')->name('admin.items.destroy');

これで動くはず。動かなかったら知らない。ごめん。

改善

nunulk 様から頂いた非常にナイスな書き方を受けて改善。
そうだね、「 . 」で追加すりゃよかったね…危うく読解不能な謎コードを錬成するところでした。危ない危ない。

Bootstrapの場合
<?php ~ ?> の記述は全て削除してください
View 「subnavi.blade.php」

<ul>
    <li class="{{ Request::is('admin/items') ? 'active' : '' }}">
        <a href="/admin/items">一覧</a>
    </li>
    <li class="{{ Request::is('admin/items/create') ? 'active' : '' }}">
        <a href="/admin/items/create">新規登録</a>
    </li>
    @if(!empty($item -> id))
    <li class="{{ isset($item->id) && Request::is('admin/items/' . $item->id) ? 'active' : '' }}">
        <a href="/admin/items/{{ $item -> id }}">詳細</a>
    </li>
    <li class="{{ isset($item->id) && Request::is('admin/items/' . $item->id . '/edit') ? 'active' : '' }}">
        <a href="/admin/items/{{ $item -> id }}/edit">編集</a>
    </li>
    <li class="{{ isset($item->id) && Request::is('admin/items/' . $item->id . '/delete') ? 'active' : '' }}">
        <a href="/admin/items/{{ $item -> id }}/delete">削除</a>
    </li>
    @endif
</ul>

UIKitの場合
<?php ~ ?> の記述は全て削除してください
View 「subnavi.blade.php」


<div class="uk-margin uk-grid">
    <div class="uk-width-medium-1-1">
        <div>
            <ul class="uk-tab">
                <li class="{{ Request::is('admin/items') ? 'uk-active' : '' }}">
                    <a href="/admin/items">一覧</a>
                </li>
                <li class="{{ Request::is('admin/items/create') ? 'uk-active' : '' }}">
                    <a href="/admin/items/create">新規登録</a>
                </li>
                @if(!empty($item -> id))
                <li class="{{ isset($item->id) && Request::is('admin/items/' . $item->id) ? 'uk-active' : '' }}">
                    <a href="/admin/items/{{ $item -> id }}">詳細</a>
                </li>
                <li class="{{ isset($item->id) && Request::is('admin/items/' . $item->id . '/edit') ? 'uk-active' : '' }}">
                    <a href="/admin/items/{{ $item -> id }}/edit">編集</a>
                </li>
                <li class="{{ isset($item->id) && Request::is('admin/items/' . $item->id . '/delete') ? 'uk-active' : '' }}">
                    <a href="/admin/items/{{ $item -> id }}/delete">削除</a>
                </li>
                @endif
            </ul>
        </div>
    </div>
</div>
5
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5