检索Laravel模型的所有子孙

时间:2015-05-18 19:23:32

标签: php laravel eloquent

我有几个模型,所有模型都需要访问之前的模型。以下示例描述了类似的情况

<?php namespace backend\Models;

use Illuminate\Database\Eloquent\Model;

class Geo_Locations extends Model {
   protected $table = 'geo_locations';
   protected $fillable = ['id', 'name', 'population', 'square_miles', 'comments'];
   public function state(){
    return $this->hasMany('backend\Models\Geo_State', 'id', 'state_id');
  }
}

&#34; Geo_State&#34;模型

<?php namespace backend\Models;

use Illuminate\Database\Eloquent\Model;

class Geo_State extends Model {
   protected $table = 'geo_states';
   protected $fillable = ['id', 'name', 'political_obligation', 'comments'];
   public function city(){
    return $this->hasMany('backend\Models\Geo_City', 'id', 'city_id');
  }
}

然后是&#34; Geo_City&#34;模型将是

<?php namespace backend\Models;

use Illuminate\Database\Eloquent\Model;

class Geo_City extends Model {
   protected $table = 'geo_cities';
   protected $fillable = ['id', 'name', 'population', 'comments'];
   public function miles(){
    return $this->hasMany('backend\Models\Geo_Mile', 'id', 'mile_marker');
  }
}

它可以继续,但为了方便起见,我会停在那里。我想要完成什么,而且我相信很多其他人也会这样做。将是一种检索与其中一个主要模型相关的所有数据的方法。例如,我想在一个位置内获取所有城市及其各自的州。我想要的结果是什么,如

print_r(json_encode($a->getChildren(), JSON_PRETTY_PRINT));

应该打印出来

{
   "Geo_Location":{
        "name":"United States",
        "population":"300 Some Million",
        "comments":"they have a lot of issues",
        "Geo_State":{       
           "name":"Texas",
           "population":"Some big number",
           "comments":"they have a lot of republicans",       
           "Geo_City":{
              "name":"Dallas",
              "population":"A lot",
              "comments":"Their food is awesome"
           }
        }
   }

}

我在gist中有一些代码,虽然它可能记录不清,但我所做的一切都是这样,而且这是我第三次尝试这样做。

对路由/api/v1/locations/1的单独调用将返回United States的所有信息,但会遗漏Geo_State及以下内容。拨打/api/v1/state/1的电话会返回Texas个信息,但会遗漏Geo_LocationGeo_City

我所拥有的问题是它不是递归的。如果我去路线/api/v1/all,它假设要返回一个类似于上面所需的json数组,但它没有得到孩子。

2 个答案:

答案 0 :(得分:2)

听起来你想要的是加载模型在调用该模型时的关系。我知道你可以通过两种方式在laravel中使用预先加载。

第一种方法是使用with参数检索模型时,可以添加关系和嵌套关系,如下所示。     $geoLocationCollectionObject = Geo_Location::with('state', 'state.city', 'state.city.miles', 'etc..') ->where('id', $id) ->get();

这将返回一个集合对象 - 它具有返回json(toJson)的函数。我不确定它如何处理关系(你的调用子项),因此你可能需要创建一个自定义函数来解析收集对象并将其格式化为你指定的方式。
toJson Function

第二个选项与第一个选项类似,但您将with参数(作为protected $ with array)添加到模型中,以便每次调用该模型时都会加载关系。

Geo_Location class
    protected $with = array('state');
Geo_State class
    protected $with = array('city');
Geo_City class
    protected $with = array('miles');
etc...

现在,当您检索Geo_Location集合对象(或其他任何对象)时,该关系已经被加载到对象中,我相信它应该是递归的,这样当您获得状态模型时,也会调用城市里程实例 - 但我自己没有对此进行测试,因此您可能需要对此进行验证。 我使用ChromeLogger输出到控制台并自行检查。

如果你最终需要一个自定义的json_encode函数,你可以通过$ geoLocation-&gt; state来检索所有状态然后为每个状态$ state-&gt; city等来访问这个关系...查看文档了解更多信息。 Laravel Docs on Eager Loading

我不确定你所链接的代码中发生了什么,但希望这有助于一些。

答案 1 :(得分:1)

所以在经过一番摆弄之后,事实证明我正在寻找的是

Geo_Locations::with('state.city')->get();

Geo_Locations是基本模型。 “国家”和“城市”将是与基础模型的关系。如果我要返回上面的查询,我最终会得到一个我正在寻找的json数组。感谢您的帮助Anoua

(为了让这更具活力,我将尝试找到一种方法来获取所有功能的名称以使其全部自动化以跟上我的目标。)