bnu*_*mak 3 php mysql laravel eloquent
(对不起,长篇文章很抱歉)
我正在将我的应用程序从laravel 5.2升级到5.4,并且从今天早上开始一直停留在这个问题上。由于某种原因,我的查询选择了用雄辩的'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');
}
Run Code Online (Sandbox Code Playgroud)
以及“ 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');
}
...
Run Code Online (Sandbox Code Playgroud)
我都在测试中制作了两个虚拟版本。虚拟“业务”可用于其他测试,但针对此测试用例,我引入了以下虚拟“ 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;
}
Run Code Online (Sandbox Code Playgroud)
现在这是实际的测试功能:
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);
}
Run Code Online (Sandbox Code Playgroud)
测试不会失败,这意味着该事件已与业务正确关联,并且无论我如何查询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);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我什至尝试记录“ $ greaterThan”布尔值,该布尔值应该测试“ whereDate”所做的完全相同的事情,并且其结果为true!我已经尝试了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);
}
Run Code Online (Sandbox Code Playgroud)
升级期间,我确实必须更改的一件事是将mysql-db设置为非严格,因为Laravel抱怨缺少默认值。但是,我检查了数据库,并正确填充了测试条目。
任何帮助将不胜感激!
非常感谢Omisakin Oluwatobi,解决方案实际上是使用了雄辩的“ 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);
}
Run Code Online (Sandbox Code Playgroud)