Laravel 9 withCount on nested hasManyThrough relationship throws error - php

I'm working in Laravel 9 and need to add a count of my hasManyThrough relationship of tiers.
I have a PingtreeGroup model that defines this relationship through my PingtreeEntry model and works fine without doing a withCount, but when I add a withCount it throws an error.
Here's my code:
$pingtreeGroup = PingtreeGroup::where('company_id', $company_id)
->where('id', $id)
->with('pingtrees.tiers')
->withCount('pingtrees.tiers')
->first();
The error:
Call to undefined method App\Models\PingtreeGroup::pingtrees.tiers()
And the tiers relationship on the PingtreeGroup model:
/**
* Get the pingtrees for the model
*/
public function pingtrees()
{
return $this->hasManyThrough(
Pingtree::class,
PingtreeEntry::class,
'pingtree_group_id',
'id',
'id',
'pingtree_id'
);
}
What am I missing?

Related

Laravel hasManyThrough get the intermediate model on query results

I'm working on a Laravel 9 project. I have a model called PingtreeGroup that I need to get all associated Pingtree models through my PingtreeEntry model.
My query is working as expected and is joining the furthest model which is my Pingtree.
The problem I've encountered is that I also need to join the actual PingtreeEntry model as well to the furthest model, or somehow get the PingtreeEntry model with it.
This is my current PingtreeGroup model relationship:
/**
* Get the pingtrees for the model
*/
public function pingtrees()
{
return $this->hasManyThrough(
Pingtree::class,
PingtreeEntry::class,
'pingtree_group_id',
'id',
'id',
'pingtree_id'
);
}
Then my query:
$pingtreeGroups = PingtreeGroup::where('company_id', $company_id)
->with('pingtrees')
->withCount('pingtrees')
->paginate($request->input('perPage', 10));
How could I achieve this desired result?
I assume PingtreeEntry-Pingtree has one-on-one relationship.
// in Pingtree model add this relationship
public function pingtree_entry()
{
return $this->belongsTo(Pingtree::class);
}
And update your query to call this relationship
$pingtreeGroups = PingtreeGroup::where('company_id', $company_id)
->with('pingtrees', 'pingtrees.pingtree_entry')
->withCount('pingtrees')
->paginate($request->input('perPage', 10));
Now from a single PingtreeGroup, you can get multiple Pingtree.
And inside each of this Pingtree, you can fetch data from PingtreeEntry.
For example lets do get a single PingtreeGroup
$pingtreeGroup = PingtreeGroup::where('company_id', $company_id)
->with('pingtrees', 'pingtrees.pingtree_entry')
->first();
// get the first Pingtree
$pingTree = $pingtreeGroup->pingtrees()->first();
// and inside this Pingtree , you get fetch PingtreeEntry
$pingtreeEntry = $pingTree->pingtree_entry;
Now you can get any kind of data inside this PingtreeEntry.
I hope this can help you out.

Laravel Eloquent belongsto relationship returns null

I have two Eloquent models:
1) Post
class Post extends Model
{
protected $table = 'posts';
protected $fillable = ['id', 'user_id', 'product_id', 'site_id', 'link_id', 'body', 'created_at', 'updated_at'];
public function user(){
return $this->belongsTo(User::class);
}
public function product(){
return $this->belongsTo(Product::class);
}
2) Product
protected $table = 'products';
protected $fillable = ['id', 'user_id', 'manufacturer_id', 'shift_product_id', 'name', 'english_name',
'slug', 'text', 'spec', 'live', 'created_at', 'updated_at'];
public function posts(){
return $this->hasMany(Post::class);
}
I need to get the product from a post
I do that:
$posts = Post::get();
foreach($posts as $key){
dd($key->product);
}
Like this it returns NULL
If I do like this:
dd($key->product());
I get the product but I can't to use that
but I need to get something like that to use whant I need:
Try to point out foregin key and other key in relation, examples:
public function post()
{
return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
}
public function user()
{
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
}
More: https://laravel.com/docs/5.5/eloquent-relationships
i found my problem
i dont have in the DB product with ID = 1
:/
stuped problem
thanks for all the help i leran alot from u.
The relationship probably doesn't exist in the database.
Based on your fillable array on Post, the way you have the relationships setup looks correct as you are following naming conventions for keys and your belongsTo relationship methods have the correct name for convention.
$post->product() is not returning your Product model. It is returning a Relation type object (BelongsTo). This is used for querying the relationship. $post->product would be the dynamic property for the relationship that would return the already loaded relationship or load the relationship and give you the result.
Laravel 5.5 Docs - Eloquent - Relationships - Relationship Methods Vs. Dynamic Properties
If the relationships are setup correctly $post->product being null would mean the relationship doesn't actually exist in the database, no matching id in products for product_id or product_id being null. (assuming no foreign key constraint)
Side note: eager loading the relationship would be a good idea:
$posts = Post::with('product')->get();
I just came across this post because I got a similar error while working on a project.
What I discovered is that when you query a model with the all() method, it ignores the related softdeleted rows.
When you try to access them tho, you get the null
Remember to hit save() after associate and dissociate. Got me a couple of times:
$model->relation()->associate($record)->save();

