Search code examples
phpormlaraveleloquent

How do I get all of the results from a hasMany() relationship in Laravel?


For example, I have a Product, and I have a BaseProduct.

In the model for the Product, I've specified the following:

//In class Product
public function BaseProduct()
{
    return $this->belongsTo("BaseProduct", "BaseProductId");
}

In the BaseProduct, I've specified the following relationship:

//In class BaseProduct
public function Products()
{
    return $this->hasMany("Product", "ProductId");
}

If I were to select a product, like so:

$Product::first()

I could get the BaseProduct by doing the following:

$Product::first()->BaseProduct()->get();

Instead of getting the array of the result from that, how would I get the Model of the BaseProduct, so I can get all of the children of BaseProduct, meaning all Products that have a foreign key relating to this BaseProduct.

I've tried BaseProduct()->all(); instead, but it isn't a valid method.


Edit:

I've created the following chain of function calls - but it's awful.

return BaseProduct::find(Product::first()->BaseProduct()->getResults()['BaseProductId'])->Products()->getResults();

Final edit:

I had made a mistake in my BaseProduct model. In the Products() function, I had specified return $this->hasMany("Product", "ProductId"); where ProductId should have been BaseProductId.

After I fixed that, I could successfully use:

Product::first()->BaseProduct->products;

As Sheikh Heera had explained.


Solution

  • To get the children of the BaseProduct you may try this:

    $bp = BaseProduct::with('Products')->get();
    

    Now, you have a collection of BaseProduct so, you may use something like this:

    $bp->first()->products
    

    Or get the second item from collection

    $bp->get(1)->products
    

    Also, you may run a loop like this (most probably in the view after pass it):

    // From the controller
    $bp = BaseProduct::with('Products')->get();
    return View::make('view_name')->with('baseProduct', $bp);
    

    In the View

    @foreach($baseProduct->products as $product)
        {{ $product->field_name }}
    @endforeach
    

    Update: Yes, you may try this

    $product = Product::first();
    $baseProduct = $product->BaseProduct;
    
    // Dump all children/products of this BaseProduct
    dd($baseProduct->products->toArray());
    

    You may chain like:

    Product::first()->BaseProduct->products;
    

    Update: Your table structure should look something like:

    Table:baseproduct:

    id(pk) | some_field | another_field
    

    Table:products:

    id(pk) | baseproduct_id(fk) | another_field
    

    According to this table structure, relationship should be

    // BaseProduct
    public function Products()
    {
        return $this->hasMany("Product");
    }
    
    // Product
    public function Products()
    {
        // second parameter/baseproduct_id is optional unless
        // you have used something else than baseproduct_id
        return $this->belongsTo("BaseProduct", "baseproduct_id");
    }