【问题标题】:How to Get User's myProjects' Tasks with Eloquent in Laravel如何在 Laravel 中使用 Eloquent 获取用户的 myProjects 任务
【发布时间】:2020-06-17 20:52:31
【问题描述】:

我是 Laravel 和 Eloquent 的新手。 在我的应用程序中,我想检索当前用户和其他项目成员的任务并在视图中显示它们。 这是我建立的数据库关系:

users (id)

projects(id, user_id)

user_project(id、user_id、project_id、角色)

tasks (id, user_id, project_id)

(我已经在迁移中定义了所需的外键)

为了解释这种关系,每个项目都有一个用户(创建项目的人)。但是在user_project 表中,用户也可以分配到其他项目,并且在那里定义他们的角色。例如:有两个用户
id=1
id=2

还有三个项目
id=1,user_id=1
id=2,user_id=2
id=3,user_id=1

user_project 关系:
id=1,user_id=1,project_id=1,角色=admin
id=2,user_id=2,project_id=1,角色=employee
id=3,user_id=2,project_id=2,角色=admin
id=4,user_id=1,project_id=3,角色=admin

还有四个任务
id=1,user_id=1,project_id=1
id=2,user_id=2,project_id=1
id=3,user_id=1,project_id=2
id=4,user_id=1,project_id=3

我希望用户 id=2 能够看到 project_id=1 的任务,因为他作为员工被邀请到该项目以及 project_id=2 的任务,因为他创建了该项目。当然,用户应该看不到 project_id=3 的任务,因为他不是会员。那么,最简​​洁的方法是什么?

这是我定义的模型:

class User extends Authenticatable
{
    public function projects(){
        return $this->hasMany(Project::class);
    }
    public function tasks(){
        return $this->hasMany(Task::class);
    }
    public function joinedProjects()
    {
        return $this->hasMany(ProjectUser::class);
    }
}

class Project extends Model
{
    public function tasks(){
        return $this->hasMany(Task::class);
    }
    public function users(){
        return $this->hasMany(User::class);
    }
}

class ProjectUser extends Model
{
}

class Task extends Model
{
    public function projects(){
        return $this->belongsTo(Project::class);
    }
    public function users(){
        return $this->belongsTo(User::class);
    }
}

这是我尝试检索项目成员任务的方式(我正在寻找的理想方式是:$tasks = $user->joinedProjects->tasks 但我不知道该怎么做,所以这就是我的方式我目前正在尝试完成这项工作):

class TasksController extends Controller
{
    public function index()
    {
        $user = Auth()->user();
        //I guess there are better ways to retrieve projects, but:
        $projects = app('App\Http\Controllers\HomeController')->allProjects($user);
        foreach($projects as $project){
            $tasks[] = Task::where('project_id', $project->id);
        }
        return view('tasks.index', compact(['tasks','user']));
        //gives error: Property [id] does not exist on the Eloquent builder instance
        //when I'm trying to get $task->id in a foreach loop.
    }
}

这是 home 控制器(我需要 HomeController 中的 allProjects() 函数来实现其他一些类函数):

class HomeController extends Controller
{
    function allProjects($user){
        $projects = $user->projects;
        $otherProjects = \App\ProjectUser::where('user_id',$user->id)->get();
        foreach ($otherProjects as $project){
            $projects[] = \App\Project::find($project->project_id);
        }
        return $projects;
    }
}

【问题讨论】:

  • 为什么不只用$user->projects( )->get( )访问它?
  • 当我使用它时,它只提供用户创建的项目。将错过邀请用户参与的其他项目。

标签: laravel eloquent many-to-many


【解决方案1】:

首先,我认为您应该将joinedProjects 设置为many-to-many relationship,这样访问它会感觉更直接。

// in User model
public function joinedProjects()
{
    // i'm assuming you want to always have access to the role property
    return $this->belongsToMany(Project::class, 'user_project')->withPivot('role');
}

// in Project model
public function memberUsers()
{
    return $this->belongsToMany(User::class, 'user_project')->withPivot('role');
}

有了这个关系,你应该可以调用$user->joinedProjects来获取用户加入的项目列表。

要获得任务,当然可以调用joinedProjects 关系并像你设置的for循环一样循环遍历生成的项目。或者,您也可以使用集合类的pluck 方法。

class TasksController extends Controller
{
    public function index()
    {
        // here I put load to eager load the project and task
        $user = Auth()->user()->load('joinedProjects.tasks');

        // OPTION 1: you can loop to get the tasks
        $tasks = collect();
        foreach($user->joinedProjects as $project){
            $tasks = $tasks->merge($project->tasks);
        }

        // OPTION 2: or use pluck (must be eager loaded to work)
        $tasks = $user->joinedProjects->pluck('tasks');

        // $tasks should be unique here, but if it is not you can call the unique method of collection
        $tasks = $tasks->unique('id');

        return view('tasks.index', compact(['tasks','user']));
    }
}

您共享的HomeController 也可以通过新关系进行简化

class HomeController extends Controller
{
    function allProjects($user){
        // here i'm assuming user automatically joins a project when they create it
        $projects = $user->joinedProjects;

        return $projects;
    }
}

这是我在代码中使用的unique 方法和lazy eager loading 的一些额外参考

【讨论】:

  • 哦,非常感谢。有用。 Auth()->user()->load('joinedProjects.tasks') 节省了大量时间!我还没有检查那个独特的方法,但我稍后会检查它。再次感谢。
猜你喜欢
  • 2014-11-04
  • 2021-08-13
  • 1970-01-01
  • 2020-11-07
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多