如何获取多对多关系的id?
How to get the ids of many to many relation?
我有两个模型,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;
}
但这似乎很复杂,并且增加了很多我试图摆脱的复杂性。有没有更简单的方法来获得所需的输出?
感谢您的帮助。
您可以使用lists方法。
$foo->bars->lists('id');
将为您提供一组 foo 的栏 ID。
可用时间:
- Illuminate\Database\Eloquent\Builder::列表
- Illuminate\Database\Query\Builder::列表
- Illuminate\Support\Collection::列表
一些额外的建议:
为了return你想要的格式的数据,使用转换器可能会很好,比如来自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'),
];
}
}
听起来您想要在 foo 查询中使用 GROUP CONCAT,为此您需要使用 DB::raw()。
还有 lists() 方法,例如
public function barsIds() {
return $this->belongsToMany('bar','foos_bars')
->lists('id');
}
使用transformers/presenters这种东西,分形是你可以考虑的一种。但是,您可以使用 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
的集合时,记得eager loadbars
关系,否则您将遇到 N+1 查询问题。
我有两个模型,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;
}
但这似乎很复杂,并且增加了很多我试图摆脱的复杂性。有没有更简单的方法来获得所需的输出?
感谢您的帮助。
您可以使用lists方法。
$foo->bars->lists('id');
将为您提供一组 foo 的栏 ID。
可用时间:
- Illuminate\Database\Eloquent\Builder::列表
- Illuminate\Database\Query\Builder::列表
- Illuminate\Support\Collection::列表
一些额外的建议:
为了return你想要的格式的数据,使用转换器可能会很好,比如来自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'),
];
}
}
听起来您想要在 foo 查询中使用 GROUP CONCAT,为此您需要使用 DB::raw()。
还有 lists() 方法,例如
public function barsIds() {
return $this->belongsToMany('bar','foos_bars')
->lists('id');
}
使用transformers/presenters这种东西,分形是你可以考虑的一种。但是,您可以使用 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
的集合时,记得eager loadbars
关系,否则您将遇到 N+1 查询问题。