系统中有用户、社区,用户是否加入某个社区的信息保存在 community_member 表中。
在 Laravel 中可以使用模型关联,在社区模型中关联 CommunityMember 模型,如下:

  1. /**
  2. * 用于判断是否已加入该社区, 如果未加入则为 null
  3. * @return HasOne
  4. */
  5. public function memberInfo()
  6. {
  7. return $this->hasOne(CommunityMemberModel::class, 'community_id', 'id')
  8. ->where(['user_id' => auth('app')->user()->id ?? 0]);
  9. }

但是返回给前端的数据,最好是直接有一个字段用 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);
}