Как получить задачи пользователя в myProjects с помощью Eloquent в Laravel - PullRequest
0 голосов
/ 17 июня 2020

Я новичок в 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, role = admin
id = 2, user_id = 2, project_id = 1, role = employee
id = 3, user_id = 2, project_id = 2, role = admin
id = 4, user_id = 1, project_id = 3, role = 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.
    }
}

А вот домашний контроллер (мне нужна функция allProjects() в HomeController для некоторых других функций класса):

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;
    }
}

1 Ответ

1 голос
/ 18 июня 2020

Прежде всего, я думаю, вам следует настроить joinedProjects как отношение многие-ко-многим , тогда доступ к нему будет более простым.

// 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 и l oop через итоговый проект похож на настроенный вами для l oop. Или в качестве альтернативы вы можете использовать метод класса коллекции ' 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;
    }
}

Вот некоторые дополнительные ссылки на уникальный метод, который я использую в коде, и ленивую загрузку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...