How can I write this without a join for a scope in a Laravel model as the 'id' field becomes ambiguous
/**
* Return events that social category name
*/
public function scopeWithSocialEvents($query)
{
return $query->join('categories', 'events.event_type_id', '=', 'categories.id')
->where('categories.name', 'social');
}
Use this:
public function eventType()
{
return $this->belongsTo(Category::class);
}
public function scopeWithSocialEvents($query)
{
return $query->whereHas('eventType', function($query) {
$query->where('name', 'social');
});
}
Related
I have StudentEducation model and in this model i got
public function student_education_countries()
{
return $this->hasMany(StudentEducationCountry::class, 'education_id');
}
and
public function student_education_education_types()
{
return $this->hasMany(StudentEducationEducationType::class, 'education_id');
}
in StudentEducationCountry model i got
public function student_education()
{
return $this->belongsTo(StudentEducation::class, 'education_id');
}
public function student_country()
{
return $this->belongsTo(StudentCountry::class, 'country_id');
}
and in StudentEducationEducationType model i got
public function student_education()
{
return $this->belongsTo(StudentEducation::class, 'education_id');
}
public function student_educationcategory()
{
return $this->belongsTo(StudentEducationcategory::class, 'educationcategory_id');
}
The question is how should i join for to take all educations where country_id is 2 and type is secondary
Simple with whereHas()
$educations = StudentEducation::query()->whereHas('student_education_countries', function (Builder $query) {
$query->where('id', 2);
})->whereHas('student_education_education_types', function (Builder $query) {
//maybe here you need another columns
$query->where('type', 'secondary');
})->get();
I have two models. Task and TaskCheck
in TaskCheck i have
class TaskCheck extends Model
{
public function task(): BelongsTo
{
return $this->belongsTo(Task::class);
}
public function owner(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function scopeOwnedBy(Builder $query, int $userId): Builder
{
return $query->where('user_id', '=', $userId);
}
}
in Task model i have
class Task extends Model
{
public function taskCheck(): HasMany
{
return $this->hasMany(TaskCheck::class)->with(['taskState', 'owner']);
}
}
And would like to use something like this:
public function scopeHasOwner(Builder $query, int $taskOwnerId): Builder
{
return $query->whereHas('taskCheck', function ($q) use ($taskOwnerId) {
$q->hasOwner($taskOwnerId);
});
}
however this throws exception Call to undefined method App\Models\Task::hasOwner() as it seems inner query is not aware of Task model.
I know I could use this instead and it works
public function scopeHasOwner(Builder $query, int $taskOwnerId): Builder
{
return $query->whereHas('taskCheck', function ($q) use ($taskOwnerId) {
$q->where('user_id', '=', $taskOwnerId);
});
}
but i would rather not repeat the where clause in every related model, because there are more related models deeper in relationships which would use similar functionality and i would like to have it on one place only.
In your TaskCheck model, you have ownedBy() scope, but you called hasOwner() in the whereHas query.
Change your query to ownedBy()
$query->whereHas('taskCheck', function ($q) use ($taskOwnerId) {
$q->ownedBY($taskOwnerId);
});
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 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');
}
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);
})