複数のワイルドカードルートを作成する方法.


場合によっては、アプリケーションのWebサイト上で同じルートワイルドカードパスで複数の種類のリソースが利用できることを確認してもよい.
たとえば、ブログ記事のスラッグルートURLでブログ記事にアクセスしたい場合もあります.また、ルートURLでの/プライバシーポリシーのようなカスタムページも見つけたいかもしれません.

ルートモデルバインディング


Laravelでは、最もダイナミックなリソースルーティング要件のために働くルートモデル結合と呼ばれる素晴らしい機能があります.それらを利用するには、ルート設定ファイルでルートを定義し、モデルルートで定義されたモデルに暗黙的または明示的にそのルートをバインドします.

ルート定義


Laravelは、ルート定義で使用する変数名を自動的に使用して、適切なモデルを見つけるか、またはControlメソッドパラメーターに直接期待しているリソースの種類を設定できます.
ブログのスラッグURLの例については、ルートファイルのルートを定義し、ルートファぅ襪路上のstatic function get ()でルートを定義します.
次に、リクエストを処理するためにルートが使用するコールバック関数またはコントローラを書きます.
//In routes/web.php
<?php
use App\Http\Controllers\BlogController;

Route::get('/{blog}', [BlogController::class, 'show'])->name('pages.show');
上の例では、カーリーの場所にあるブログのワイルドカードルートパラメータを追加し、show ()メソッドを使用してブログコントローラのリクエストを処理するようにアプリケーションに指示します.
💡 このルートを簡単なリファレンスの名前として指定することもできます.これは、この例でname ()メソッドが行うことです.

モデルコントローラ


ブログコントローラがどのように見えるかを知っているので、ここに例をあげました.
//in App/Http/Controllers/BlogController.php
<?php

namespace App\Http\Controllers;

use App\Models\Blog;
use Illuminate\Http\Request;

class BlogController extends Controller
{
    /**
     * Display a blog article
     *
     * @return \Illuminate\Http\Response
     */
    public function show(Blog $blog)
    {
        return view('blogs.show', compact('blog'));
    }
}
ほとんどの場合、あなたのルートが論理リソースディレクトリに入れ子になっていることを望みます.そして、それは我々のニーズのために、我々は多分ブログ/ブログスラグのURLである私たちの例のブログルートを定義するでしょう.
/blog/blog-url //This goes to a blog page
/blog //This goes to an index view of all recent blogs.
/services/service-url //This goes to a service page
/services // This goes to a list of services
あなたはアイデアを得る.
ほとんどのWebアプリケーションでは、これはまさに実装して期待する動作の型です.

同じルートパスを持つルート


しかし、いくつかのケースでは、同じルートディレクトリに複数の種類のリソースを置く必要があるかもしれません.私が開始した例のように、あなたは、アプリケーション内の同じ論理的な場所ですべてのブログやカスタムページを配置することができます.
これは物事がトリッキーになるところです.

パスに要求された要求:最初のルートが定義されます


問題は、我々のアプリは、カーリーブレースの間に入れたものについてのすべてを気にしないです.ルートが一致する場合、それは自動的に何が後に関係なく、あなたのアプリケーションで最初のワイルドカードルートに要求を提供します.
これは自動的に問題を引き起こします.我々は/ブログスラグの最初のためのルートを定義した場合、アプリは、ブログと同じコントローラに/に行った要求を送信します!
つまり、これらのケースではラービアモデルのルートバインディングを使用できません.

スイッチコントローラを使う


ブログのためのブログコントローラ、またはカスタムページのページコントローラのいずれかに要求が正しく送信されるようにするには、仲介コントローラを作成する必要があります.このコントローラは、我々のアプリのためのスイッチとしてどのコントローラは、それが提供されている要求のために最も適切であることを伝えるように動作します.

コントローラへのルートを定義する


そこで、両方のブログとページの2つのルートを定義する代わりに、両方のリソースが一致する要求を処理するために使用する1つのルートを定義する必要があります.
以下のようになります.
// In routes/web.php
<?php
use App\Http\Controllers\ResolvePathController; //You can name this controller whatever makes sense to you.

Route::get('/{blogOrPageSlug}', [ResolvePathController::class, 'show'])->name('pages.show');As you can see, the curly brace variable changed. The name of that variable really doesnt matter. Ive named it blogOrPageSlug because that is a name that makes sense to me.
また、私は私たちのルートファイル内のブログコントローラまたはページコントローラのいずれかを使用していないが、私たちのアプリのスイッチとして機能する新しいコントローラを使用してアプリケーションを伝えることに気づくことができます.
💡 同じディレクトリパスを使用している他の静的ルートの後にこのルートを定義するようにしてください!

