【问题标题】:laravel 4 Eager load as a list of idslaravel 4急切加载为ID列表
【发布时间】:2014-04-04 04:39:21
【问题描述】:

我想急切加载相关模型。但是,我不想获取整个相关模型,而是只检索它的 id。所以最后,我会有以下内容:

{
"error": false,
"invoices": {
    "id": 5,
    "biz_id": 7,
    "doc_num": 0,
    "type": 1,
    "due_date": "0000-00-00",
    "status": null,
    "to": null,
    "**related_model**": [1,2,3,4]
}

我宁愿避免循环。

更新

据我所知,如果没有循环,我就无法做到,我做了以下事情:

        $data = array();
    //get models
    $models = IncomeDoc::with('relatedReceipts')
                        ->where('type', '!=', 2)
                        ->get()
                        ->toArray();

    foreach ($models as $model)
    {
        $model['related_receipts'] = array_pluck($model['related_receipts'], 'id');

        $data[] = $model;
    }

现在我的问题是:有什么方法可以在模型本身中进行数据操作?这段代码不干净,不能重复使用,我宁愿避免。

【问题讨论】:

  • 这种方式通常无法获取ids,但在得到结果后还需要做更多的事情,并且必须有foreign key才能获取相关模型。

标签: php laravel laravel-4


【解决方案1】:

您可以使用关系来获取标识符。

  1. 自定义函数:

    public function myRelationIds()
    {
        return $this->myRelation->lists('id');
    }
    

    您调用该函数并将结果添加到响应中。

  2. Through accessor

    public function getMyRelationIdsAttribute()
    {
        return $this->myRelation->lists('id');
    }
    

    现在,您可以使用appends 属性使该属性在模型变为Array 或JSON 时自动添加:

    protected $appends = array('my_relation_ids');
    

请注意,继续预先加载关系以防止过多查询非常重要。并且鉴于关系将继续加载,您可能希望隐藏它并且只有标识符:

protected $hidden = array('myrelation');

【讨论】:

    【解决方案2】:

    最直接的解决方案是在相关模型中定义可见字段:

    class RelatedModel extends Eloquent
    {
        protected $visible = array('id');
    }
    

    注意,这将是toArray() 方法在各处返回的唯一字段。

    【讨论】:

      【解决方案3】:

      直接您将无法在单个模型中获取所有 ids,每个模型都有自己的相关模型,但您可以使用以下内容获取相关模型的 ids,例如 @ 987654323@ 是主/父模型,Post 有很多 comments,所以可以使用这个来完成:

      $ids = array();
      $posts = Post::with(array('comments' => function($q){
          // post_id is required because it's the foreign key for Post
          $q->select(array('id', 'post_id'));
      }))->get()->map(function($item) use(&$ids){
          $ids[] = $item->comments->fetch('id')->toArray();
      });
      
      // Get all ids in one array
      $ids = array_flatten($ids);
      

      现在,您只需将 Post 重命名为 Invoice 并将 comments 重命名为相关型号名称。这里Post 有许多在Post 模型中定义的具有以下关系的cmets:

      // Post model
      public function comments()
      {
          return $this->hasMany('Comment'); // Comment model
      }
      

      【讨论】:

      • 有没有办法在模型级别处理这个问题?
      【解决方案4】:

      我最近自己在急切加载方面遇到了一些问题。我的建议是复制预加载的功能,即运行第二个查询,包括第一个模型的 id 的whereIn()。回到你的例子

      $modelsQuery = IncomeDoc::where('type', '!=', 2);
      $models = $modelsQuery->get();
      $modelIds = $models->select('id')->lists('id');
      $relatedReceiptsQuery = RelatedReceipts::whereIn(`model_id`,$modelIds);
      $relatedReceipts = $relatedReceiptsQuery->get();
      $relatedReceiptsLookup = $relatedReceiptsQuery->lists(`id`,`model_id`)
      

      您将能够遍历$models,并检索$relatedReceipts->find($relatedReceiptsLookup[$models->id])。如果您只需要来自RelatedReceipts 的单个字段,则可以进一步简化此操作,或者您可以将toArray() 添加到$relatedReceipts 并搜索数组,而不是使用$relatedReceiptsLookup 来搜索模型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-13
        • 1970-01-01
        • 2015-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-12
        • 2014-08-30
        相关资源
        最近更新 更多