【发布时间】:2015-07-03 03:40:29
【问题描述】:
我正在开发一个社交网络,用户可以在其中关注并拥有关注者。追随者和被关注的用户使用学说实现为集合。我希望能够在不加载整个集合的情况下过滤这些集合,因为学说 2.5 这应该可以使用标准和匹配来实现,我想要做的过滤应该很简单,我想隐藏被阻止的用户。假设用户 A 屏蔽了用户 B,而用户 B 在用户 C 的关注者列表中,那么用户 B 应该被隐藏,这样用户 A 就无法在用户 C 的关注者列表中看到它。
这是我使用标准的第一个方法:
public function getFollowerUsers(User $user, $page){
$filter_ids = array_merge((array)$user->getBlockedUserIds(), (array)$user->getBlockingUserIds());
$criteria = Criteria::create()
->where(Criteria::expr()->notIn('id', $filter_ids))
->setFirstResult($page * User::USERS_PER_PAGE)
->setMaxResults(User::USERS_PER_PAGE);
return $this->followers->matching($criteria);
}
这应该可以,但是正在执行的 SQL 如下:
SELECT te.id AS id, te.user_login AS user_login, te.user_pass AS user_pass, te.user_nicename AS user_nicename, te.user_email AS user_email, te.user_url AS user_url, te.user_registered AS user_registered, te.user_activation_key AS user_activation_key, te.user_status AS user_status, te.display_name AS display_name FROM users te JOIN followers t ON t.following_user_id = te.id WHERE t.user_id = ? AND te.ids = ?' with params ["1", ["7","37"]]
请注意,我将Criteria::expr()->notIn('id', $filter_ids) 更改为Criteria::expr()->notIn('ids', $filter_ids),所以我可以看到正在执行的SQL,这里重要的是学说使用te.ids = 什么时候应该使用te.ids NOT LIKE,它不无论我使用哪个运算符,原则总是将其更改为 =,所以它似乎只适用于 Criteria::expr()->eq('id', 1),我做错了什么还是这是一个错误?如果我将由学说生成的 sql 更改为 not in 它可以正常工作!
我当前的解决方案是创建一个服务,因此实体对 EntityManager 一无所知:
class UserService {
/* $em EntityManager */
private $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function getFollowingUsers(\models\Users $user, \models\Users $user_querying, $page, $users_per_page){
$filter_ids = implode(",", array_merge((array)$user_querying->getBlockedUserIds(), (array)$user_querying->getBlockingUserIds()));
//var_dump($filter_ids);
$user_following = $this->em->createQuery("SELECT u,f FROM \models\WpUsers u JOIN u.following f WHERE u.id = :user_id AND f.id NOT IN($filter_ids)")
->setParameter('user_id', $user->getId())
->setFirstResult($page * $users_per_page)
->setMaxResults($users_per_page)
->getResult();
return $user_following[0]->getFollowingUsers();
}
}
这样称呼它:
$service = new \services\UserService($this->em);
$following_users = $service->getFollowingUsers($user_list, $user);
这工作正常,似乎我没有加载整个集合进行过滤,但我希望能够以另一种方式进行,因为它更清晰、更优雅
【问题讨论】:
标签: php doctrine-orm many-to-many