我目前正在努力应对复杂的SQL / Laravel关系问题。
对于每个用户,我需要设置首选项。这些偏好包括四种不同的类型:
期望的关系类似于:
$user = User::find(1)
//Retrieves all user locations
$user->preferences->locations
//Retrieves all user competitors
$user->preferences->competitors
//Retrieves all user platforms
$user->preferences->platforms
//Retrieves all graphs
$user->preferences->graphs
我已经反复更改了当前的数据结构,因为我无法弄明白,但它看起来像这个表:
然后对于每种类型的偏好(位置,竞争对手等),另一个表:
这种混乱的进一步复杂化是四种偏好类型与它们要加入的表格不匹配。例如,位置和竞争对手都需要加入我拥有的业务表(他们在该数据透视表中的ID是业务ID),平台需要加入服务表。
我的问题是,我将如何制定这种复杂的关系?这是我使用多态关系的情况吗?我是否需要每个数据透视表的模型(user_preferences_location等)?我现在完全不知所措,我几个小时都在努力解决这个问题。任何帮助都会非常有帮助。
感谢。
答案 0 :(得分:2)
我认为你过度思考它。您真的需要通过preferences
属性访问关系吗?为什么不做这样的事情:
$user = User::find(1)
//Retrieves all user locations
$user->locationPreferences
//Retrieves all user competitors
$user->competitorPreferences
//Retrieves all user platforms
$user->platformPreferences
//Retrieves all graphs
$user->graphPreferences
区别是什么?这些只是四个简单的" hasMany"四种不同类型的偏好中的每一种的用户模型和模型之间的关系。然后你的模型看起来像这样:
class LocationPreference extends Model {
}
// plus classes for the other types of preferences...
class User extends Model {
public function locationPreferences() {
return $this->hasMany("LocationPreference");
}
// plus methods for the other types of preferences...
}
表格很简单:
CREATE TABLE location_preferences (
id INT AUTOINCREMENT,
user_id INT,
-- plus whatever other fields you need
);
您在开始时描述的方案很好 - 在模型的属性下组织所有首选项在逻辑上非常干净 - 但它需要一些扭曲来使其工作。为什么不选择一个可能不那么漂亮的简单解决方案?
答案 1 :(得分:0)
如果首选项类型表只包含id,那么您似乎只需要在用户和位置,图表等之间使用4个数据透视表。然后您可以通过user->位置访问它们或设置将返回它们的存取方法以所需的格式
public function getPreferencesAttribute($value)
{
$preferences = new stdClass();
$preferences->locations => $this->locations;
$preferences->graphs => $this->graphs;
return $preferences;
}
答案 2 :(得分:0)
我最终稍微改变了我的数据结构。我添加了一个user_preferences
表,它只是一个主键和一个user_id
。然后,我让我的三个数据透视表有一个user_preferences_id
,然后我就这样在eloquent中创建了模型:
class UserPreferences extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function locations()
{
return $this->belongsToMany(Business::class, "user_preference_location");
}
public function competitors()
{
return $this->belongsToMany(Business::class, "user_preference_competitor");
}
public function platforms()
{
return $this->belongsToMany(Service::class, "user_preference_platform");
}
}
现在,我可以通过简单的$user->preferences->locations
访问我的媒体资源。它并不像我想的那样干净:例如,我更喜欢有一个偏好表而不是它的三个支点,甚至在user_preferences
和它的类型之间有一个支点。但那是另一天的事情。