Laravel Eloquent:模型关联远程一对多的反向,远程一对一写法记录
因工作中需要且在论坛没有找到相关的答案,自行找到了解决办法,记录一下。
远程一对多文档链接
拿文档的表结构举例
projects
id - integer
name - string
environments
id - integer
project_id - integer
name - string
deployments
id - integer
environment_id - integer
commit_hash - string
官方给予的远程一对多配置
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
/**
* 获取项目的所有部署。
*/
public function deployments()
{
return $this->hasManyThrough(Deployment::class, Environment::class);
}
}
上面的可以通过project直接获取所有部署不多赘述。
但是有的时候可能需要从部署的机器来获取项目信息,以上表结构也可以两个反向一对一来解决问题,但是有点不够优雅。
比如一下这两个模型关联
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Environment extends Model
{
/**
* 获取环境所属项目。
*/
public function Project()
{
return $this->belongsTo(Project::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Deployment extends Model
{
/**
* 获取部署所属环境。
*/
public function Environment()
{
return $this->belongsTo(Environment::class);
}
// 这样从部署对象获取项目
public function getProject()
{
$deployment = self::query()
->with(['Environment' => function (BelongsTo $query) {
$query->with(['Project']);
}])
->first();
$project = $deployment->Environment->Project;
}
}
以上的办法有点冗余,每次要使用都要with套with,而且如果要筛选projects的name字段是某个值的部署列表,使用whereHas也很麻烦(真实场景可能是部署列表里筛选project的status字段是正常的等等),还需要用到having,但是如果能在Deployment中直接定义一个远程一对一关联到Project,那就可以直接一个with取到Project信息,而且可以正常使用whereHas,定义方式如下:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Deployment extends Model
{
/**
* 获取部署所属环境。
*/
public function Project()
{
return $this->hasOneThrough(
Project::class, // 最终获取表
Environment::class, // 中间表
'id', // Environment 被Deployment表(当前表) 关联主键
'id', // Project 被Environment表(中间表) 关联主键
'environment_id', // Deployment表(当前表)关联中间表关联字段
'project_id' // Environment(中间表) 关联最终表关联字段
);
}
// 这样从部署对象获取项目
public function getProject()
{
$deployment = self::query()
->with(['Project'])
->first();
// 获取项目信息
$project = $deployment->Project;
// whereHas筛选 名字是我的项目的部署列表
$deployment = self::query()
->whereHas('Project',function ($query) {
$query->where(['projects.name' => '我的项目']);
})
->get()->toArray();
}
}
以上,希望可以帮助到各位
本作品采用《CC 协议》,转载必须注明作者和本文链接