Php 如何在连接表时使用with()
我有以下仅包含相关字段的表格: 装置 身份证 名称 创建于 更新地址 设备报告 身份证 设备id 地方 创建于 更新地址 我有一份报告,上面有许多过滤器,这些过滤器已经在工作,所以我想坚持用雄辩的方式做事。以下是控制器功能:Php 如何在连接表时使用with(),php,mysql,laravel,eloquent,Php,Mysql,Laravel,Eloquent,我有以下仅包含相关字段的表格: 装置 身份证 名称 创建于 更新地址 设备报告 身份证 设备id 地方 创建于 更新地址 我有一份报告,上面有许多过滤器,这些过滤器已经在工作,所以我想坚持用雄辩的方式做事。以下是控制器功能: public function devices(Request $request) { $devicesQuery = Device::with(['latestReport']); if ($request->ajax()) {
public function devices(Request $request)
{
$devicesQuery = Device::with(['latestReport']);
if ($request->ajax())
{
if($request->input('start') && $request->input('start')!='')
{
$start_date = date('Y-m-d', strtotime($request->input('start')));
$end_date = date('Y-m-d', strtotime($request->input('end')));
$devicesQuery = $devicesQuery->lastReportBetween($start_date,$end_date);
}
$devices = $devicesQuery->paginate(10);
return Response::json(View::make('devices/table', array('devices' => $devices))->render());
}
}
模型的最新报告定义为:
public function latestReport()
{
return $this->hasOne('App\Models\DeviceReport')->latest();
}
public function scopeLastReportBetween($query, $start, $end)
{
$query = $query->join('device_reports AS dr', 'dr.device_id', '=', 'devices.id');
$query = $query->where('dr.id', '=', DB::raw('(SELECT max(dr2.id) FROM device_reports AS dr2 WHERE dr2.device_id = devices.id)'));
$query = $query->where(DB::raw("(IFNULL(dr.gps_time, dr.created_at))"), '>=', DB::raw("STR_TO_DATE('".$start."', '%Y-%m-%d')"));
$query = $query->where(DB::raw("(IFNULL(dr.gps_time, dr.created_at))"), '<=', DB::raw("STR_TO_DATE('".$end."', '%Y-%m-%d')"));
return $query;
}
模型的函数lastReportBetween定义为:
public function latestReport()
{
return $this->hasOne('App\Models\DeviceReport')->latest();
}
public function scopeLastReportBetween($query, $start, $end)
{
$query = $query->join('device_reports AS dr', 'dr.device_id', '=', 'devices.id');
$query = $query->where('dr.id', '=', DB::raw('(SELECT max(dr2.id) FROM device_reports AS dr2 WHERE dr2.device_id = devices.id)'));
$query = $query->where(DB::raw("(IFNULL(dr.gps_time, dr.created_at))"), '>=', DB::raw("STR_TO_DATE('".$start."', '%Y-%m-%d')"));
$query = $query->where(DB::raw("(IFNULL(dr.gps_time, dr.created_at))"), '<=', DB::raw("STR_TO_DATE('".$end."', '%Y-%m-%d')"));
return $query;
}
当在选择开始/结束日期的情况下运行上述操作时,我会返回正确的记录,但在latestReport中不会返回任何内容,但当我在没有日期过滤器的情况下运行页面时,它会在latestReport类变量中正确返回设备信息和最新的报告记录
有谁能帮助我理解如何更改此代码,以便在调用lastReportBetween函数时能够返回最新的报告吗?我解决了问题。我应该使用whereHas而不是手动连接之类的
public function scopeLastReportBetween($query, $start, $end)
{
return $query->whereHas('latestReport', function($reportsQuery) use ($start, $end)
{
$reportsQuery->whereBetween('created_at', [$start, $end])
->where('device_reports.id', '=', DB::raw('(SELECT max(dr2.id) FROM device_reports AS dr2 WHERE dr2.device_id = device_reports.device_id)'));
});
}
非常确定您需要手动保护DB::raw,以防$start和$end PHP变量上的SQL注入。。我相信DB::qoute。。或者DB::escape工作不确定annymore这些函数在您的Laravel版本中是否有效。否则,您需要执行DB::connection->getPdo->quote..我将对此进行研究。