Laravel 5 Eloquent Realtionship has one through - laravel

I have the following database structure
products quesionnaires questionnaire_results
-------- -------------- ----------------------
id id id
questionnaire_id questionnaire_id
product_id
A Questionnaire can be used for multiple products, and store results for each product, apart, in questionnaire_results table.
A product can have only one questionnaire and only one result of its questionnaire.
I need a way to get from Product Model the result of its Questionnaire.

If you do not have a QuestionnaireResult model then there is no straightforward Eloquent relationship for this, as all of the default relationships rely on the existence of an Eloquent model. However, there is a fairly clean way to accomplish this by treating it as a Many to Many relationship between Product and Questionnaire and treating questionnaire_results as your pivot table (even thought you really know that a product will only ever belong to one Questionnaire).
Product Model:
public function questionnaire() {
return $this->belongsToMany('App\Questionnaire', 'questionnaire_results');
}
Questionnaire Model:
public function products() {
return $this->belongsToMany('App\Product', 'questionnaire_results');
}
As this relation will return a collection, you need to either access the first array with [0] or use the first() method.
$product->questionnaire()->first();
However, if you do have a QuestionnaireResult model then you have a very straightforward One to One relationship with no need to go through another model. You have some questionnaire results that belong to a product, while a product can only have one set of questionnaire results (according to your post info).
Product Model:
public function questionnaireResult() {
return $this->hasOne('App\QuestionnaireResult');
}
Questionnaire Result Model:
public function product() {
return $this->belongsTo('App\Product');
}

// Product Model
public function quesionnaire() {
return $this->hasOne("App\Quesionnaire");
}
// Quesionnaire Model
public function questionnaire_result() {
return $this->hasOne("App\Questionnaire_result");
}
$product->quesionnaire->questionnaire_result

Related

How to get data from three models that are related to each other in Laravel 5.8

So I have this model Order which has one to many relation with ProductOrder model. And also Product model which has the same one to many relation with ProductOrder model. I can get the PorductOrder data with Product or with Order. Like this:
Order::with('product_orders')->get();
Now this is returning my orders with the associated ProductOrder data. How can I include the Products of each ProductOrder data in this collection?
Make changes of function name, field name, model name as per you requirements
Step 1:
In you ProductOrder Model use this function:
public function products()
{
return $this->hasOne('App\Product', 'id', 'product_id');
}
Step 2:
After this in you query you can use as:
Order::with('product_orders.products')->get();
It sounds like ProductOrder is just a joining table/model, is that right? If that is the case, you should change to a ManyToMany relationship to of the Products model to
public function orders()
{
return $this->belongsToMany('App\Orders', 'product_order');
}
and the Orders to
public function products()
{
return $this->belongsToMany('App\Products', 'product_order');
}
Then you can access like
Order::find(1)->products()->get();

Laravel getting data from a deep relationship

I have 3 tables:
Users
Baskets
Items
id
id
id
user_id
basket_id
price
I'm trying setup a relationship in eloquent by which I can get all the all the Items and the corresponding Baskets where the price of items is X. I want it so that I can simply use $user->items(x) and get the results.
I'm unsure if this can be done using Relationships alone or will I have to resort to writing custom queries.
Any, and all, help and guidance will be appreciated!
The relationship you are looking for is hasManyThrough
https://laravel.com/docs/7.x/eloquent-relationships#has-many-through
User Modal
public function items()
{
return $this->hasManyThrough(Item::class, Bucket::class);
}
The way you want to use is not possible to achieve I think.
Possible Usage
$user->items()->where('price', x);
of if you define custom scopes
Item Modal
public function scopeWherePrice($query, $value)
{
return $query->where('price', $value);
}
Usage
$user->items()->wherePrice(x);
EDIT
If you really want to write a code like $user->items(x) you can define a method on the User Modal.
Note that this is not a relationship, just another method which fetch the result.
User Modal
public function items($price)
{
return this->items()->where('price', $price)->get();
}
Using hasManyThrough Define the relationship in your models:
User Model
/**
* Get all of the items & baskets for the user.
*/
public function items($price)
{
return $this->hasManyThrough('App\Items', 'App\Baskets')
->with('basket')
->where('price',$price);
}
Basket Model
/**
* Get the Items's Basket.
*/
public function basket()
{
return $this->belongsTo('App\Basket','basket_id');
}
And then call it like this:
$user->items(x);
This will return all user items with their corresponding baskets in a specific price.

