Можно ли добавить атрибут к моей модели при вызове области видимости модели?
Например, в моем контроллере я хочу вызвать область, чтобы добавить этот динамический атрибут, например:
$Media_query = OutDoorMedia::query();
$Media_query->orderby('created_at', 'desc');
$Media_query->PreviouslyOrdered();
$Media = $Media_query->get();
И в своей модели я хочу сделать что-то вроде:
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;
}
}
}
Но это не работает, и я знаю, что это неправильно, как этого добиться?






Я думаю, что есть недопонимание того, как должны работать осциллографы. Область действия в основном похожа на быстрый запрос для модели. Вы используете его, чтобы проверить наличие отношений, но есть способ сделать это лучше, используя whereHas.
Вот как этого добиться с помощью отношений:
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();
}
}
Затем вы просто делаете:
$Media_query = OutDoorMedia::whereHas('previousOrders')
->orderby('created_at', 'desc');
Если вы автоматически добавили динамический атрибут к модели, вы можете просто добавить в модель следующее:
public $appends = [ 'previously_ordered' ];
Думаю, если вы хотите получить лучшее из обоих миров, вы можете:
class OutdoorMediaWithPreviouslyOrdered extends OutDoorMedia {
public $appends = [ 'previously_ordered' ];
}
Затем, когда вам понадобится добавляемая модель, вы можете использовать:
$Media_query = OutdoorMediaWithPreviouslyOrdered ::orderby('created_at', 'desc');
Прямо сейчас с вашим подходом запрос возвращает только те, у которых есть заказы.
Если вы не включите whereHas, вы получите все, а затем, если вы добавите код атрибута, вы должны получить логическое значение previously_ordered в модели.
проблема в том, как добавить код атрибута в запрос! я должен написать другой метод для этого в модели?
Что ты имеешь в виду? Если атрибут находится в свойстве $appends, вам не нужно ничего делать, чтобы добавить его в модель. Он будет добавлен автоматически.
мы вернулись на первое место, вот в чем проблема, мне нужно добавить этот атрибут только в этот контроллер, а не во все контроллеры, которые используют указанную выше модель. вот почему я попросил прицелы.
Если вы не добавляете его в $appends и просто получаете к нему доступ, когда он вам нужен, например $model->previously_ordered, он должен просто работать, однако он не будет автоматически добавлен в ответы JSON.
вы хотите поместить: $ model-> ранее_ordered в мой запрос контроллера? если да, то как правильно назначить его каждой записи? Я не хочу использовать для этого foreach.
Что ты делаешь с записями? Вы можете использовать ->previously_ordered на каждой модели, когда вам нужно, и он будет работать. Однако нет возможности массово назначить его, если вам нужно, например, отправить все модели как JSON (согласно это), поэтому я думаю, что ответ - нет серебряной пули. Или используйте $appends, чтобы делать это везде, или, если вам просто нужно в определенном JSON, просто добавьте его в цикл. Как я отметил в обновлении, расширение класса должно быть вариантом, как указано выше.
Я очень ценю вашу помощь, и это хорошее решение, но это не то, что я искал, есть проблема с вашим решением, которое является основным запросом, который у меня выше в вопросе, может быть не таким простым и имеет некоторые условия, и я не хочу использовать цикл foreach для добавления этого атрибута, я хотел добавить атрибут условно и там, где мне нужно. Конечно, цикл foreach выполняет свою работу или расширяет класс, но я думаю, что это будет немного накладными расходами по сравнению с тем, что я хотел сделать. вы можете увидеть мой ответ и понять, что я имел в виду.
Я решил эту проблему с помощью @apokryfos, но с небольшой настройкой. надеюсь, что это уменьшит трату времени других.
Вместо добавления атрибутов к модели я добавил указанный атрибут к моей модели красноречивым магическим методом:
$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
});
В модели, как сказал апокрифос, я использовал эти два метода:
public function PreviousOrders() {
return $this->hasMany('App\Models\OutDoorMediaOrders', 'odm_id', 'id');
}
public function getPreviouslyOrderedAttribute() {
return $this->PreviousOrders()->exists();
}
Но мне этот метод не нужен, и мне пришлось удалить его из модели, потому что, если он существует в модели, он автоматически добавится в модель:
public $appends = [ 'previously_ordered' ];
Спасибо, да, думаю, я запуталась. но все же есть проблема, я хочу вернуть все записи, и те, которые связаны с заказами, имеют параметр ранее_ordered = true, а те, у которых нет никакого порядка, то ранее_ordered = false, и я не хочу быть глобальным, я хочу прикрепить его к моему запросу в некоторых контроллерах. вот почему я думал, что прицел решит мою проблему