Условно добавить атрибут к модели в laravel

Можно ли добавить атрибут к моей модели при вызове области видимости модели?

Например, в моем контроллере я хочу вызвать область, чтобы добавить этот динамический атрибут, например:

$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;
    }
}

}

Но это не работает, и я знаю, что это неправильно, как этого добиться?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
0
9 522
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, что есть недопонимание того, как должны работать осциллографы. Область действия в основном похожа на быстрый запрос для модели. Вы используете его, чтобы проверить наличие отношений, но есть способ сделать это лучше, используя 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');

Спасибо, да, думаю, я запуталась. но все же есть проблема, я хочу вернуть все записи, и те, которые связаны с заказами, имеют параметр ранее_ordered = true, а те, у которых нет никакого порядка, то ранее_ordered = false, и я не хочу быть глобальным, я хочу прикрепить его к моему запросу в некоторых контроллерах. вот почему я думал, что прицел решит мою проблему

Mohammad_Hosseini 18.11.2018 09:53

Прямо сейчас с вашим подходом запрос возвращает только те, у которых есть заказы.

Mohammad_Hosseini 18.11.2018 09:57

Если вы не включите whereHas, вы получите все, а затем, если вы добавите код атрибута, вы должны получить логическое значение previously_ordered в модели.

apokryfos 18.11.2018 10:02

проблема в том, как добавить код атрибута в запрос! я должен написать другой метод для этого в модели?

Mohammad_Hosseini 18.11.2018 10:04

Что ты имеешь в виду? Если атрибут находится в свойстве $appends, вам не нужно ничего делать, чтобы добавить его в модель. Он будет добавлен автоматически.

apokryfos 18.11.2018 10:05

мы вернулись на первое место, вот в чем проблема, мне нужно добавить этот атрибут только в этот контроллер, а не во все контроллеры, которые используют указанную выше модель. вот почему я попросил прицелы.

Mohammad_Hosseini 18.11.2018 10:20

Если вы не добавляете его в $appends и просто получаете к нему доступ, когда он вам нужен, например $model->previously_ordered, он должен просто работать, однако он не будет автоматически добавлен в ответы JSON.

apokryfos 18.11.2018 10:25

вы хотите поместить: $ model-> ранее_ordered в мой запрос контроллера? если да, то как правильно назначить его каждой записи? Я не хочу использовать для этого foreach.

Mohammad_Hosseini 18.11.2018 11:34

Что ты делаешь с записями? Вы можете использовать ->previously_ordered на каждой модели, когда вам нужно, и он будет работать. Однако нет возможности массово назначить его, если вам нужно, например, отправить все модели как JSON (согласно это), поэтому я думаю, что ответ - нет серебряной пули. Или используйте $appends, чтобы делать это везде, или, если вам просто нужно в определенном JSON, просто добавьте его в цикл. Как я отметил в обновлении, расширение класса должно быть вариантом, как указано выше.

apokryfos 18.11.2018 18:19

Я очень ценю вашу помощь, и это хорошее решение, но это не то, что я искал, есть проблема с вашим решением, которое является основным запросом, который у меня выше в вопросе, может быть не таким простым и имеет некоторые условия, и я не хочу использовать цикл foreach для добавления этого атрибута, я хотел добавить атрибут условно и там, где мне нужно. Конечно, цикл foreach выполняет свою работу или расширяет класс, но я думаю, что это будет немного накладными расходами по сравнению с тем, что я хотел сделать. вы можете увидеть мой ответ и понять, что я имел в виду.

Mohammad_Hosseini 19.11.2018 06:15

Я решил эту проблему с помощью @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' ];

Другие вопросы по теме