Symfony 单一位置限制对条令实体的访问

Symfony 单一位置限制对条令实体的访问,symfony,doctrine-orm,Symfony,Doctrine Orm,我刚刚开始使用Doctrine并建立了一个简单的博客项目。我的要求之一是,在发布日期之前,任何人都不能看到博客文章(为了简单起见,跳过编辑界面) 在我看来,使用自定义存储库显然是可行的。让我们通过以下方式扩展find方法: public function find($id, $lockMode = null, $lockVersion = null) { /** @var Post $post */ $post = parent::find($id, $lockMode, $lo

我刚刚开始使用Doctrine并建立了一个简单的博客项目。我的要求之一是,在发布日期之前,任何人都不能看到博客文章(为了简单起见,跳过编辑界面)

在我看来,使用自定义存储库显然是可行的。让我们通过以下方式扩展
find
方法:

public function find($id, $lockMode = null, $lockVersion = null)
{
    /** @var Post $post */
    $post = parent::find($id, $lockMode, $lockVersion);
    if($post->getCreatedAt() > new \DateTime()) {
        return null;
    }

    return $post;
}
这将限制对显示单个
Post
实体的页面的访问。对于概述页面,可以使用自定义方法执行相同操作:

public function findForOverview()
{
    $query = $this->createQueryBuilder('p')
        ->where('p.createdAt < CURRENT_TIMESTAMP()')
        ->orderBy('p.createdAt', 'DESC')
        ->getQuery();

    return $query->getResult();
}
公共函数findForOverview()
{
$query=$this->createQueryBuilder('p')
->其中('p.createdAtorderBy('p.createdAt','DESC')
->getQuery();
返回$query->getResult();
}
因此,即使对于这个简单的需求,我已经编写了两个自定义方法。如果我继续处理我的项目,可能会出现其他限制,并且可能会出现加载该实体的其他方法。就我所见,对于每种情况,我都必须为所有的门禁系统实现逻辑


没有比这更简单的方法了吗?我正在考虑一种类似于注释或“实体加载侦听器”的方法,它可以简化为所有此类检查编写一个入口点的过程,从而不可能忘记此类检查……

此类限制通常通过使用in-doctor机制来实现。此过滤器的实现在DQL的较低级别上工作,并允许您对正在构造的SQL查询应用修改。在您的情况下,它可能如下所示:

namespace App\ORM\Filter;

use App\Entity\Post;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;

class PostVisibilityFilter extends SQLFilter
{
    /**
     * Gets the SQL query part to add to a query.
     *
     * @param ClassMetadata $targetEntity
     * @param string $targetTableAlias
     * @return string The constraint SQL if there is available, empty string otherwise
     */
    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string
    {
        if ($targetEntity->name !== Post::class) {
            return '';
        }
        return sprintf('%s.%s >= now()', $targetTableAlias, $targetEntity->getColumnName('createdAt'));
    }
}

我也在写答案。这似乎是你的解决方案:)谢谢,这看起来是一个完美的解决方案!