Красноречивый: запрос с использованием несуществующего столбца

Я пробую следующее: у меня есть две модели (Pub и Schedule), связанные отношениями 1xN следующим образом:

Паб:

/**
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function pubSchedules()
{
    return $this->hasMany(Schedule::class);
}

Расписание:

/**
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function pub()
{
    return $this->belongsTo(Pub::class);
}

Таблица расписаний имеет следующие поля:

id | pub_id | week_day | открытие_время | закрытие_время |

Я использую следующую функцию, чтобы узнать, открыт ли один паб в настоящее время (или нет):

/**
 * @return bool
 */
public function isPubCurrentlyOpen()
{
    $schedules = Schedule::where([
            ['pub_id', $this->id ],
            ['week_day', Carbon::now()->dayOfWeek],
    ])->get();

    foreach ($schedules as $schedule){
        $isOpen[] =
            Carbon::now('Europe/Madrid')->between(
                Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->opening_time),
                Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->closing_time)
            );
    }

    if (in_array(true, $isOpen)){
        return true;
        //return "Pub Opened";
    }

    return false;
    //return "Pub Closed";
}

В моем PubController я бы хотел, чтобы при выборе опции «Фильтр по открытым пабам» if ($request->openPubs == 1) отображались только открытые пабы isOpen ==true.

Зная отношения между моделями, как я могу это сделать?

Я ищу что-то вроде этого:

 if ($request->openPubs == 1)
 {
   $pubs = $pubs->with('pubSchedules')->where('isOpen' == true);
 }

Вы можете помочь мне?

Большое спасибо!

Может вы это ищете: laravel.com/docs/5.6/eloquent-relationships#eager-loading

Birendra Gurung 11.06.2018 16:07

использование $ appends и getOpenPubs () в модели должно дать вам виртуальное поле, которое вы ищете

GoatHater 11.06.2018 16:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
0
2
101
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Для небольших таблиц вы можете вызвать функцию isPubCurrentlyOpen для каждого элемента.

Для этого вам нужно будет изменить свою функцию, чтобы получать pub_id в качестве параметра:

public function isPubCurrentlyOpen($pub_id)
{
    $schedules = Schedule::where([
            ['pub_id', $pub_id ],
            ['week_day', Carbon::now()->dayOfWeek],
    ])->get();

    foreach ($schedules as $schedule){
        $isOpen[] =
            Carbon::now('Europe/Madrid')->between(
                Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->opening_time),
                Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->closing_time)
            );
    }

    if (in_array(true, $isOpen)){
        return true;
        //return "Pub Opened";
    }

    return false;
    //return "Pub Closed";
}

и для запроса данных выполните:

if ($request->openPubs == 1)
{
   // assuming $pubs is a collection instance
   $pubs = $pubs->filter(function($a){
        return $this->isPubCurrentlyOpen($a->id);
   })
}

Я не совсем понимаю, как вы пытаетесь это сделать, но должно быть что-то вроде этого

   $pubs = Pub::with(['pubSchedules' => function ($query) {

        $query->where('opening_time', '>' ,Carbon::now()) // make sure it's currently open
              ->where('closing_time', '<' ,Carbon::now()) // make sure that it's not finished already
              ->where('week_day', '==' ,Carbon::now()->dayOfWeek) // make sure it's today

    }])->find($id);

  // to get if pub is currently

  if ($pub->pubSchedules->count()){
      //
   }

   you can put this code in the model (Pub) and make some changes
   if you already have the object you can do this (Add it to model)

public function isPubOpen()
{
    $this->load(['pubSchedules' => 
        // same code in other method
    ]);

    return (bool) $this->pubSchedules->count();
}
Ответ принят как подходящий

Вы можете сделать это с помощью whereHas

$openPubs = Pub::whereHas('schedule', function ($query) {
       $query->where('week_day', Carbon::now()->dayOfWeek);
       $query->whereRaw(
           "'".Carbon::now('Europe/Madrid')->format("H:i:s")."' BETWEEN opening_time AND closing_time"
       ); 
})->get();       

