2017-08-31 96 views
0

目前,我正在编写基于Laravel的电子商务应用程序。我的项目的主导航结构如下:Laravel - 类别导航路由错误

  • 首页(/)
  • 类别1(例如/汽车)
  • 类别2(例如/汽车/大众)
  • 3类(如/汽车/大众/高尔夫)

该模型的名称是'类别'和控制器是'类别控制器'。型号表产生与迁移

<?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}', '[email protected]'); 

Route::get('/{category1}/{category2}', '[email protected]'); 

Route::get('/{category1}/{category2}/{category3}', '[email protected]'); 

这是我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/volksw这样的页面agen/golf可以打开。问题是如果我在浏览器中请求本地主机/高尔夫,服务器会将页面发送给我。该页面不是我想要的。这个页面只能通过localhost/cars/volkswagen/golf。

你有一些建议如何解决这个问题?

编辑1:我仍然想要页/ category1 /和/ category1/category2 /交付。本页面显示可用产品的概览。

+0

您是否验证其功能,它实际上正在经历?尝试'Log :: info(__ FUNCTION __);'作为每个函数的第一行,然后在浏览到该页面后检查日志。 – aynber

+0

@aynber它正在通过所有的功能: [2017-09-01 05:50:24] local.INFO:category1 [2017-09-01 05:50:30] local.INFO:category2 [ 2017-09-01 05:50:35] local.INFO:category3 – glembo

回答

0

我自己找到了解决方案。为了避免不同类别可以输入到URL的“错误”部分,我必须在RouteServiceProvider的引导方法中定义我自己的解析逻辑。这被称为Route Model Binding

这是代码insinde的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(); 
        } 
      } 

     }); 
    } 

想像这样本地主机/汽车/大众/高尔夫的最终到达网址。在数据库中,汽车被定义为类别1(id = 1,parent_id = 0),大众汽车被定义为类别2(id = 2,parent_id = 1)并且高尔夫被定义为类别3(id = 3,parent_id = 2 )。

EDIT1:

作为URL图案为localhost /类别1 /类别2 /类别3我只能进入汽车作为1相同的类别的值是有效的大众作为第2类和高尔夫球作为第3类如果我试图进入其中之一:

  • 本地主机/大众或
  • 本地主机/高尔夫或
  • 本地主机/汽车/高尔夫

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

0

正如已创建三个不同的路线:

Route::get('/{category1}', '[email protected]'); 

Route::get('/{category1}/{category2}', '[email protected]'); 

Route::get('/{category1}/{category2}/{category3}', '[email protected]'); 

每当你传递一个参数时,其匹配的路线即将被执行。首先一个,同样如果传递两个参数发生。

如果你愿意,这条路由只能用三个参数工作,删除前两条路由并且只保留那条有3个路由参数的路由。

+0

我仍然想要页面/ category1 /和/ category1/category2 /交付,所以我需要它们吗?本页面显示可用产品的概览。 – glembo

0

解决问题“问题是如果我在我的浏览器中请求本地主机/高尔夫球,服务器会为我提供页面。”写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); 
    } 

});