Eloquent:使用不存在的列进行查询

时间:2018-06-11 13:51:28

标签: laravel orm eloquent filtering

我尝试以下操作:我有两个与1xN关系相关的模型(Pub和Schedule),如下所示:

酒吧:

const inputRange = [1,2,3,4,5,6,7,8,9,10]
if(inputRange.includes(parseInt(input)))

时间表:

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

表格时间表包含以下字段:

id | pub_id | week_day | opening_time | closing_time |

我使用以下函数来了解当前(或不)打开一个酒吧:

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

在我的PubController中我喜欢,当选项"过滤开放酒吧"已选择/** * @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"; } ,仅显示已打开的酒吧if($request->openPubs == 1)

了解模型之间的关系,我该怎么做?

我正在寻找类似的东西:

isOpen ==true

你能帮助我吗?

非常感谢!

5 个答案:

答案 0 :(得分:1)

我不完全明白你是如何努力实现这一点的,但它应该是这样的

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

答案 1 :(得分:1)

您可以使用“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(); 

答案 2 :(得分:0)

对于小表,您可以为每个元素调用函数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);
   })
}

答案 3 :(得分:0)

Eloquent中有一个名为Eager Loading的功能。 Eloquent ORM提供了一种简单的语法来查询与此特定Pub相关的所有Schedules,如下所述:

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

答案 4 :(得分:0)

如果将来有人帮助我发布我的解决方案,感谢@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()));
}