Laravel 5.6.17 - 关系查询与条件

时间:2018-04-20 23:16:37

标签: php laravel

我正在使用Laravel Framework 5.6.17。我有2个模型通过many to many与数据透视表链接。

相关模型QuestionTagtag_question表相关联。

问题可以包含许多标签,标签可以包含许多问题。

模型看起来像这样:

class Question extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title', 'body',
    ];

    /**
     * @var bool
     */
    public $timestamps = true;

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function tags()
    {
        return $this->belongsToMany(Tag::class, 'tag_question');
    }
}

class CreateQuestionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('questions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->longText('body');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('questions');
    }
}
class Tag extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'tag',
    ];

    /**
     * @var bool
     */
    public $timestamps = true;

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function questions()
    {
        return $this->belongsToMany(Question::class, 'tag_question');
    }
}

class CreateTagsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->increments('id');
            $table->string('tag');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tags');
    }
}

枢轴看起来像这样:

class CreateTagQuestionTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tag_question', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('question_id');
            $table->integer('tag_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tag_question');
    }
}

没有什么不寻常的,相当直接的东西。

问题

我尝试按标签过滤问题,并且我使用以下查询执行此操作:

$q = $question
    ->with(['tags' => function($query) use($request) {
        $query->where('tags.tag', '=',  $request->query('tag'));
    }])
    ->orderBy('created_at', 'DESC')
    ->paginate(10);

但是,所有问题都会被检索到,无论他们拥有什么标签,或者他们是否有任何标签(标签不是强制性的,尽管这不重要)。

请注意,我没有收到错误,一切正常,除非它检索到意外结果。

到目前为止我尝试了什么

几乎我能想到的任何事情。

运行的查询如下:

select * from `users` where `id` = '1' limit 1

select count(*) as aggregate from `questions`

select * from `questions` order by `created_at` desc limit 10 offset 0

select `tags`.*, `tag_question`.`question_id` as `pivot_question_id`, `tag_question`.`tag_id` as `pivot_tag_id` from `tags` inner join `tag_question` on `tags`.`id` = `tag_question`.`tag_id` where `tag_question`.`question_id` in ('1', '2', '3', '4', '5', '52', '53', '54', '55', '56') and `tag` = 'test'

1 个答案:

答案 0 :(得分:3)

您需要使用->whereHas()代替with()

$q = $question
    ->whereHas('tags', function($query) use($request) {
        $query->where('tags.tag', '=',  $request->query('tag'));
    })
    ->orderBy('created_at', 'DESC')
    ->paginate(10);

但是,这不会急于加载标签。因此,如果您还希望加载标记,则仍需要添加->with('tags')