How to get third relation in laravel - php

I have the following models: User, Device, Product.
User
public function devices()
{
return $this->hasMany('App\Device');
}
Device
public function user()
{
return $this->BelongsTo('App\User');
}
public function reading()
{
return $this->hasMany('App\Reading', 'device_id', 'part_id');
}
public function product()
{
return $this->hasOne('App\Product');
}
Product
public function device()
{
return $this->belongsTo('App\Device');
}
The following query pulls my users and all their devices, but inside that collection is not the relation from device to product.
$deviceSingles = User::with('devices')->get();
This query gets me all the products with all devices assigned to it
$deviceSinglesTwo = Product::with('device')->get();
How do I get that third relation, attached to my initial query so i can do this
$deviceSingles->device->product->title

Use nested eager loading.
To eager load nested relationships, you may use "dot" syntax.
User::with('devices.product')->get()

Related

Laravel return model with if statement

I'm trying to create offers and assign them to parent categories, to be more specific i have an Offer model and inside the offer model i have this many to many relationship
public function category() {
return $this->belongsToMany(Category::class);
}
I want the above function to return ONLY the categories which have NULL parent_category which mean they are the parent categories. Is it possible with the above code?
Without knowing the entire scope of your project, I'd suggest one of the following: either change the name of the relation (A) or keep the relation as is and query it when you need it (B).
Option A -
public function childCategory() {
return $this->belongsToMany(Category::class)->whereNull('parent_category');
}
Option B -
public function category() {
return $this->belongsToMany(Category::class);
}
$offer = Offer::with('category')
->whereHas('category' function ($query) {
$query->whereNull('parent_category');
});
public function category() {
return $this->belongsToMany(Category::class)->where('parent_category', null);
}

Laravel Eloquent elation for pivot table

I'm currently working on a laravel project, but I'm kind of stuck finding the right eloquent relations.
My tables and the connections (should) look like this:
Project Relations
My model relations look like this:
User
public function team()
{
return $this->hasMany(Team::class, 'user_id');
}
public function evaluation()
{
return $this->hasMany(Evaluation::class, 'user_id');
}
Team
public function user()
{
return $this->belongsTo(User::class);
}
public function survey()
{
return $this->hasMany(Survey::class, 'team_id');
}
Evaluation
public function user()
{
return $this->belongsTo(User::class);
}
public function survey()
{
return $this->hasMany(Survey::class, 'evaluation_id');
}
Survey
public function team()
{
return $this->belongsTo(Team::class);
}
public function evaluation()
{
return $this->belongsTo(Evaluation::class);
}
public function surveyresponse()
{
return $this->hasMany(SurveyResponse::class, 'survey_id');
}
SurveyResponse
public function survey()
{
return $this->belongsTo(Survey::class);
}
public function testquestion()
{
return $this->belongsTo('App\TestQuestion');
}
Is this the way to go? Do I need a "Has Many Through" relation here? Or a "Polymorphic Relationship"?
Seems correct to me, i just didnt see the TesteQuestion model (your last relation).
Answering your question:
The HasManyThrough relation is just a shortcut for accessing distant relations via an intermediate relation, in your case: Users has many evaluations that has many surveys. With this relationship you could get all surveys from a user.
Your relation would look like this:
/**
* Get all of the surveys for the user.
*/
public function surveys()
{
return $this->hasManyThrough('App\Survey', 'App\Evaluation');
}
You can access this relation like this:
$user->surveys();
But you can achieve the same (without using the HasManyThrough) by doing:
$user->evaluations()->surveys();
Beware that this will return the evaluations too, not just the surveys and it requires more processing.
So i recommend you doing the HasManyThrough relationship if you pretend to access the surveys a lot.

Retrieving eloquent relationship with laravel

