(对于长篇文章提前抱歉)
我正在将我的应用程序从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');
}
以及&#39; BusinessEvent &#39;模型:
<?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');
}
...
我在测试中都制作了虚拟版本。虚拟商业&#39;适用于其他测试,但我为此测试用例引入了以下 dummy&#39; business_event&#39; :
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 result,test in test,production ......)它总是返回一个空数组!
跟随功能在控制器中被称为(也经过验证!):
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);
}
正如你所看到的,我甚至尝试记录&#34; $ greaterThan&#34;应该测试与#34; whereDate&#34;完全相同的布尔值是的,它评估为真!我尝试过使用Carbon :: parse(),设置语言环境,现在我几乎没有想法。
在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抱怨缺少默认值。但是,我检查了数据库,并且测试条目已正确填充。
任何帮助将不胜感激!
答案 0 :(得分:5)
非常感谢Omisakin Oluwatobi,解决方案实际上使用了一个Eloquent'where'而不是'whereDate',因为'whereDate'只比较日期而不是日期时间(事后看来很明显)。
如果使用相同数量的代码使用'where'可以获得相同的结果,我发现'whereDate'函数存在有点令人困惑。
我可以验证(单元测试)以下最终解决方案是否可用于选择未来的日期时间并忽略过去的日期时间:
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);
}