Ajeesh Ajeesh - 2 days ago 5
PHP Question

Laravel eloquent model how to get data from relationship's table

I am developing a laravel application which has the following eloquent models


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

  • Sku belongTO('App/Product')



I have a controller 'ProductController' where the following code is available

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


I am exposing RESTfull API which will allow my users to get all product details (including skus, shipping types etc..).

Suppose if I have an API GET : /products

The code which fetches all the product details will be some what the following

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.
}


Now my question is , is this logic proper? In this case all the logics are in the controller since im using eloquent models I have a model for each table and the relationships are defined in it. Is there a way I can get all the details of a product/associated model (Products details (in table 1)+ Sku details (in table 2)) rather than using the below

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


I am pretty new to laravel development and eloquent models. I will be using repository pattern for the development and in that case where does the aboe logic (Product+Sku combining) resides.

Please help out.

Answer

Yes, you can get the details of the products and skus without making one additional query per product using eager loading ( this referred as the typical N+1 query problem where N is the number of the products )

Suppose the relation between your Product and Sku models model is:

Product

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

To fetch the products data along with the sku data you should use the with method. In your controller:

Controller

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

Then, in your views, you can get the info this way:

View

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

Now, for the repository question: if you want to use a repository you can place the eloquent-access part of your code inside the repository. So, for example you could have this method inside the repository:

ProductRepository

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

then you can use your repository in your controller:

Controller

//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();
}
Comments