【发布时间】:2017-07-07 15:38:45
【问题描述】:
(抱歉,长篇大论)
我正在将我的应用程序从 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');
}
...
我在测试中制作了这两个版本的虚拟版本。虚拟“业务”适用于其他测试,但我为此测试用例引入了以下 虚拟“业务事件”:
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;
}
现在是实际的 test 函数:
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、日志记录结果、测试中的返回值、生产...)它总是返回一个空数组!
以下函数是控制器中调用的(也已验证!):
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”布尔值,它应该测试与“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 抱怨缺少默认值。但是,我已经检查了数据库,并且测试条目已正确填充。
任何帮助将不胜感激!
【问题讨论】:
-
我认为您应该首先记录
$business->businessEvents()->first()->end_date的值并查看它返回的内容,然后您可以告诉它是否可以告诉您是否还有更多需要考虑 -
我确实记录了这个值,它是
"2017-07-07 18:32:01",而比较值(当前日期)输出为"2017-07-07 17:29:39"。正是我所期望的:/ -
您可以检查两件事:我对字符串或日期时间对象的日期时间比较不太自信,因为根据内部转换,Laravel 的模型日期时间字段可能会返回作为字符串或 Carbon 对象,所以我建议即使您也可以简单地使用:
Carbon::now()->greaterThan(Carbon::parse($business->businessEvents()->first()->end_date));也尽量不要使用whereDate()并使用where() -
谢谢,使用 where() 是解决方案!我以为我已经尝试过了,但肯定有其他东西在干扰(或者我搞砸了其他东西)......
标签: php mysql laravel eloquent