Laravel 8中如何让模型属性依不同仓库方法返回不同结果
解决Laravel模型属性根据仓库方法返回不同结果的问题
方法一:给模型添加临时状态标记
通过在模型上设置临时属性,让仓库方法可以控制children属性的返回逻辑:
- 修改模型代码
添加一个公共标记属性,调整getChildrenAttribute的判断逻辑:
public $timestamps = false; protected $guarded = ['Id']; protected $table = 'MapLayerGroup'; protected $appends = ['leaf', 'children']; protected $hidden = ['descendants', 'mapLayers']; // 新增临时标记,控制是否包含mapLayers public $includeMapLayers = false; public function parent() { return $this->belongsTo(MapLayerGroupModel::class, 'ParentId'); } public function descendants() { return $this->hasMany(MapLayerGroupModel::class, 'ParentId')->orderBy('id', 'asc'); } public function mapLayers() { return $this->hasMany(MapLayerModel::class, 'MapLayerGroupId', 'Id'); } public function getChildrenAttribute() { if (!$this->includeMapLayers) { return $this->descendants->toArray(); } else { return array_merge( $this->descendants->toArray(), $this->mapLayers->toArray() ); } } public function getLeafAttribute() { return count($this->children) === 0; }
- 修改仓库方法
在返回结果前,遍历模型实例设置标记:
public function paginate(array $options = []) { $typeCode = $options['typeCode'] ?? null; $user = Auth::user(); $is_admin = $user->isAdmin(); if(!$is_admin && $typeCode === null) { throw BaseException::withMessages([ __('Gis::error.map_layer.not_allowed') ]); } $query = $this->model ->whereNull('ParentId') ->with(['descendants']) ->orderBy('Id', 'asc'); if ($typeCode !== null) { $query->whereHas('MapLayerGroupType', function ($query) use ($typeCode) { $query->where('Code', $typeCode); }); } $this->setQuery($query); $result = parent::paginate($options); // 设置标记:不包含mapLayers foreach ($result->items() as $item) { $item->includeMapLayers = false; } return $result; } public function mapGroupLayersList() { $query = $this->model ->with(['descendants', 'mapLayers']) // 预加载mapLayers避免N+1查询 ->whereNull('ParentId') ->orderBy('Id', 'asc'); $this->setQuery($query); $result = parent::paginate(); // 设置标记:包含mapLayers foreach ($result->items() as $item) { $item->includeMapLayers = true; } return $result; }
方法二:使用API资源类(更优雅的方案)
通过Laravel的API资源类,根据不同场景返回不同结构,无需修改模型核心逻辑:
- 创建资源类
namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class MapLayerGroupResource extends JsonResource { private $includeMapLayers; public function __construct($resource, $includeMapLayers = false) { parent::__construct($resource); $this->includeMapLayers = $includeMapLayers; } public function toArray($request) { $children = $this->descendants->toArray(); if ($this->includeMapLayers) { $children = array_merge($children, $this->mapLayers->toArray()); } return [ 'id' => $this->Id, // 其他需要返回的字段 'children' => $children, 'leaf' => count($children) === 0, ]; } }
- 仓库方法中使用资源返回
public function paginate(array $options = []) { // 原有查询逻辑... $result = parent::paginate($options); // 默认不包含mapLayers return MapLayerGroupResource::collection($result); } public function mapGroupLayersList() { $query = $this->model ->with(['descendants', 'mapLayers']) ->whereNull('ParentId') ->orderBy('Id', 'asc'); $this->setQuery($query); $result = parent::paginate(); // 传入true表示包含mapLayers return MapLayerGroupResource::collection($result, true); }
内容的提问来源于stack exchange,提问作者Shokouh Dareshiri
相关产品推荐
相关产品推荐

