如何获取多对多关系的id?

How to get the ids of many to many relation?

我有两个模型,FooBar: ​​​​​

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 查询问题。