系统中有用户、社区,用户是否加入某个社区的信息保存在 community_member 表中。
在 Laravel 中可以使用模型关联,在社区模型中关联 CommunityMember 模型,如下:
/**
* 用于判断是否已加入该社区, 如果未加入则为 null
* @return HasOne
*/
public function memberInfo()
{
return $this->hasOne(CommunityMemberModel::class, 'community_id', 'id')
->where(['user_id' => auth('app')->user()->id ?? 0]);
}
但是返回给前端的数据,最好是直接有一个字段用 true/false 表示是否加入该社区。
方案一
在 Controller 返回数据之前,检查关联的属性是否为 null,并把关联的属性的去掉。
这么做的坏处就是麻烦,因为这么做意味着每一次返回社区列表,都要进行用 for 循环检查数据、修改数据。
/**
* 社区列表 & 搜索社区接口
* @return JsonResponse
*/
public function index()
{
// 1.1 被封禁的社区不显示
$query = CommunityModel::where(['status' => BaseModel::ENABLED]);
// 1.2 过滤
if (!empty($this->allowedFilterFields)) {
$query = $this->constructFilters($query);
}
// 1.3 执行通用排序器
if (!empty($this->allowedSortFields)) {
$query = $this->constructSort($query);
}
// 1.4 关联是否已加入该社区
$query->with('memberInfo');
$list = $query->paginate(request('pagesize', 20));
// 返回前检查数据
$items = $list->items();
for ($i=0; $i<count($items); $i++) {
$items[$i]->is_joined = $items[$i]->memberInfo == null ? false : true;
unset($items[$i]->memberInfo);
}
return $this->success($list);
}
方案二
在 CommunityModel 中添加 is_joined 属性,并添加 getIsJoinedAttribute 方法,在此方法中判断关联的模型是否为 null,如果为 null 表示没有加入过。
(如果为关联属性设置一个 getXxxAttribute 方法,该方法会被调用,但是传入进来的 $value 为空,且不清楚究竟是 Laravel 对这些方法的调用顺序是怎么样的)
方案二虽然可行,但是未知的东西太多,比如能否保证进入下面这个 getIsJoinedAttribute 方法之前,$this->memberInfo
不为空?能否保证 unsetRelation('memberInfo')
之后 Laravel 不会使用到该属性?
protected $appends = [
'is_joined',
];
public function getIsJoinedAttribute($value)
{
if ($this->memberInfo == null) {
$this->unsetRelation('memberInfo');
return false;
} else {
$this->unsetRelation('memberInfo');
return true;
}
}
方案三
添加 is_joined 属性,并为其添加 getIsJoinedAttribute 方法,在此方法中直接查询数据库,获取当前用户是否加入某个社区的信息。
protected $appends = [
'is_joined',
];
public function getIsJoinedAttribute($value)
{
$userId = auth('app')->user()->id ?? 0;
$row = CommunityMemberModel::where(['user_id' => $userId, 'community_id' => $this->id])->first();
return !empty($row);
}