php - Eloquent "whereDate"在 Laravel 5.4 升级后不工作

标签 php mysql laravel eloquent

(很抱歉提前发了这么长的帖子)

我正在将我的应用程序从 Laravel 5.2 升级到 5.4,并且从今天早上开始就一直卡在这个问题上。出于某种原因,我使用 Eloquent “whereDate”选择即将到来的业务事件的查询没有返回任何内容,即使其他一切都表明它应该有效!

我有一个无法通过的 phpUnit 测试来尝试定位问题。 (详见下文)

我有一个“业务”模型:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Business extends Model
{
    protected $table = 'businesses';
    ..

public function businessEvents(){
    return $this->hasMany('App\BusinessEvent', 'business_id');
}

以及“BusinessEvent”模型:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class BusinessEvent extends Model
{
  protected $table = 'business_events';
  protected $fillable = ['business_id', ..., 'start_date', 'end_date'];

  public function business(){
      return $this->belongsTo('App\Business', 'business_id');
  }
...

我在测试中制作了它们的虚拟版本。虚拟“业务”适用于其他测试,但我为这个测试用例引入了以下虚拟“business_event”:

protected function createMockBusinessEventWithUpcomingDateTime($businessId){
  $faker = Faker::create();

  $businessEvent = BusinessEvent::create([
      'business_id'   => $businessId,
      'name'          => $faker->name,
      'description'   => $faker->text,
      'start_date'    => date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")."+30 minutes")),
      'end_date'      => date("Y-m-d H:i:s", strtotime(date("Y-m-d H:i:s")."+1 hour +30 minutes"))
  ]);

  ...

  $business = Business::find($businessId);
  if($business){
    $businessEvent->business()->associate($business);
  }

  return $businessEvent;
}

现在这是实际的测试函数:

public function testGetUpcomingN(){

    $this->businessEvent  = $this->createMockBusinessEventWithUpcomingDateTime($this->business->id);

    $response = $this->json('GET', '/api/v1/business/'.$this->business->id.'/events/upcoming/2');

    $this->outp($response->content());

    $this->outp("Testing Assertions");
    $this->assertEquals(200, $response->status());  
    $this->assertEquals($this->business->businessEvents()->first()->id, $this->businessEvent->id);     
}

测试没有失败,这意味着事件正确地与业务相关联,无论我如何查询 api 端点(HttpRequester、Logging 结果、测试中的返回值、生产......)它总是返回一个空数组!

Controller 中调用的以下函数(也验证过了!):

public function upcomingN($businessId, $n){
    Log::info('Get upcoming '.$n.' recorded events for business with id: '.$businessId);
    $business = Business::find($businessId);
    if (is_null($business)){
        Log::warning('No business exists with given id. Exiting.');
        return response('No Content.', 204);
    }

    $currentDate = date('Y-m-d H:i:s');

    $greaterThan = $business->businessEvents()->first()->end_date >= $currentDate;
    Log::info("Greater THAN:", [$greaterThan]);

    $events = $business->businessEvents()->whereDate('end_date', '>=', $currentDate)->take($n)->get();

    if (!is_null($events)){
        Log::info('Got upcoming N recorded events for business with id: '.$businessId, (array) $events);
        return response()->json($events);
    }

    return response('No Content.', 204);
}

如您所见,我什至尝试记录“$greaterThan” bool 值,它应该测试与“whereDate”所做的完全相同的事情,并且它的计算结果为真!我已经尝试过 Carbon::parse()-ing,设置语言环境,但现在我完全没有想法了。

在 5.2 中有效的旧函数:

public function upcomingN($businessId, $n){
   Log::info('Get upcoming N recorded events for business with id: '.$businessId);
$business = Business::find($businessId);
if (is_null($business)){
    Log::warning('No business exists with given id. Exiting.');
        return response('No Content.', 204);
    }

    $currentDate = date('Y-m-d H:i:s');
    $events = $business->businessEvents()->whereDate('start_date', '>=', $currentDate)->take($n)->get();

     if (!is_null($events)){
         Log::info('Got upcoming N recorded events for business with id: '.$businessId, (array) $events);
         return response()->json($events);
     }

    return response('No Content.', 204);
}

在升级过程中我确实需要更改的一件事是将 mysql-db 设置为非严格的,因为 Laravel 提示缺少默认值。但是,我已经检查了数据库并且正确填充了测试条目。

任何帮助将不胜感激!

最佳答案

非常感谢 Omisakin Oluwatobi ,解决方案实际上是使用 Eloquent “where”而不是“whereDate”,因为“whereDate”只比较日期而不是日期时间(事后看来似乎很明显)。

如果您可以使用相同数量的代码获得与“where”相同的结果,那么“whereDate”函数的存在让我感到有点困惑。

我可以验证(经过单元测试)以下最终解决方案是否适用于选择 future 的日期时间并忽略过去的日期时间:

public function upcomingN($businessId, $n){
    Log::info('Get upcoming '.$n.' recorded events for business with id: '.$businessId);
    $business = Business::find($businessId);

    if (is_null($business)){
        Log::warning('No business exists with given id. Exiting.');
        return response('No Content.', 204);
    }

    $currentDate = date('Y-m-d H:i:s');
    $events = $business->businessEvents()->where('end_date', '>=', $currentDate)->take($n)->get();

    if (!is_null($events)){
        Log::info('Got upcoming N recorded events for business with id: '.$businessId, (array) $events);
        return response()->json($events);
    }

    return response('No Content.', 204);
}

关于php - Eloquent "whereDate"在 Laravel 5.4 升级后不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44974792/

相关文章:

mysql - Ruby on Rails 查询中下划线的转义字符

php - 我有一个 SQL 查询,它使用 UNION : 链接 3 个表

javascript - 如何在 Laravel 中使用 js

php - 任何 php artisan 命令卡住终端

mysql - 如何在 Laravel 5.2 中获取最新条件后的行号?

php - 刷新页面过多

php - 我在数据库中有一个表,我想在其中获取列的最后一个值

php - 在 CodeIgniter 中显示用于 seo 的动态 URL

php - 如何统计静态页面的浏览量?

MySql - 如何在选择和分组依据中使用表达式