我有两个模型,Foo
和Bar
:
class Foo extends Eloquent {
protected $table = 'foos';
protected $fillable = array('name');
public $timestamps = false;
public function bars() {
return $this->belongsToMany('bar','foos_bars');
}
}
class Bar extends Eloquent {
protected $table = 'bars';
protected $fillable = array('name');
public $timestamps = false;
public function foos() {
return $this->belongsToMany('foo','foos_bars');
}
}
我试图让所有Foo
模型及其相关的bars
像这样,然后在json中输出:
class FooController extends \BaseController {
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$foos = Foo:with('bars')->get();
return Response::json(array(
'foos' => $foos->toArray()
),200);
}
}
我遇到的问题是输出。这将输出如下内容:
{
"foos": [
{
"id": 1,
"name": "Foo 1",
"bars": [
{
"id": 1,
"name": "Bar 1",
"pivot": {
"foo_id": 1,
"bar_id": 1
}
},
{
"id": 2,
"name": "Bar 2",
"pivot": {
"foo_id": 1,
"bar_id": 2
}
},
{
"id": 3,
"name": "Bar 3",
"pivot": {
"foo_id": 1,
"bar_id": 3
}
}
]
}
]
}
但我真正想要的是:
{
"foos":
[{
"id": 1,
"name": "Foo 1",
"bars": [1, 2, 3]
}]
}
现在,我一直在迭代$foos
,以获得正确的代码:
foreach($foos as &$foo) {
$bar_ids = array();
foreach($foo->bars as $bar) {
$bar_ids[] = $bar->pivot->bar_id;
}
unset($foo->bars);
$foo->bars = $bar_ids;
}
但这似乎很复杂,增加了我试图摆脱的复杂性。是否有更简单的方法来获得所需的输出?
感谢您的帮助。
答案 0 :(得分:2)
您可以使用lists方法。
$foo->bars->lists('id');
会给你一系列foo的bar id。
适用于:
要以您想要的格式返回数据,最好使用变换器,例如fractal package(或根据您的要求自行制作更简单的版本)。
我们的想法是在中间设置一些内容来格式化数据,而不是将模型转储到控制器中的响应中。它可以直接处理您的问题并添加诸如将属性转换为类型(如布尔和整数)以及使控制器与数据库更改隔离的好处。
变压器看起来像这样:
class FooTransformer extends TransformerAbstract
{
/**
* Transform this item object into a generic array.
*
* @param Foo $foo
* @return array
*/
public function transform(Foo $foo)
{
return [
'id' => (int) $foo->id,
'name' => $foo->name,
'bars' => $foo->bars->lists('id'),
];
}
}
答案 1 :(得分:2)
使用变形金刚/演示者这样的东西,分形是你可以考虑的。但是,您可以使用Eloquent轻松完成相同的操作:
// Foo
protected $hidden = ['bars']; // don't show the collection in json
protected $appends = ['barsIds']; // but show additional info you need via accessor
public function getBarsIdsAttribute()
{
return $this->bars->lists('id');
}
现在您可以直接使用访问者:
$foo->barsIds; // [1,5,10]
并自动附加到toArray/toJson
输出:
{
"foos": [
{
"id": 1,
"name": "Foo 1",
"barsIds": [1,5,10]
}
]
}
重要如果要输出foos
的集合,请记住急切加载 bars
关系,否则您将体验到N + 1查询问题。
答案 2 :(得分:1)
听起来你想要在foo查询中使用GROUP CONCAT,你需要使用DB :: raw()。
还有lists()方法,例如
public function barsIds() {
return $this->belongsToMany('bar','foos_bars')
->lists('id');
}