Laravel 5 – get particular many to many relation based on model and related model ID

I've got Tag and Attendee Eloquent models, they are in many-to-many relation. Pivot table has also two more attributes – value_int and value_string. My Attendee model looks like this:
class Attendee extends Model
{
public $timestamps = false;
protected $fillable = [
'event_id'
];
public function tags() {
return $this->belongsToMany('App\Models\Tag', 'attendee_tag', 'attendee_id', 'tag_id')
->withPivot(['value_string', 'value_int']);
}
public function scoreTagValue($tag_id) {
return $this->tags->where('tag_id', '=', $tag_id)->first();
}
}
What I want is to obtain pivot values based on Attendee model and variable tag_id, so I've written scoreTagValue function, but it always returns null and I don't know why :( I'm calling it this way:
$attendee->scoreTagValue($tag_id). Thanks for your help :)
You need to access the relation, not the property:
public function scoreTagValue($tag_id) {
return $this->tags()->where('tag_id', '=', $tag_id)->first();
}
Also, according to the docs, withPivot() does not take an array, so:
->withPivot('value_string', 'value_int');

Laravel 5.4 relationship

Hi I need to display users items from table name Items.
I have 3 models.
User model:
public function userItem()
{
return $this->hasMany('App\UserItem', 'item_id');
}
UserItem model:
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
What to write to Item Model to make this relationship successful. So I could display items from items table.
If I now do this:
I get info from user_items table from DB.
when I do this #foreach(Auth::user()->userItem as $item) I get this:
Column not found: 1054 Unknown column 'user_items.user_items' in
'where clause'
I think you want to use many to many relation
you have 2 models User and Item
and 3 tables : -users -items -user_items
User Model should be like this:
public function userItem()
{
return $this->belongsToMany('App\Item','user_items','user_id','item_id');
}
and Item Model:
public function user()
{
return $this->belongsToMany('App\User','user_items','item_id','user_id');
}
and you need a table that you named it user_items
and you dont need to define userItem model you can remove relations in this model
in your blade use this code:
#foreach(Auth::user()->userItem as $item)
You are exhibiting a many-to-many relatioship, and yet using methods for one-to-many relationships. For a many to many relationship, use the following code in your models:
//user model:
public function userItem()
{
return $this->hasMany('App\UserItem', 'user_items', 'user_id', 'item_id');
}
//userItem Model:
public function user()
{
return $this->hasMany('App\User', 'user_items', 'item_id', 'user_id');
}
For a many-to-many relationship, you need a hasMany method on both your models.
For information on the parameters to the hasMany method as well as other information on many-to-many relationships, please read the documentation on many-to-many relationships: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
Hope this helps.

Laravel attach() method not working to hasMany side

The application has the models:
Atividade.php
class Atividade extends Eloquent {
public function intervencoes() {
return $this->belongsToMany('Intervencao');
}
}
Intervencao.php
class Intervencao extends Eloquent {
public function atividades() {
return $this->hasMany('Atividade');
}
}
The following code works:
Atividade::find($id)->intervencoes()->attach($intervencao_id);
But, this...
Intervencao::find($id)->atividades()->attach($atividade_id);
Returns an BadMethodCallException:
Call to undefined method Illuminate\Database\Query\Builder::attach()
SOLUTION (thanks to #gnack):
I was trying to set a many-to-many relationship, so just needed to change this...
return $this->hasMany('Atividade');
To this:
return $this->belongsToMany('Atividade');
See the Laravel documentation here:
http://laravel.com/docs/eloquent#inserting-related-models
Basically you have set up two different types of relationships for the same two tables - you've set up a many-to-many and a one-to-many. It looks as though you probably wanted a many-to-many, so you'll need to change this line:
return $this->hasMany('Atividade');
To this:
return $this->belongsToMany('Atividade');
This will set the relationship up as a many-to-many relationship, which will then support the attach() method.
The attach() method is only for many-to-many, for other relationships there's save() or saveMany() and associate() (see the docs linked above).
See the documentation Laravel 5.7
A Comment belongTo an unique Post
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
A Post can Have multiple Comments
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
When you want to update/delete a belongsTo relationship, you may use the associate/dissociate method.
$post= App\Post::find(10);
$comment= App\Comment::find(3);
$comment->post()->associate($post); //update the model
$comment->save(); //you have to call save() method
//delete operation
$comment->post()->dissociate();
$comment->save(); //save() method
attach() is for many-to-many relationships. It seems your relationship is supposed to be a many-to-many but you have not set it up correctly for that.
class Intervencao extends Eloquent {
public function atividades() {
return $this->belongsToMany('Atividade');
}
}
Then the attach() should work
In my case I've two roles() methods that's why it's throwing this error.

Categories