Laravel Eloquent:五张数据表的关联关系实现方法咨询
Laravel Eloquent关联实现:users、user_location、cities、states、countries五表关联
嘿,我来帮你理清楚这五张表的Eloquent关联关系,其实按照数据层级一步步拆解就很清晰了,咱们逐个模型来写对应的关联方法:
1. Country模型
一个国家对应多个州,所以是一对多关联;同时可以通过hasManyThrough直接关联到城市(跳过州这一层):
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Country extends Model { protected $table = 'countries'; // 一个国家有多个州 public function states(): HasMany { return $this->hasMany(State::class); } // 一个国家有多个城市(通过州间接关联) public function cities() { return $this->hasManyThrough(City::class, State::class); } }
2. State模型
一个州属于某个国家,同时对应多个城市,分别是多对一和一对多关联:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; class State extends Model { protected $table = 'states'; // 州属于某个国家 public function country(): BelongsTo { return $this->belongsTo(Country::class); } // 一个州有多个城市 public function cities(): HasMany { return $this->hasMany(City::class); } }
3. City模型
城市属于某个州,同时通过user_location中间表和用户形成多对多关联;如果需要直接关联到国家,可使用belongsToThrough(注意版本兼容性):
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class City extends Model { protected $table = 'cities'; // 城市属于某个州 public function state(): BelongsTo { return $this->belongsTo(State::class); } // 城市属于某个国家(通过州间接关联) // 注意:Laravel 9.x及以上原生支持belongsToThrough,低版本需安装staudenmeir/belongs-to-through包,或用join替代 public function country() { return $this->belongsToThrough(Country::class, State::class); } // 城市关联多个用户(通过user_location中间表) public function users(): BelongsToMany { // 参数依次:关联模型、中间表名、中间表中当前模型的外键、中间表中关联模型的外键 return $this->belongsToMany(User::class, 'user_location', 'cities_id', 'user_id'); } }
4. UserLocation模型(可选)
如果你的user_location表需要存储额外字段(比如关联时间、备注等),可以建立这个模型,用来直接操作中间表数据:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class UserLocation extends Model { protected $table = 'user_location'; public $timestamps = false; // 如果表没有created_at/updated_at字段,需设置为false // 关联用户 public function user(): BelongsTo { return $this->belongsTo(User::class); } // 关联城市 public function city(): BelongsTo { return $this->belongsTo(City::class, 'cities_id'); } }
5. User模型
用户通过user_location和城市形成多对多关联,也可以通过关联链直接获取到州和国家:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class User extends Model { protected $table = 'users'; // 用户关联多个城市(通过user_location中间表) public function cities(): BelongsToMany { return $this->belongsToMany(City::class, 'user_location', 'user_id', 'cities_id'); } // 获取用户所在的所有州(通过城市间接关联) public function states() { return $this->hasManyThrough(State::class, City::class, 'id', 'id', 'id', 'state_id'); } // 获取用户所在的所有国家(通过州和城市间接关联) public function countries() { return $this->hasManyThrough(Country::class, State::class, 'country_id', 'id', 'id', 'state_id'); } // 如果使用了UserLocation模型,可直接关联中间表 public function userLocations() { return $this->hasMany(UserLocation::class); } }
关联使用示例
- 获取某个用户的所有城市及对应的州和国家:
$user = User::with('cities.state.country')->find(1); foreach ($user->cities as $city) { echo "{$city->name}, {$city->state->name}, {$city->state->country->name}\n"; }
- 获取某个国家的所有州及下属城市:
$country = Country::with('states.cities')->find(1); foreach ($country->states as $state) { echo "{$state->name}: "; foreach ($state->cities as $city) { echo "{$city->name} "; } echo "\n"; }
内容的提问来源于stack exchange,提问作者Kaushal Patel
相关产品推荐
相关产品推荐

