25

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.

4 Answers 4

50

Yes, you can get the details of the products and skus without making one additional query per product using eager loading ( this is 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 can 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 );
}

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();
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the detailed answer. One more query I am having from your answer is where does all my data validations happen? Is it in the controller or repository and can I treat a repository as a library like in codeigniter?
@user34305 : To validate the data you can do it in different way: in your controller, in your models, or using specific classes, it depends on your needs and preferences: check here to get more info. For the codeigniter part i can't help as i don't use it :)
2

If the repository pattern is used, do it like this.

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

Comments

1

If I understand your question correctly, you can use eager loading.

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

This will give you an array of products that have a skus array in each product object.

Comments

0

You can try this:

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

}

This will give you the exact result in the object form.

1 Comment

Code-only answers are generally frowned upon on this site. Could you please edit your answer to include some comments or explanation of your code? Explanations should answer questions like: What does it do? How does it do it? Where does it go? How does it solve OP's problem? See: How to anwser. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.