How to model these relashionships? - laravel

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.

Related

Laravel Eloquent Relationship by Models

I have a table called "categories" and there is a 3 table needed the id of categories
the 3 tables needed a categories id is "activies", "stories", "news" i really want to know how to fix this issue the stories and news table is running well im using php tinker to see if the relationship is running and the table activities it give me a null value, inside the activities table i`d input same category_id in the table of activities it gives always a null value given in php tinker
Models
Category.php
public function stories()
{
return $this->hasMany(Story::class);
}
public function news()
{
return $this->hasMany(Newy::class);
}
public function activites()
{
return $this->hasMany(Activity::class);
}
Activity.php
public function category()
{
return $this->belongsToMany(Category::class, 'category_id');
}
If you are using hasMany in your Category Model, the opposite relationship in your Activity model should be belongsTo() and not belongsToMany()
public function category()
{
return $this->belongsTo(Category::class);
}
You can read more in the documentation here

Laravel | Using Eloquent hasManyThrough

I have a table called invoiceDetails that has item_id as foreign key from another table called items which has category_id as foreign key from table called categories.
I want to do that following using eloquent:
$result = InvoiceDetail::groupBy('item_id')
->selectRaw('sum(qty) as qty, item_id')->with('item', 'category')->get();
but I am getting error:
Call to undefined relationship [category] on model [App\InvoiceDetail].
Here's my relation inside Category model:
public function invoiceDetail() {
return $this->hasManyThrough('App\InvoiceDetail', 'App\Item', 'category_id', 'item_id');
}
Any suggestions?
Not sure you would even need a hasManyThrough relation here, unless you want to fetch all InvoiceDatail objects belonging to all items which in turn belong to the Category. That part is not clear from your question.
But in your example you are fetching items with their category from distinct item_id.
The reason this is not working is because you are trying to fetch the category relation from the InvoiceDetail object, which does not exist.
->with('item', 'category')
You want to load the Category based on the item relation, not based on the InvoiceDetail, try the dot notation (given that you did define the other relations)
->with('item.category')
Relations should be like this:
class InvoiceDetail extends Model
{
public function item()
{
return $this->belongsTo(\App\Item::class);
}
}
class Item extends Model
{
public function invoiceDetails()
{
return $this->hasMany(\App\InvoiceDetail::class);
}
public function category()
{
return $this->belongsTo(\App\Category::class);
}
}
class Category extends Model
{
public function items()
{
return $this->hasMany(\App\Item::class);
}
public function invoiceDetails()
{
return $this->hasManyThrough(\App\InvoiceDetail::class, \App\Item::class, 'category_id', 'item_id');
}
}
You would want to use the hasManyThrough if, for example, you have a Category and you want to load all the InvoiceDetails directly.
dd($category->invoiceDetails);

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"

Laravel 5 Eloquent Realtionship has one through

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

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