【问题标题】:Laravel 5.5 Resources Customize show($id) methodLaravel 5.5 资源自定义 show($id) 方法
【发布时间】:2018-07-03 16:25:46
【问题描述】:

全部!!

我正在尝试在 Laravel 5.5 中开发一个 API,我真的坚持这一点:

我有这条路线:

Route::get('products', 'ProductController@index'); ==> Works OK
Route::get('product/{id}', 'ProductController@show'); ==> Works OK
Route::get('product/{barcode}', 'ProductController@productByEan'); ==> Fail

使用这些方法:

public function index()
{
  $product = Product::paginate(15);
  return ProductResource::collection($product);
}

public function show($id)
{
  $product = Product::findOrFail($id);
  return new ProductResource($product);
}

以下是相同的逻辑,我使用 id 创建了 show 方法来获取我的产品,它工作正常,但是当我创建一个名为 productByEan 的新方法来使用 EAN13(条形码)而不是使用此方法的 id 获取产品时 (使用带有此 URL 的邮递员:http://ws.barcode.primerbit.com/api/product/9440396613933):

public function productByEan($barcode)
{   
    $response =  Product::where('barcode',$barcode);
    return new ProductResource($response);
}

获取“抱歉,找不到您要查找的页面” 我不知道发生了什么,所以如果有人可以帮助我,我将非常感谢。

提前致谢!!

【问题讨论】:

  • 非常感谢!!我会尽一切努力,看看会发生什么,但我忽略的一个小细节是产品 id 它' pk 但条形码是同一张表上的另一个字段。我可以使用带有非 pk 字段的 show 方法吗?

标签: laravel api routes postman


【解决方案1】:

由于你已经有了product/{id} 路由,product/{barcode} 将永远不会被执行。因此,将其更改为:

product/barcode/{barcode}

或者你可以使用不同的动词,比如 POST 而不是 GET 这条路线:

Route::post('product/{barcode}', 'ProductController@productByEan');

您也可以尝试更改这两条路线的顺序并添加regular expression constraint

Route::get('product/{barcode}', 'ProductController@productByEan')->where('barcode', '[0-9]{13}');    
Route::get('product/{id}', 'ProductController@show');

【讨论】:

    【解决方案2】:

    Route::get('product/{id}', 'ProductController@show'); 路由中匹配您的{id} 没有限制。

    这意味着任何匹配product/* 的东西都将使用ProductController@show 方法。

    您可以通过切换 2 条路线亲自尝试。即

    Route::get('product/{barcode}', 'ProductController@productByEan');
    Route::get('product/{id}', 'ProductController@show');
    

    您将看到所有使用 EAN 的 url 现在都可以使用,但 id 将停止工作。

    为了防止“所有变量匹配此路径”行为,您可以限制 ID 或条形码的范围,因为条形码具有现成的限制,您可以最轻松地使用它。

    尝试切换路线并将条形码路线更改为:

    Route::get('product/{barcode}', 'ProductController@productByEan')->where('barcode', '[0-9]{13}');
    

    这将确保条形码必须匹配一个 13 位长的数字。任何其他数字或字符串都不会匹配,因此会根据 ID 传递到您的其他路由。

    【讨论】:

      【解决方案3】:

      最后我找到了这个问题的解决方案,错误不在规则中,实际上我没有更改任何规则,问题是我在 ProductController 中的 productByEan() 方法,因为该方法引用了 ProductResource ,所以当我尝试创建 ProductResource 的新实例时,雄辩无法获取对象属性并引发以下异常:

      ErrorException (E_NOTICE) 未定义属性:Illuminate\Database\Eloquent\Builder::$id

      其中 $id 是 ProductResource 中的第一个属性:

       public function toArray($request)
      {
         // return parent::toArray($request);
      
         return [
              'id' => $this->id,
              'barcode' => $this->barcode,
              'description' => $this->description,
              'price' => $this->price,
              'currency'=> $this->currency
      
         ];
      
      }`
      

      因此,解决方案是从此更改 ProductByEan 方法:

       public function productByEan($barcode)
      {   
          $response =  Product::where('barcode',$barcode)->get();
      
           return  new ProductResource::collection($response);
      }
      

      到这里:

       public function productByEan($barcode)
      {   
          $response =  Product::where('barcode',$barcode)->get();
      
           return  ProductResource::collection($response);
      }
      

      而且它有效!

      非常感谢您的帮助!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-14
        • 1970-01-01
        • 2016-07-05
        • 2015-05-20
        • 2015-12-03
        • 2014-08-19
        • 2021-10-15
        • 2021-11-09
        相关资源
        最近更新 更多