コントローラの作成


それから、私たちは、その新しいコントローラを作成して、スラグを受け入れて、パラメタとして要求を要求して、我々の要求を指示するコントローラを見るためにスラグを使用します.
私たちのケースでは、スラッグのいずれかのブログやページを私たちのデータベースに格納参照します.
それは私たちを大いに助けなければならないので、私たちは、それらの1つの中のマッチングスラグを探す必要があることを知っています.
最初のリソースを見つけることができなければ、スラッグは他のモデルを参照するか、存在しないことを知っています.
//In App/Http/Controllers/ResolvePathController.php
<?php

namespace App\Http\Controllers;

use App\Models\Blog;
use App\Models\Page;
use Illuminate\Http\Request;

class ResolvePathController extends Controller
{
    public function show(Request $request, string $pageOrBlogSlug)
    {
        $page = Page::whereSlug($pageOrBlogSlug)->first();
        if ($page) {
            return PageController::show($page);
        }

        $blog = Blog::whereSlug($pageOrBlogSlug)->firstOrFail();
        return BlogController::show($request, $blog);
    }
}

心から探す


この例のアプリケーションでは、まずページを検索します.私は最終的に我々のアプリがブログ記事より少ないカスタムページを持つと推測しています.
私たちは、他の前にリソースの1つを検索する必要がありますので、私たちが最初に最小のデータセットを検索するのは、私にとって意味があります.それはあなたが決めることです.

最初のモデルリソースを見つけられなければ失敗を返さないでください


ページモデルのコレクションにfirst ()メソッドを使用するだけです.ページが存在しない場合はブログをチェックすることができるかどうかチェックしたい.

最後の検索では、リソースが見つからない場合は404を返します。


しかし、ブログを探す第2の呼び出しでは、要求されたスラッグでブログ記事が存在しない場合、404ページを返したいので、firstorfail ()を使用しています.2つ以上のモデルを持っている必要がある場合は、直接ユーザーを希望している場合は、その呼び出しをfirst ()メソッドを作成したいと思いますが、最後のモデルを検索すると、見つからないリソースの404を返します.

モデルコントローラを静的に呼び出す


あなたが気づくかもしれないもう一つは、コントローラのメソッドを静的に呼び出しを返すことです.これは、コントローラのメソッドを適切に呼び出すために必要な非常に重要な変更です.これらのコントローラは静的メソッドを使用してこのメソッドを呼び出すことができます.
この例ではPageController :
<?php

namespace App\Http\Controllers;

use App\Models\Page;
use Illuminate\Http\Request;

class PageController extends Controller
{
    /**
     * Display a page
     * This has to be static, because we call this from the resolve path controller.
     *
     * @param Page $page
     * @return \Illuminate\View\View
     */
    public static function show(Page $page)
    {
        return view('pages.show', \compact('page'));
    }
}
このメソッドは、Showメソッドを使用するようにアプリケーションを指示するときにコントローラクラスをインスタンス化していないため、他のコントローラメソッドとは異なります.これをするより良い方法があるかもしれませんが、私はこれが良い方法であると感じました.
同様に、あなたのブログコントローラのshowメソッドを更新してください.

考慮するカップル


スラグの一意性の検証


一つのことは、バリデーションです.
ユーザーがブログ記事と同じスラグを持つページを作成するとどうなりますか?さて、彼らがそのスラグを使うならば、誰もブログ記事に向けられません.
スラグが同じことがないことを確実にするために両方のモデルスラグのバリデーションを含めないならば、あなたは若干の主要な痛いバグに走らせます.されていない場合は、記事のページにあなたを取る必要があります代わりに、同じpickyカスタムページに移動し続ける記事のリンクをクリックすることがあります.

データベースのインデックススラグ列


もう一つのことは、サイトの速度です.あなたは確実に検索時間を確保するためにあなたのデータベースのテーブルにあなたのスラグの列をインデックスにすることができます.私はこのタイプのリソースをできるだけ構造化するのを避けましょう.

Conclusion


これは私が長い間考えていたものであり、感謝して信じられないほどの上級エンジニアアレックスTopalがアイデアをバウンスした.数分以内に彼はこの解決策を持っていました.
私はうまくいけばあなたがうまくいけば、これを行う方法について考えてあまりにも多くの時間を費やす必要はありませんので、すぐにこれを要求する機能に実行する次の時間に行くことができるように書いている.
あなたのパートナーが必要ですかLaravel Application development ? うちの会社をチェックしなさい.Magnet Co . 我々は、デザイナーやエンジニアの世界クラスのチームであり、我々はあなたのソフトウェアのニーズであなたと提携することを楽しみにしています.
もともと投稿this article on my website .