Php Laravel雄辩的where doesnthave()文档让我困惑

Php Laravel雄辩的where doesnthave()文档让我困惑,php,laravel,eloquent,Php,Laravel,Eloquent,参考查询 使用illumb\Database\elount\Builder; $posts=App\Post::whereDoesntHave('comments.author',函数(Builder$query){ $query->where('banked',0); })->get(); 被描述为“从未被禁止的作者那里检索所有带有评论的帖子”。这对我来说似乎是不正确的,因为这似乎意味着,如果一篇文章有一条来自被禁作者的评论,另一条来自非被禁作者的评论,那么该文章将在最终的收集中——毕竟,它

参考查询

使用illumb\Database\elount\Builder;
$posts=App\Post::whereDoesntHave('comments.author',函数(Builder$query){
$query->where('banked',0);
})->get();
被描述为“从未被禁止的作者那里检索所有带有评论的帖子”。这对我来说似乎是不正确的,因为这似乎意味着,如果一篇文章有一条来自被禁作者的评论,另一条来自非被禁作者的评论,那么该文章将在最终的收集中——毕竟,它有来自未被禁作者的评论

            SELECT 
                *
            FROM
                `comments`
            WHERE
                `posts`.`id` = `comments`.`postId`
                    AND EXISTS( SELECT 
                        *
                    FROM
                        `authors`
                    WHERE
                        `comments`.`authorId` = `authors`.`id`
                            AND `banned` = 0)
事实上,这样的帖子不会被收录在收藏中,因为存在一个被禁止的作者的评论,不管该帖子可能有其他评论

更准确的说法是“检索所有有评论的帖子,其中没有一篇来自被禁作者”


我弄错什么了吗?

事实上,两者都不正确。可以这样说:

检索所有没有评论或所有评论都来自被禁止作者的帖子 我创造了

从此类调用生成的sql如下所示:

SELECT 
    *
FROM
    `posts`
WHERE
    NOT EXISTS( SELECT 
            *
        FROM
            `comments`
        WHERE
            `posts`.`id` = `comments`.`postId`
                AND EXISTS( SELECT 
                    *
                FROM
                    `authors`
                WHERE
                    `comments`.`authorId` = `authors`.`id`
                        AND `banned` = 0))
分解这一点,内部查询说“找到与每个帖子相关的所有评论,这些评论是由一位未被禁止的作者撰写的。”

            SELECT 
                *
            FROM
                `comments`
            WHERE
                `posts`.`id` = `comments`.`postId`
                    AND EXISTS( SELECT 
                        *
                    FROM
                        `authors`
                    WHERE
                        `comments`.`authorId` = `authors`.`id`
                            AND `banned` = 0)
然后,顶级查询说,“现在,给我上面的子查询没有返回行的所有帖子”

也就是说,所有的作者都被禁止,或者根本没有评论

  SELECT 
        *
    FROM
        `posts`
    WHERE
        NOT EXISTS(
          {.. sub query above here }
       )

如果你想自己测试一下, 型号:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Post extends Model
{
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class, 'postId');
    }
}


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Comment extends Model
{
    public function author(): HasOne
    {
        return $this->hasOne(Author::class, 'id', 'authorId');
    }

}

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{

}
内容sql:

# crate a post
INSERT INTO `posts` (`id`) VALUES ('1');




# add a banned and not banned author 
INSERT INTO `authors` (`name`, `banned`) VALUES ('Jack', '0');
INSERT INTO `authors` (`name`, `banned`) VALUES ('Jill', '1');


# add a comment from a banned and not banned author 
INSERT INTO `comments` (`postId`, `authorId`, `content`) VALUES ('1', '1', 'a');
INSERT INTO `comments` (`postId`, `authorId`, `content`) VALUES ('1', '2', 'b');
现在运行代码:

$post = \App\Models\Post::whereDoesntHave('comments.author', function ( $query) {
     $query->where('banned', 0);
})->get();
您将返回0个结果

现在运行此命令以使两位作者都不被禁止:

UPDATE `authors` SET `banned`='0';
您仍将返回0个结果

现在运行此命令以禁止两位作者:

UPDATE `authors` SET `banned`='1';
您现在将返回1个结果

现在运行此命令,使两位作者不再被禁止,而是删除他们的评论:

UPDATE `authors` SET `banned`='0';
DELETE FROM `comments`;
您现在将返回1个结果


这证明了实际行为是“检索所有没有评论的帖子,或者所有评论都来自被禁止的作者”“

不仅仅是你,除非我看错了,否则我会觉得很奇怪。。。这些文件对PRs开放。。。但对我来说,这个例子可以理解为,我希望所有的帖子都不会有来自作者的任何评论,这些评论都不会被禁止。。。老实说,我觉得我写这篇文章时把自己搞糊涂了,所以我想我想说的是,一篇文章必须只有被禁止发表评论的作者才能发表评论…@lagbox,是的,或者根本没有评论,按照下面的要求和确认,提交了一份公关地址。不错。嗯,这是我最初的印象,但我把我的测试用例搞砸了,结果我对它的理解被错误地修改了。哈哈。不错!嗯,我想这可能会缩短为“检索所有没有被禁止作者评论的帖子”?因为这将抓住没有评论的帖子和有评论但不是来自被禁作者的帖子的情况。尽管我认为您的版本更适合文档,因为它非常清楚。comment有一个作者关系:这不意味着commentId在authors表中吗。要使authorId(author_id)在注释表中是外来的,应该有属于作者的注释。hasOne和belongsTo之间的区别在于设置外键的位置。对吗?