Laravel: How to get records by using the pivot table?

孤者浪人 提交于 2019-12-13 03:25:23

问题


I have a many to many relationship between task and users, I am trying to get archived tasks, an archived task is:

  • A task that is_done = 1
  • A task that was done yesterday or before, not including tasks finished today

  • A user can only see archived tasks that he created or he was assigned to, if a user is assigned to a task, his id is stored in the pivot table

  • For reasons outside the scope of the question, I can only get to users by using the pivot table as shown in Task.php below.

Task.php model

public function taskUsers()
{
    return $this->hasMany('App\Models\Tasks\UserTask')->where('role',1);
}

UserTask.php model contains nothing, an empty model

class UserTask extends BaseModel { }

Migrations

class CreateTasksTable extends Migration
{
    protected $table = 'tasks';
    protected $app_table = true;


    public function up()
    {
        Schema::create($this->getTable(), function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->dateTime('submit_date');
            $table->dateTime('closed_date')->nullable();
            $table->dateTime('due_date')->nullable();
            $table->tinyInteger('is_done')->nullable()->default(0);
            $table->integer('domain_id')->unsigned()->nullable();
            $table->foreign('domain_id')->references('id')
                ->on(self::getTableName('domains'))->onDelete('cascade');
            $table->bigInteger('created_by')->unsigned()->nullable();
            $table->foreign('created_by')->references('id')
                ->on(self::getTableName('auth_users', false))->onDelete('cascade');
            $table->bigInteger('closed_by')->unsigned()->nullable();
            $table->foreign('closed_by')->references('id')
                ->on(self::getTableName('auth_users', false))->onDelete('cascade');
            $table->timestamps();
        });

    }
    public function down()
    {
        Schema::drop($this->getTable());
    }
}

and

class CreateTaskUsersTable extends Migration
{
    protected $table = 'task_user';
    protected $app_table = true;
    public function up()
    {
        Schema::create($this->getTable(), function (Blueprint $table) {
            $table->increments('id');
            $table->integer('task_id')->unsigned()->nullable();
            $table->foreign('task_id')->references('id')
                ->on(self::getTableName('tasks'))
                ->onDelete('cascade');
            $table->bigInteger('user_id')->unsigned()->nullable();
            $table->foreign('user_id')->references('id')
                ->on(self::getTableName('auth_users', false))
                ->onDelete('cascade');
            $table->integer('role');
        });
    }
    public function down()
    {
        Schema::drop($this->getTable());
    }
}

The actual tables respectively

and

My code:

The helper is below

    public static function getArchived($domainId, $userId)
    {
        Task::where("domain_id", $domainId)
            ->where("is_done", 1)
            ->where("closed_date", '<', Carbon::today()->startOfDay())

            ->where(function ($query) use ($userId) {
                $query->whereHas('taskUsers', function ($query) use ($userId) {
                    $query->where('user_id', $userId);
                });
            })
            ->orWhere(function ($query) use ($userId) {
                $query->where('created_by', $userId);
            })
->get();
    }

The Action:

public function execute()
{
    $domainId = $this->request->get('domain_id');
    $userId = \Auth::id();
    $tasks = TasksHelper::getArchived($domainId,$userId);
    return $this->response->statusOk(['tasks' => $tasks]);
}

I just get a status OK, no result, tasks array is null, although my code seems to be correct and the tables contain 1 record which should have been returned.


回答1:


You're missing the return statement in your getArchived method. Also, the orWhere condition seems out of place. You must use parameter grouping if you need the 1st three conditions to apply as well. Otherwise the query reads (1 && 2 && 3 && 4) || 5 whereas you need 1 && 2 && 3 && (4 || 5).

public static function getArchived($domainId, $userId)
{
    return Task::where("domain_id", $domainId)
        ->where("is_done", 1)
        ->where("closed_date", '<', Carbon::today()->startOfDay())

        ->where(function ($query) use ($userId) {
            $query->whereHas('taskUsers', function ($query) use ($userId) {
                $query->where('user_id', $userId);
            })->orWhere('created_by', $userId);
        })->get();
}


来源:https://stackoverflow.com/questions/53464283/laravel-how-to-get-records-by-using-the-pivot-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!