Laravel - 类别导航路由错误
Laravel - category navigation routing errors
目前,我正在编写一个基于Laravel的电子商务应用程序。我项目的主要导航结构如下:
- 主页 (/)
- 类别 1(例如 /cars)
- 类别 2(例如 /cars/volkswagen)
- 类别 3(例如 /cars/volkswagen/高尔夫)
模型名称为'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);
}
});
目前,我正在编写一个基于Laravel的电子商务应用程序。我项目的主要导航结构如下:
- 主页 (/)
- 类别 1(例如 /cars)
- 类别 2(例如 /cars/volkswagen)
- 类别 3(例如 /cars/volkswagen/高尔夫)
模型名称为'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);
}
});