我有一个简单的数据库设置:用户,组,页面 - 每个都是多对多。 见图:http://i.imgur.com/oFVsniH.png
现在我有一个可变的用户ID($ id),有了这个,我希望得到一个用户有权访问的页面列表,因为它在所有表上是多对多的。
我已经设置了我的主要模型:
class User extends Eloquent {
protected $table = 'ssms_users';
public function groups()
{
return $this->belongsToMany('Group', 'ssms_groups_users', 'user_id','group_id');
}
}
class Group extends Eloquent {
protected $table = 'ssms_groups';
public function users()
{
return $this->belongsToMany('User', 'ssms_groups_users', 'user_id','group_id');
}
public function pages()
{
return $this->belongsToMany('Page', 'ssms_groups_pages', 'group_id','page_id');
}
}
class Page extends Eloquent {
protected $table = 'ssms_pages';
public function groups()
{
return $this->belongsToMany('Group', 'ssms_groups_pages', 'group_id','page_id');
}
}
我可以通过以下方式获取用户所属的组:
User::with('groups')->first(); // just the first user for now
然而,我完全迷失了如何通过一个查询获取用户可以访问的页面(明显地)?
我相信SQL会是这样的:
select DISTINCT GP.page_id
from GroupUser GU
join GroupPage GP on GU.group_id = GP.group_id
where GU.user_id = $id
有人可以帮忙吗?
由于
答案 0 :(得分:0)
你之前尝试过这样的事吗?
$pages = User::with(array('groups', 'groups.pages'))->get();
急切加载可能是您问题的解决方案:eager loading
答案 1 :(得分:0)
<强> TL; DR:强>
fetchAll
类中的MyCollection
方法可以完成工作。只需致电fetchAll($user->groups, 'pages');
好的,假设您设法加载数据(应该通过急切加载来完成,如其他答案中所述),您应该遍历Group
所拥有的User
,然后遍历其Page
并将其添加到新集合中。由于我已经遇到过这个问题,我认为简单地扩展Laravel自己的Collection
类并添加一个通用的方法来做到这一点会更容易。
为了简单起见,只需创建一个app/libraries
文件夹,然后将其添加到composer.json
下的autoload -> classmap
,这将为我们加载课程。然后将扩展的Collection
类放在文件夹中。
应用/库/ MyCollection.php 强>
use Illuminate\Database\Eloquent\Collection as IlluminateCollection;
class MyCollection extends IlluminateCollection {
public function fetchAll($allProps, &$newCollection = null) {
$allProps = explode('.', $allProps);
$curProp = array_shift($allProps);
// If this is the initial call, $newCollection should most likely be
// null and we'll have to instantiate it here
if ($newCollection === null) {
$newCollection = new self();
}
if (count($allProps) === 0) {
// If this is the last property we want, then do gather it, checking
// for duplicates using the model's key
foreach ($this as $item) {
foreach ($item->$curProp as $prop) {
if (! $newCollection->contains($prop->getKey())) {
$newCollection->push($prop);
}
}
}
} else {
// If we do have nested properties to gather, then pass we do it
// recursively, passing the $newCollection object by reference
foreach ($this as $item) {
foreach ($item->$curProp as $prop) {
static::make($prop)->fetchAll(implode('.', $allProps), $newCollection);
}
}
}
return $newCollection;
}
}
但是,为了确保您的模型将使用此类而不是原始Illuminate\Database\Eloquent\Collection
,您必须创建一个基础模型,您将从中扩展所有模型,并覆盖{ {1}}方法。
应用/模型/ BaseModel.php 强>
newCollection
不要忘记,您的模型现在应该abstract class BaseModel extends Eloquent {
public function newCollection(array $models = array()) {
return new MyCollection($models);
}
}
,而不是extend BaseModel
。完成所有操作后,要获取所有Eloquent
个User
,仅拥有其ID,请执行以下操作:
Page