Laravel eloquent not calling the relationship (returning string)

I have this relationship:
A store may have many products and each products can have many effects
stores and products -> many to many relationship
products and effects -> one to many (one product can have multiple effects)
Here are my relationships:
Store model
public function products()
{
return $this->belongsToMany('App\Models\Product');
}
Product model
public function stores()
{
return $this->belongsToMany('App\Models\Store');
}
public function effects()
{
return $this->hasMany('App\Models\Effect');
}
Effect model
public function products()
{
return $this->belongsTo('App\Models\Product');
}
Now, I can access the relationship with products ok, but when I access the effects relationships:
$store = Store::where('slug', 'cantina')->first();
dd($store->products->first()->effects);
The dd returns a string with the name of the relationship:
"effects"
I never seen this "error" before, anyone knows why the relationship are returning a string instead of the eloquent?
[Edit]
If I digit anything in the relationship call, they output what I digited:
dd($store->products->first()->effects);
//Output:
"effects"
Another example:
dd($store->products->first()->foobar);
//Output:
"foobar"

How to model these relashionships?

Well, these are two simple entities but with many interactions which makes me a bit confused about how to do the relationship setup ..
So, I have two entities .. Category and Article .. It seems simple.. but here are what I need to do:
Categories can be a standalone model with no relationships
Category can contain other categories
Categories can contain Articles
Articles can be standalone (not inside categories)
How do you think I can model these entities and relationships between them?
Most straightforward:
// categories table: category_id fk categories.id nullable
// Category model
public function parent()
{
return $this->belongsTo('Category', 'category_id');
}
public function children()
{
return $this->hasMany('Category', 'category_id');
}
public function articles()
{
return $this->hasMany('Article');
}
// articles table: category_id fk categories.id nullable
// Article model
public function category()
{
return $this->belongsTo('Category');
}
Mind that if you wish to build a tree of those categories and then load whole tree, this will not be easy. If that's the case you should use eg. adjacency list or other model for self-referencing tables.

Laravel - Pivot table for three models - how to insert related models?

I have three models with Many to Many relationships: User, Activity, Product.
The tables look like id, name. And in the each model there are functions, for example, in User model:
public function activities()
{
return $this->belongsToMany('Activity');
}
public function products()
{
return $this->belongsToMany('Product');
}
The pivot table User_activity_product is:
id, user_id, activity_id, product_id. The goal is to get data like: User->activity->products.
Is it possible to organize such relations in this way? And how to update this pivot table?
First I suggest you rename the pivot table to activity_product_user so it complies with Eloquent naming convention what makes the life easier (and my example will use that name).
You need to define the relations like this:
// User model
public function activities()
{
return $this->belongsToMany('Activity', 'activity_product_user');
}
public function products()
{
return $this->belongsToMany('Product', 'activity_product_user');
}
Then you can fetch related models:
$user->activities; // collection of Activity models
$user->activities->find($id); // Activity model fetched from the collection
$user->activities()->find($id); // Activity model fetched from the db
$user->activities->find($id)->products; // collection of Product models related to given Activity
// but not necessarily related in any way to the User
$user->activities->find($id)->products()->wherePivot('user_id', $user->id)->get();
// collection of Product models related to both Activity and User
You can simplify working with such relation by setting up custom Pivot model, helper relation for the last line etc.
For attaching the easiest way should be passing the 3rd key as a parameter like this:
$user->activities()->attach($activityIdOrModel, ['product_id' => $productId]);
So it requires some additional code to make it perfect, but it's feasible.
The solution was found with some changes.
In the models relationships look like:
// User model
public function activities()
{
return $this->belongsToMany('Activity', 'user_activity_product', 'user_id', 'activity_id')->withPivot('product_id');
}
public function products()
{
return $this->belongsToMany('Product', 'user_activity_product', 'user_id', 'product_id')->withPivot('activity_id');
}
To update pivot table:
$user->products()->save($product, array('activity_id' => $activity->id));
- where product and activity ids I get from Input.
And, for example, to check if "user -> some activity -> some product is already exists":
if ($company->activities->find($activity_id)->products()->where('product_id', '=', $product_id)->wherePivot('company_id', $company_id)->get()->count() > 0) {
// code...
}
I think it needs improvements but it works for me now.

Resources