laravel - 使用关系表查询远距离关系
问题描述
我正在使用 Laravel 5.7 和 mysql。我有一张services
桌子,还有一张allowed_locations
桌子,上面有每个城市提供的服务。1 个服务可以在 1 个或多个城市提供。每个城市属于一个州,每个州属于一个国家。我想返回服务、城市、州和国家,但我不确定如何在每个模型中设置关系。我可以检索城市、州和国家吗?
城市
id
state_id
状态
id
country_id
name
国家
id
name
服务
id
name
Allowed_Locations
city_id (id from cities table)
service_id (id from Services table)
国家 ID,名称 1,美国
状态
id, country_id, name
3, 1, California
4, 1, Washington
5, 1, Oregon
城市
id, state_id, name
1, 3, San Diego
2, 4, Seattle
3, 5, Portland
服务
id, name
1, Tax Services
2, Legal Services
允许的位置
city_id, service_id
1, 1
2, 1
3, 2
Services.php 模型
public function locations () {
return $this->belongsToMany('App\cities', 'services_by_location', 'service_id','city_id');
}
city.php 模型
public $with = ['state'];
public function state() {
return $this->hasOne(states::class, 'id', 'state_id');
}
states.php 模型
public $with = ['country'];
public function country() {
return $this->hasOne(Countries::class, 'id', 'country_id');
}
Country.php 模型
//
AllowedLocations.php 模型
//
控制器
$data = Services::with(['locations'])->get();
return response()->json($data, 200);
目前我正在回复这样的回复
{
{
id: 1,
name: Tax Services
locations:
{
{
city_id: 1,
city: San Diego,
state: {
name: California
}
country: {
name: USA,
}
},
{
city_id: 2,
city: Seattle,
state: {
name: Washington
}
country: {
name: USA,
}
},
}
},
{
id: 2,
name: Legal Services
locations:
{
{
city_id: 3,
city: Portland,
state: {
name: Oregon
}
country: {
name: USA,
}
},
}
}
}
而不是嵌套state
,country
我想在位置嵌套数组中返回城市、州和国家名称。这可能吗?
{
{
id: 1,
name: Tax Services
locations:
{
{
city_id: 1,
city: San Diego,
state: California,
country: USA
},
{
city_id: 2,
city: Seattle,
state: Washington,
country: USA
},
}
},
{
id: 2,
name: Legal Services
locations:
{
{
city_id: 3,
city: Portland,
state: Oregon,
country: USA
},
}
}
}
解决方案
这是一个有趣的挑战,所以我在一台测试机器上设置了它并解决了它。毫无疑问,还有其他方法可以做到这一点,但这是可行的,并且可以根据需要在顶层使用州和国家/地区。
这些参数不会显示在dd()
转储中,尽管它们可以在顶层直接访问,并且如果您通过 JSON转储,它们将显示出来。
我认为最简单的帮助方法是在 City 模型上设置访问器。然后,当locations()
从 Services 模型调用该方法时,所有城市都有您需要的信息。
城市型号:
protected $fillable=[
'name',
'state_id',
];
protected $appends = ['state_name', 'country_name'];
public function state() {
return $this->hasOne(State::class, 'id', 'state_id');
}
public function getStateNameAttribute ()
{
return $this->state->name;
}
public function getCountryNameAttribute ()
{
return $this->state->country->name;
}
注意protected $appends = ['state_name', 'country_name'];
. 这允许在您转储到 JSON 时显示这些额外的字段。如果您只需要访问额外的字段 (state_name
和country_name
),则不需要这一行——您现在可以从数组的 City 级别部分中提取字段,因为我们在 City 模型中有访问器。
该查询现在需要包含更多的急切加载,以便这些访问器不会尝试从空值中获取名称。(您应该在访问器中添加一个空检查)我建议像这样一次将其全部拉入:
$data = \App\Service::with(['locations' => function($query){
$query->with(['state' => function($query){
$query->with('country');
}]);
}])->get();
现在,执行 for 循环$data
将为您提供城市级别所需的一切。例如:
foreach($data as $service){
echo "Service id: ".$service->id.": ";
echo $service->name."<br/>";
echo $service->locations->first()->name.", ";
echo $service->locations->first()->state_name." -- in the country: ";
echo $service->locations->first()->country_name;
echo "<br/><br/><br/>";
}
这成功产生:
Service id: 1: Tax Services
Annapolis, Maryland -- in the country: USA
Service id: 2: Legal Services
Potomac, Maryland -- in the country: USA
推荐阅读
- php - MySQL插入失败,没有错误,执行中的绑定值,PHP
- postgresql - java 8 到 java 11 迁移后使用 postgres db 和 spring boot 保存 jsonb 类型数据得到 JpaSystemException
- python - 如何在 Queryset 类中通过聚合获取对象计数
- frameworks - 我在向导航栏应用填充时遇到问题(扩展时)
- python - 即使在我定义变量之后,我的变量也不想显示出来,这给了我一个变量不存在的错误
- apache-kafka - 与 kafka 或其他框架一起使用时是否存在 JAAS / SASL / PLAIN / SCRAM 的安全架构图?
- c++ - VS 代码 C++ Linter
- video - 视频跟踪文件量过长?
- laravel - laravel 视图组件类不向实时服务器中的视图组件发送数据
- python - Discord.py `on_user_update` 不起作用,即使启用了意图