I have a model that I want to sort based on a relationship property.
First model "DeviceType":
public function make()
{
return $this->hasMany(DeviceMake::class);
}
Second model: "DeviceMake":
public function type()
{
return $this->hasOne(DeviceType::class, 'id', 'device_type_id');
}
public function model()
{
return $this->hasMany(DeviceModel::class);
}
Controller:
$type = DeviceType::with(['make'])->where('id', '=', $device_type_id)->first();
Table name is device_makes and I want to sort it by name. How can I do this?
And what about?
$type = DeviceType::with(['make' => function ($query) {
$query->orderBy('name', 'asc');
}])->where('id', '=', $device_type_id)->first();
Please note that first() will only return the first model that matches your query whereas get() will return all of them.
Maybe you could try this instead in your Model:
public function make() {
return $this->hasMany(DeviceMake::class)->orderBy('name', 'asc');
}
Related
I have Post eloquent related with PostCategory and my collection is good.
class Post extends Model
{
public function post_categories()
{
return $this->belongsTo(PostCategory::class, 'category_id');
}
public function detail($slug_category, $slug)
{
$detail = Post::with('post_categories')
->whereHas('post_categories', function ($query) use ($slug_category){
$query->where('category_slug', $slug_category);
})->where('slug', $slug)
->first();
return($detail);
}
}
I have this another class 'Players' where i need to have a collection with all user's posts with PostCategory category relation.
class Players extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
public function detail($slug_category, $slug_name)
{
$detail = Player::with('posts')
->whereHas('players_info', function ($query) use ($slug_name){
$query->where('slug', $slug_name);
})
->whereHas('player_categories', function ($query) use ($slug_category){
$query->where('category_slug', $slug_category);
})->first();
return($detail);
}
}
I read something about "belongsToMany" and "withPivot", but I'm still confused for correct way.
What can I do to resolve this?
thanks!
I solved just with this.
return $this->hasMany(Post::class)->with('post_categories');
Hello I have the following relationship setup:
Product class:
public function attributes()
{
return $this->hasMany(ProductAttribute::class);
}
ProductAttribute class:
public function attribute()
{
return $this->belongsTo(Attribute::class);
}
public function values()
{
return $this->hasMany(ProductAttributeValue::class, 'product_attribute_id');
}
ProductAttributeValue class:
public function attributeValue()
{
return $this->belongsTo(AttributeValue::class, 'attribute_value_id');
}
How to check if Product has values with ids 5 and 15?
I am trying to make a query like this:
Product::whereHas('values', function($q) use ($product_values_ids) {
$q->whereIn('attribute_value_id', $product_values_ids);
})->get();
however it is not working. I cannot access directly $product->values.
Any suggestions on how to access directly the values of attributes from the Product?
Update:
I have just managed to make it work with a many to many trough relationship:
Product class:
public function values()
{
return $this->hasManyThrough(ProductAttributeValue::class, ProductAttribute::class);
}
is there a way to get only the results that have all the ids listed in the $product_values_ids array?
You have to add new relation to Product model:
public function values(): HasManyThrough
{
return $this->hasManyThrough(ProductAttributeValue::class, ProductAttribute::class);
}
and then:
$builder = Product::query();
foreach($product_values_ids as $id) {
$builder->whereHas('values', function($q) use ($id) {
$q->where('id', $id);
});
}
$product = $builder->get();
I have two models in a many-to-many relationship: Fixture and Event.
Fixture:
public function events()
{
return $this->belongsToMany(Event::class, 'fixture_events')->withPivot('player_id');
}
Event:
public function fixtures()
{
return $this->belongsToMany(Fixture::class, 'fixture_events')->withPivot('player_id');
}
You will notice that the pivot table has an additional field player_id. This is because FixtureEvent also had a relationship to a model called Player.
FixtureEvent:
public function fixture()
{
return $this->hasOne(Fixture::class, 'id', 'fixture_id');
}
public function event()
{
return $this->hasOne(Event::class, 'id', 'event_id');
}
public function player()
{
return $this->belongsTo(Player::class, 'id', 'player_id');
}
And Player has:
public function events()
{
return $this->hasMany(FixtureEvent::class);
}
My problem arises when I want to get all the fixture_events for a player and sort them by a field in the events table. This field is named sequence.
However, whatever I do, the events always come out ordered by ID.
This is the query that I would like to order by events.sequence, whether by using some type of join or whatever works (this is inside the Player model so $this is a player object):
$events = $this->events()->whereHas('fixture', function ($query) use ($round, $competition_id) {
$query->where('fixtures.round', '=', $round)->where('competition_id', $competition_id);
})->get();
I've tried adding a join query here on fixture_events.event_id = events.id and then ordering by events.sequence but this doesn't work.
I've also tried adding orderBy directly in the model relationship, i.e. in the Fixture model:
public function events()
{
return $this->belongsToMany(Event::class, 'fixture_events')->orderBy('sequence')->withPivot('player_id');
}
But this does nothing for my problem.
How do I make this happen?
Update
At first I misread the relations, can you try with the below query?
$events = $this->events()->whereHas('fixture', function ($query) use ($round, $competition_id) {
$query->where('fixtures.round', '=', $round)->where('competition_id', $competition_id);
})->with(['events.event' => function ($query) {
$query->orderBy('sequence');
}])->get();
You have a couple of alternatives, but first I suggest you to edit your relationship to include the sequence field you are trying to load.
Then proceed with one of the following:
Order by on the relationship definition, but I think you have to load that field from the pivot table, otherwise you won't have its value, and prefix the relations table on the orderby field.
public function events() {
return $this->belongsToMany(Event::class, 'fixture_events')
->withPivot(['player_id', 'sequence'])
->orderBy('fixture_events.sequence');
}
or with:
public function events() {
return $this->belongsToMany(Event::class, 'fixture_events')
->withPivot(['player_id', 'sequence'])
->orderBy('pivot_sequence');
}
Order by a pivot field outside the relation can be done like this:
$events = $this->events()->whereHas('fixture', function ($query) use ($round, $competition_id) {
$query->where('fixtures.round', '=', $round)->where('competition_id', $competition_id);
})->with(['fixture' => function ($query) {
$query->orderBy('sequence');
}])->get();
or with:
$events = $this->events()->whereHas('fixture', function ($query) use ($round, $competition_id) {
$query->where('fixtures.round', '=', $round)->where('competition_id', $competition_id);
})
->orderBy('pivot_sequence')
->get();
Let me know if any of these methods works!
When I am adding a new post in my app there is a 7 tables to affect when I add single post. To fetch all posts with all post data my simple query look like:
$userPost = Post::with(['product','postattribute.attribute.category','user.userDetails'])
->offset($offset)
->limit($limit)
->whereStatus("Active")
->whereIn('product_id', $userApprovalProductIDs)
->orderBy('id','desc')
->get();
So it is retrun all data which I want. Now I want to implement search query within all tables, currently I am able to search only posts table.
If I am doing search on category table with categoryTitle I am trying to code like
where('category.title','=', $serachTitle)
But it is not working in my case.
POST model relationship :
public function user() {
return $this->belongsTo(User::class);
}
public function product() {
return $this->belongsTo(Product::class);
}
public function postattribute() {
return $this->hasMany(PostAttribute::class);
}
POSTATTRIBUTES model relationship :
public function post() {
return $this->belongsTo(Post::class);
}
public function attribute() {
return $this->belongsTo(Attribute::class);
}
ATTRIBUTES model relationship :
public function category() {
return $this->belongsTo(Category::class);
}
public function attributes() {
return $this->belongsTo(Attribute::class);
}
How can I do this ?
To apply filter on your nested relations you could use whereHas
$userPost = Post::with(['product','postattribute.attribute.category','user.userDetails'])
->offset($offset)
->limit($limit)
->whereStatus("Active")
->whereIn('product_id', $userApprovalProductIDs)
->whereHas('postattribute.attribute.category', function ($query) use($serachTitle) {
$query->where('title', '=', $searchTitle);
})
->orderBy('id','desc')
->get();
Querying Relationship Existence
From comments what i understood is you want to know how to search within each relation for a post , I already added an example to search with category title
->whereHas('postattribute.attribute', function ($query) use($var) {
$query->where('some_field_of_attribute_table', '=', $var);
})
->whereHas('postattribute', function ($query) use($var) {
$query->where('some_field_of_postattribute_table', '=', $var);
})
On query get the error with undefine method. Simply i want to get data from two tables query look linke
public static function userDetail($id){
$result = User::whereHas('user_details', function ($query) {
$query->where('user_details.user_id',$id);
})->first();
return $result ;
}
Relationship
On Model User define relationship
public function userDetails()
{
return $this->hasOne(UserDetails::class);
}
and in userDetails model
public function user()
{
return $this->belongsTo(User::class);
}
just change
public static function userDetail($id){
$result = User::whereHas('user_details', function ($query) use($id) {
$query->where('user_id',$id);
})->first();
return $result ;
}
If you dont need to use static, you can use this $result value on userDetails
public function userDetail($id){
$result = userDetails::where('user_id', '=', $id)->first();
return $result ;
}
Then the result can get access to the user from the vale by using $value->user->{user property}