When I try to get the name of the Category from my product, I discovered I had to use a 'C' rather than a 'c' before it retrieved results. However when I try to get the Supplier name, the lowercase s works just fine. I was wondering what is causing this difference. Also if I dd($var), is the relations field expected to be empty. I assumed it would have something related to the relationships defined in my models.
Blade.php
<td>{{$product->Category->name}}</td>
<td>{{$product->salePrice}}</td>
<td>{{$product->stock}}</td>
<td>{{$product->supplier->company_name}}</td>
Product.php
public function category()
{
return $this->belongsTo('App\Category','category');
}
public function supplier()
{
return $this->belongsTo('App\Supplier','supplier_id');
}
Category.php
public function product()
{
return $this->hasMany('App\Product');
}
Supplier.php
public function product()
{
return $this->hasMany('App\Product');
}
You're missing a _id on your Product model:
public function category()
{
return $this->belongsTo('App\Category','category_id');
}
Or leave empty
public function category()
{
return $this->belongsTo('App\Category');
}
In your Controller
public function index()
{
$products = Product::all()->with('category');
return view('your_view', compact('products'));
}
If you dd the products
In your View you will se that the relation has been loaded because of the
Eager Loading
When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property. However, Eloquent can "eager load" relationships at the time you query the parent model.
#foreach($products as $product)
<td>{{$product->category->name}}</td>
<td>{{$product->salePrice}}</td>
<td>{{$product->stock}}</td>
<td>{{$product->supplier->company_name}}</td>
#endforeach

Laravel unify multiple relations into one

In my application there are three models: User, Product and Retailer. A user can optionally be associated with one Retailer.
Each Product belongs to one User and optionally one Retailer.
Users should then be able to access all Products that belong to them, as well as all products that belong to the retailer they are associated with (if any).
Basically what this means is that I need to create two relations and somehow unify them.
public function products()
{
// Via column `user_id` in products table
return $this->hasMany('App\Product');
}
// And:
public function products()
{
// Via column `user_id` in products table
return $this->hasManyThrough('App\Product', 'App\Retailer');
}
How am I able to unify these two relations into one?
// User model
public function products()
{
return $this->hasMany('App\Product');
}
public function retailer()
{
return $this->belongsTo('App\Retailer');
}
// Product model
public function user()
{
return $this->belongsTo('App\User');
}
public function retailer()
{
return $this->belongsTo('App\Retailer');
}
// Retailer Model
public function products()
{
return $this->hasMany('App\Product');
}
public function users()
{
return $this->hasMany('App\User');
}
Usage:
// with one user
$user = User::find(1);
$retailerProducts = $user->retailer->products;
foreach( $retailerProducts as $product )
{
echo $product->id;
}
// When getting multiple users, use eager loading to get all products in one query
$users = User::with('retailer.products')->get();
foreach( $users as $user )
{
foreach( $user->retailer->products as $product )
{
echo $product->id;
}
}

Laravel Eloquent for sale-product-customer relationship

So using Laravel 4, I have a Sales table that has a many to many relationship with a Products table, and it also has a one to many relation with a Customers table.
I set up my models as follows:
class Sale extends Eloquent {
...
public function products(){
return $this->belongsToMany('Product');
}
public function customers(){
return $this->belongsTo('Customer');
}
}
class Product extends Eloquent {
...
public function sales(){
return $this->belongsToMany('Sale');
}
}
class Customer extends Eloquent {
...
public function sales(){
return $this->hasMany('Sale');
}
}
What I want to do is return the data of all sales, including the data of each product included in each sale and the data of the customer that bought it.
In my SalesController I'm using eager loading to query my data like this:
public function index()
{
return Sale::with('products', 'customers')->get();
}
It returns an object with the Sale data, the Product data, but the Customer data is null.
How can I achieve this using Eloquent (or a custom query)?
EDIT
This is the object string it returns:
[{"id":1,"customer_id":1,"date":"2013-11-21","status":1,"created_at":"0000-00-00 00:00:00","updated_at":"0000-00-00 00:00:00","products":[{"id":1,"name":"Monitor","price":50,"status":1,"created_at":"0000-00-00 00:00:00","updated_at":"0000-00-00 00:00:00","pivot":{"sale_id":1,"product_id":1,"custom_price":25,"order":1}}],"customers":null}]
Try changing your customers relationship to singular:
class Sale extends Eloquent {
...
public function products(){
return $this->belongsToMany('Product');
}
public function customer(){ // <- here
return $this->belongsTo('Customer');
}
}
(Moved from comments to answer)

Categories