Предполагается, что время открытия и время закрытия являются подходящим форматом времени, а не строками (хотя строки также будут работать в 24-часовом формате).

Вы можете добиться чего-то похожего на то, что ищете, используя прицел, например.

public function scopeFilterBy($query, $filter = null) {
     if ($filter == "isOpen") {
        $query->whereHas('schedule', function ($query) {
          $query->where('week_day', Carbon::now()->dayOfWeek);
          $query->whereRaw(
            "'".Carbon::now('Europe/Madrid')->format("H:i:s")."' BETWEEN opening_time AND closing_time"
           );  
        });
    }
    return $query; //Not sure if this is needed
}

Тогда вы могли бы сделать:

 Pub::filterBy($request->openPubs ? "isOpen" : null)->get(); 

да, это было бы лучшим решением, если он хочет только открытые пабы (у)

Achraf Khouadja 11.06.2018 16:19

@AchrafKhouadja Тогда я, возможно, неправильно понял требование

apokryfos 11.06.2018 16:20

Большое спасибо за ваш ответ, просто мне нужно то, что вы сделали. У меня есть проблемы с его реализацией, но я надеюсь их решить. Позвольте мне несколько минут, большое спасибо

Ber Tsacianegu del Tepuy 11.06.2018 17:01

@BerTsacianegudelTepuy, вы можете прочитать об объемах на laravel.com/docs/5.6/eloquent#query-scopes для более подробной информации о 2-й части

apokryfos 11.06.2018 17:03

Эта ошибка: Синтаксическая ошибка или нарушение прав доступа: 1064 У вас есть ошибка в синтаксисе SQL; ........ и существует (выберите * из schedules, где pubs.id = schedules.pub_id и week_day = 1 и 2018-06 -11 17:15:56 МЕЖДУ временем открытия И временем закрытия)) в Connection.php (664) «связано с Carbon :: now ('Europe / Madrid')». МЕЖДУ временем открытия И временем закрытия "... знаете ли вы, как решить эту проблему?

Ber Tsacianegu del Tepuy 11.06.2018 17:41

Я пропустил цитаты, а вы пропустили часть ->format("H:i:s"). Проверить обновление

apokryfos 11.06.2018 17:42

В Eloquent есть функция под названием Нетерпеливая загрузка. Eloquent ORM предоставляет простой синтаксис для запроса всех расписаний, связанных с этим конкретным Pub, как описано ниже:

$pubIsOpen= $pub->schedules()
  ->where([
        ['week_day', Carbon::now()->dayOfWeek],
        ['opening_time' , '<' , Carbon::now('Europe/Madrid')],
        ['closing_time' , '>' , Carbon::now('Europe/Madrid')]
  ])
  ->count();
if ($openPubCount > 0){
    //PUB is open
}else{
    //PUB is closed
}

Если это кому-то поможет в будущем, я публикую свое решение благодаря @apokryfos:

Паб:

/**
 * @param $pubs
 * @return mixed
 */
public static function isPubCurrentlyOpen($pubs)
{
    $pubs->whereHas( 'pubSchedules', function ($pubs) {
        $pubs->where( 'week_day', Carbon::now()->dayOfWeek )
            ->whereRaw(
                "'" . Carbon::now( 'Europe/Madrid' )->format( "H:i:s" ) . "' BETWEEN opening_time AND closing_time"
            );
    } );

    return $pubs;
}

PubsController:

/**
 * @param GetPubRequest $request
 * @return ApiResponse
 */
public function getPubs(GetPubRequest $request)
{
    $orderBy = 'id';
    $order = 'asc';

    $pubs = Pub::withDistance();

    ............


    if ($request->openPubs == 1)
    {
        $pubs = Pub::isPubCurrentlyOpen($pubs);
    }

    return $this->response(PubProfileResource::collection($pubs->orderBy($orderBy, $order)->paginate()));
}

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