Laravel Eloquent模型如何从关联表中获取数据

24

我正在开发一个 Laravel 应用程序,其中包含以下 Eloquent 模型:

  • Product hasMany('App/Sku','products_id')
  • Sku belongTO('App/Product')

我有一个名为“ProductController”的控制器,在其中可用以下代码:

public function index()
{    
    $products = Product::all();
    foreach($products as $product){
            $products_id = $product->products_id;
    }
}

我正在公开RESTful API,允许我的用户获取所有产品详细信息(包括sku、运输类型等)。

假设我有一个API GET: /products

用于获取所有产品详细信息的代码如下:

public function index()
{              
      $products = Product::all();
      foreach($products as $product){
          $products_id = $product->products_id;
          $skus_data = Product::find($products_id)->skus;
      }
        // Now I have both the product details + skus which I can bundle into an array/json.
}

现在我的问题是,这个逻辑是否合适?在这种情况下,所有的逻辑都在控制器中,因为我使用的是Eloquent模型,我为每个表格都有一个模型,并且关系在其中定义。是否有一种方法可以获取产品/相关模型(表1中的产品细节+表2中的Sku细节)的所有细节,而不是使用以下方法:

foreach($products as $product){
    $products_id = $product->products_id;
    $skus_data = Product::find($products_id)->skus;
}

我对laravel开发和eloquent模型还比较陌生,将会使用存储库模式进行开发,在这种情况下,产品+SKU组合的逻辑应该放在哪里?

请给予帮助。

4个回答

48

使用 预加载,您可以获取产品和sku的详细信息,而无需为每个产品进行额外的查询(这被称为典型的N+1查询问题,其中N是产品数量)。

假设您的ProductSku模型之间的关系如下:

产品

public function skus()
{
    return hasMany('App/Sku','products_id');
}

要获取产品数据和sku数据,可以使用with方法。 在您的控制器中:

控制器

 $products = Product::with('skus')->get();

然后,在你的视图中,你可以通过以下方式获取信息:

视图

foreach ($products as $product) 
{
     //$product->skus is a collection of Sku models
     dd( $product->skus );
}

对于仓库问题:如果你想使用一个仓库,你可以把你的代码中的"Eloquent"访问部分放到仓库里。因此,例如,你可以在仓库内拥有这个方法:

ProductRepository

public function getProductsData() 
{
    //access eloquent from the repository
    return Product::with('skus')->get();    
} 

那么您可以在控制器中使用您的代码库:

控制器

//inject the repository in the controller
public function __construct( ProductRepository $productRepo )
{
    $this->productRepo = $productRepo;
}

//use the injected repository to get the data
public function index()
{
    $products = this->productRepo->getProductsData();
}

感谢您详细的回答。我还有一个问题,就是我的所有数据验证都在哪里进行?它是在控制器或存储库中进行的,我可以像在CodeIgniter中一样将存储库视为库吗? - Ajeesh
@user34305:验证数据可以通过不同的方式进行:在您的控制器中,在您的模型中,或使用特定的类,这取决于您的需求和偏好:请查看此处以获取更多信息。对于CodeIgniter部分,我无法提供帮助,因为我不使用它 :) - Moppo

2

如果使用存储库模式,请按照以下方式操作。

public function index() {
    $data = $this->passportRepository->with('user')->findWhere(['id'=>1]);
}

1

如果我理解你的问题正确,你可以使用预加载技术。

 public function index()
 {
    $products = Product::with('skus')->get();
 }

这将给你一个产品数组,每个产品对象都有一个skus数组。

0

你可以尝试这个:

public function index()
{
    $products = Product::all();
    foreach($products->skus as $product)
    {
         return $product;
    }

}

这将以对象形式给出确切的结果。


1
在这个网站上,仅提供代码的答案通常不被看好。您能否编辑您的答案,包括一些注释或解释您的代码?解释应该回答以下问题:它是做什么的?它是如何做到的?它去哪里?它是如何解决 OP 的问题的?请参阅:如何回答。谢谢! - Eduardo Baitello

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接