【问题标题】:Append accessor on demand按需附加访问器
【发布时间】:2014-11-07 10:48:00
【问题描述】:

我试图有时将我的 Accessor 附加到 Eloquent 查询的结果中。

这是我的访问器:

public function getCatAttribute() {
    return "Here's a cat!";
}

如果我使用 protected $appends = array('cat'); 数组附加它,它每次都可以正常加载。

但是,当删除它时,因为我不希望它总是附加它,我无法让它在 Eloquent 查询中加载它。

这是我尝试过的:

$items = Item::with('cat')->get();

我怎样才能做到这一点?

【问题讨论】:

  • 访问器不会附加到任何查询中。如果您使用$appends 属性,它们将在toArray/toJson 调用期间进行处理,仅此而已。那么你想达到什么目标呢?
  • 我希望能够在某些情况下添加 Cat 属性,而不是在其他情况下
  • 嗯,很明显.. 你不具体,所以你想让别人猜?现在我只能告诉你:创建 SOMETIMES 返回变异值的逻辑,否则将其原封不动地返回。
  • 问题很具体。 我有时会尝试将我的访问器附加到 Eloquent 查询的结果中,我该如何实现?
  • 我知道我需要“创建逻辑”来满足我的要求

标签: php laravel laravel-4 eloquent accessor


【解决方案1】:

对不起,如果我参加聚会迟到了。

你不能这样做:

$items = Item::with('cat')->get();

因为访问器是一个计算属性,这意味着它首先需要具有模型实例的实际属性。

相反,您可以这样做:

$items = Item::get();
$items->append('cat'); // this allows you to append accessors on-demand

【讨论】:

    【解决方案2】:

    编辑:

    IMO 唯一的方法是扩展您的模型类并使用您已经提到的$appends。所以像

    class ModelWithCat extends MyModel
    {
        protected $appends = ['cat_attribute']
    }
    

    然后将其称为

    ModelWithCat::get();
    

    以下是我的旧答案供参考:

    我正在对类似的问题进行排序,在我的情况下,我需要将 JSON 数据从查询构建器提供给 Vue 表,并且需要在后端转换数据,因此 Vue 表可以直接使用数据。我在控制器中的代码如下所示:

    $query = Photo::query()->with(['user']);
    if($filter) {
        $query->where('title', 'like', "%{$filter}%")
    }
    return $query->orderBy($field, $dir)->paginate($limit)
    

    我还没有找到触发集合访问器的方法,也无法循环访问 Paginator 类的结果。最后我意识到这最终会返回 JSON,我可以在发送到 Vue 之前对其进行修改。所以我以这样的方式结束:

    // transform the data before return them
    $res_json = $query->orderBy($field, $dir)->paginate($limit)->toJson();
    $res_decoded = json_decode( $res_json );
    foreach($res_decoded->data as $item) {
        // transform the data.. you could probably call your accessor here like 
        // $item->cat = $item->cat , for me it was easier to just write the logic
        // here instead
        $item->license = 'dynamic-license';
    }
    return response()->json($res_decoded);
    

    我知道它很丑,但这是我找到的唯一方法,而且我只在一个地方使用它,所以我认为我必须忍受它。也许它可以帮助某人。

    【讨论】:

      【解决方案3】:

      我知道这篇文章有点晚了,但对于其他一些想要了解的人来说,在最新版本中使用 append 方法在查询调用中实现按需 IMO 的简单方法。它已经在上面的一些答案中。

      Item::get()->append('attibute_name');
      

      另外,在使用分页时

      $paginate = Item::paginate(10); // receive LengthAwarePaginator Instance
      $items = collect($paginate->items()); // receive paginated items only to append
      $items->each->append('attribute_name') // then simply you append it what auto accessor will do in toArray()
      

      你明白了。

      【讨论】:

        【解决方案4】:

        我不知道我是否理解这个问题,但您可以为不存在的属性创建访问器。假设你有cat 属性,你可以创建:

        public function getModCatAttribute($value) {
          if ($this->cat == 'dog') {
             return "I'm a dog";
          }
          return $this->cat;
        }
        

        所以您现在可以访问$model->cat$model->mod_cat。对于一般用途,此方法更好,因为您始终可以访问原始属性和修改后的属性,并且您始终知道修改了哪个属性。

        但你也可以这样做:

        public function getCatAttribute($value) {
          if ($this->cat == 'dog') {
             return "I'm a dog";
          }
          return $this->cat;
        }
        

        现在您可以访问$model->cat,结果取决于您在$cat 属性中的内容。

        【讨论】:

          猜你喜欢
          • 2017-05-31
          • 2018-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-05
          • 1970-01-01
          相关资源
          最近更新 更多