Reputation: 2599
Is it possible to append an attribute to my model whenever a model scope is called?
For example in my controller I want to call a scope to append those dynamic attribute like :
$Media_query = OutDoorMedia::query();
$Media_query->orderby('created_at', 'desc');
$Media_query->PreviouslyOrdered();
$Media = $Media_query->get();
And in my model I want to do something like :
class OutDoorMedia extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'id',
'user_id',
'address',
'location',
'media_type',
];
}
class scopePreviouslyOrdered extends OutDoorMedia
{
public $appends = ['previously_ordered'];
public function getPreviouslyOrderedAttribute()
{
if ($this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id')->Where(function ($query) {
$query->where('status', MEDIA_ORDER_CHECKOUT_STATUS)
->orWhere('status', STATUS_TO_PAY);
})->exists()) {
return true;
} else {
return false;
}
}
}
But it's not working and I know it's wrong, How to achieve this?
Upvotes: 5
Views: 25473
Reputation: 1213
Just in case you need to include in your response,
$data = FarmerQuestion::where([])->get();
$data->append(
[
'user_text',
'user_photo',
'district_text',
'answers_count'
]
);
Upvotes: 0
Reputation: 40683
I think there's a misunderstanding on how scopes should work. A scope is basically like a shortcut query for a model. You are using it to test existance of a relationship but there's a better way to do that using whereHas
Here's how you would achieve this using a relationship:
class OutDoorMedia extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'id',
'user_id',
'address',
'location',
'media_type',
];
public function previousOrders() {
return $this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id');
}
public function getPreviouslyOrderedAttribute() {
return $this->previousOrders()->exists();
}
}
Then you simply do:
$Media_query = OutDoorMedia::whereHas('previousOrders')
->orderby('created_at', 'desc');
If you what the dynamic attribute appended on the model automatically you can just add the following to the model:
public $appends = [ 'previously_ordered' ];
I guess if you want the best from both worlds you can do:
class OutdoorMediaWithPreviouslyOrdered extends OutDoorMedia {
public $appends = [ 'previously_ordered' ];
}
Then when you need the appending model you can use :
$Media_query = OutdoorMediaWithPreviouslyOrdered ::orderby('created_at', 'desc');
Upvotes: 4
Reputation: 2599
I solved this problem with help of @apokryfos but with a bit tweak. hope this reduce wasting others time.
Instead of appending attributes on the model I have appended the said attribute to my model by the eloquent magic method :
$Media_query = OutDoorMedia::query();
$Media_query->orderby('created_at', 'desc');
$Media = $Media_query->get()->each(function ($items) {
$items->append('previously_ordered');//add this attribute to all records which has the condition
});
In Model As apokryfos said I have put these two methods:
public function PreviousOrders() {
return $this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id');
}
public function getPreviouslyOrderedAttribute() {
return $this->PreviousOrders()->exists();
}
But I don't need this method and I had to remove it from the model because if it exist in model it will automatically append to model:
public $appends = [ 'previously_ordered' ];
Upvotes: 6