【问题标题】:How to efficiently select only the IDs of a Belongs To Many relationship in Eloquent?如何在 Eloquent 中有效地仅选择 Belongs To Many 关系的 ID?
【发布时间】:2014-07-15 14:28:32
【问题描述】:

如果我有一个 Users 表和 Tags 表,以及 Belongs To Many 关系的数据透视表,我如何使用 Eloquent 仅加载关系的 ID?

如果我执行User::with('tags'),这将在数据透视表上进行连接,同时在标签表上进行连接。但是,这在我的情况下是不必要且低效的,因为我希望能够只从数据透视表中选择标签的 ID,而不是标签表中的其他列。换句话说,我只希望它从 Users 到 Users_Tags 进行一次联接。

谢谢。

【问题讨论】:

  • 您想在多个模型上急切加载这些 ID?
  • 是的,我想对多个模型(集合)或单个模型执行此操作。谢谢。
  • 如果不加入数据透视表,则无法获取相关标签,因为关系存储在数据透视表中。
  • @WereWolf-TheAlpha 是的,我想将数据透视表 (Users_Tags) 与用户表连接起来。不是带有数据透视表的标签表。
  • 要急切加载这种关系,您需要单独的数据透视表模型。虽然这应该不是问题,但您最终可能会得到不一致的结果,因为可能会删除在数据透视表上仍有行的标签。

标签: php mysql laravel laravel-4 eloquent


【解决方案1】:

好的,因为@WereWolf 的建议不正确(第一个会导致错误,如果有自定义键,第三个可能是错误的),这里是你的选项,不获取相关模型。

从最明显的开始:

// for single model:
$user = User::first();
$user->tags()->allRelatedIds(); // select id from related table -> join

这是您可以使用的,但它不是答案,因为您想急切加载这些 ID。

话虽如此,您需要为数据透视表创建另一个模型:

// UserTag model
protected $table = 'user_tag';

// this is not required, just to make it read-only
public static function boot()
{
   parent::boot();
   static::saving(function() {
     return false;
   }
}

// User model
public function tagsPivot()
{
   return $this->hasMany('UserTag')->select('tag_id', 'user_id'); // appropriate keys here
}

public function getTagsIds()
{
   return $this->tagsPivot->lists('tag_id');
}

// then you can do this:
$users = User::with('tagsPivot')->get(); // no join, select category_id from pivot table

foreach ($users as $user)
{
   $user->getTagsIds();
}

.


您还可以根据自己的喜好对 User 模型进行一些更改:

// to be able to do this:
$users = User::with('tagsIds')->get();

foreach ($users as $user)
{
   $user->tagsIds;
}

// User model
public function tagsIds()
{
   return $this->hasMany('UserTag')->select('tag_id', 'user_id'); // appropriate keys here
}

public function getTagsIdsAttribute()
{
   if ( ! array_key_exists('tagsIds', $this->relations)) $this->load('tagsIds');

   return $this->getRelation('tagsIds')->lists('tag_id');
}

【讨论】:

  • 太完美了,非常感谢您的努力!我一定会用这个!
  • getRelatedIds最近更名为allRelatedIds
【解决方案2】:

试一试(未测试):

$user = User::query();
$ids = $user->getRelation('tags')->getRelatedIds();

或者可能是这样的(但在tags 通话期间做了一些额外的查询):

$user = User::find(1);
$ids = $user->tags->fetch('id');

更新:(另一种方式)

$user = User::find(1);
$ids = array_fetch(DB::table($user->joiningTable('tag'))
                       ->where($user->getForeignKey(), $user->getKey())
                       ->get(), 'tag_id');

【讨论】:

  • 是的,这就是我的建议($user->tags() 当然会这样做,不需要调用查询,而且你不能调用该查询的关系;)),因为,就像在我对这个问题的评论,仅查询数据透视表可能存在不一致。
  • 不知道 getRelatedIds() 方法。不幸的是,getRelation() 方法不允许对 User 进行任何约束,因此它仅适用于整个 User 表。第二种方法有效,但仍然对标签表进行冗余查询。我还假设我正在尝试做的事情不能用于收藏?你会认为这将内置在 Eloquent 中,因为仅获取相关 ID 是相当常见的。
  • 是的,第二个会做额外的查询,如果我们能像built-in 功能一样轻松地做类似的事情会更好,也许有一种方法,但还没有公开,祝你好运:-) .
  • @WereWolf-TheAlpha 感谢您抽出宝贵时间!我会继续挖掘。
  • 不客气,如果你发现了什么,请不要忘记分享,希望你能想出一些有趣的东西:-)
猜你喜欢
  • 2019-02-21
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-13
  • 1970-01-01
  • 2012-08-11
相关资源
最近更新 更多