Laravel - 类别导航路由错误

Laravel - category navigation routing errors

目前,我正在编写一个基于Laravel的电子商务应用程序。我项目的主要导航结构如下:

模型名称为'Category',控制器名称为'CategoryController'。模型 table 是通过 migration:

生成的
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->integer('parent_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

为此,我在 web.php 中创建了以下 路线:

Route::get('/{category1}', 'CategoryController@category1');

Route::get('/{category1}/{category2}', 'CategoryController@category2');

Route::get('/{category1}/{category2}/{category3}', 'CategoryController@category3');

这是我的 CategoryController:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Category as CategoryModel;

class CategoryController extends Controller
{
    public function category1(CategoryModel $category1)
    {
        // Do some stuff
    }

    public function category2(CategoryModel $category1, CategoryModel $category2)
    {
        // Do some stuff
    }

    public function category3(CategoryModel $category1, CategoryModel $category2, CategoryModel $category3)
    {
        // Do some stuff
    }
}

终于可以打开localhost/cars/volkswagen/golf这样的页面了。问题是,如果我在浏览器中请求 localhost/golf,服务器会将页面发送给我。该页面不是我想要的。此页面只能通过 localhost/cars/volkswagen/golf.

你有什么解决这个问题的建议吗?

Edit1:我仍然希望发送页面 /category1/ 和 /category1/category2/。此页面显示可用产品的概述。

由于您创建了三个不同的路线:

Route::get('/{category1}', 'CategoryController@category1');

Route::get('/{category1}/{category2}', 'CategoryController@category2');

Route::get('/{category1}/{category2}/{category3}', 'CategoryController@category3');

每当你传递一个参数时,它的匹配路由即第一个将被执行,如果你传递两个参数也会发生同样的情况。

如果您愿意,此路由将仅使用三个参数,删除前两个路由并仅保留其中具有 3 个路由参数的路由。

我自己找到了解决办法。为避免将不同的类别输入到 URL 的 "wrong" 部分,我必须在 RouteServiceProvider 的引导方法中定义自己的解析逻辑。这叫做Route Model Binding

这是适用于我的项目的 RouteServiceProvider 中的代码:

public function boot()
    {
        parent::boot();

        Route::bind('cytegory1', function ($value) {
            return Category::where('name', $value)->where('parent_id', 0)->first();
        });

        Route::bind('category2', function ($value) {

            $category2 = Category::where('name', $value)->first();

            // Check if level 2

            if($category2->parent_id == 0) {
                // 1st level -> 404 error
                abort(404);
            } else {
                // level 2 or 3

                // get parent object 
                $parent_id= $category2->parent_id;
                $parent = Category::where('id', $parent_id)->first();
                    if($parent->parent_id == 0){
                        // level 2
                        return Category::where('name', $value)->first();
                    } else {
                        // level 3
                        abort(404);
                        return false;
                    }
            }

        });

        Route::bind('category3', function ($value) {

            $category3= Category::where('name', $value)->first();

            // check if level 1

            if($category3->parent_id == 0) {
                // 1st level -> 404 Fehler
                abort(404);
            } else {
                // level 2 or 3

                // get parent object
                $parent_id= $category3->parent_id;
                $parent = Category::where('id', $parent_id)->first();
                    if($parent->parent_id == 0){
                        // level 2
                        abort(404);
                        return false;
                    } else {
                        // level 3
                        return Category::where('name', $value)->first();
                    }
            }

        });
    }

想象一下最后的 url 就像 localhost/cars/volkswagen/golf。在数据库中,汽车被定义为类别 1 (id = 1, parent_id = 0),大众汽车被定义为类别 2 (id = 2, parent_id = 1),高尔夫被定义为类别 3 (id = 3, parent_id = 2).

编辑1:

由于 url 模式是 localhost/category1/category2/category3 我只能输入汽车作为类别 1 的值。这同样适用于大众汽车作为类别 2 和高尔夫作为类别 3。如果我尝试输入其中一项:

  • localhost/volkswagen 或
  • localhost/golf 或
  • localhost/cars/golf

应用程序正在响应 404 错误。这是预期的行为。 请给我您的意见,以便进一步改进。

解决问题"The problem is if I request localhost/golf in my browser the server delivers me the page."这样写类别1的路由,因为对于类别1,parent_id为0,我们可以编写验证以通过此路由:

Route::get('category/{category1}', function(App\Category $category1)
{
    if ($category1->parent_id==0)
    {
        return (new App\Http\Controllers\CategoryController)->category1($category1);
    }

});