我有一个Store
实体,我可以使用getNotifications()
方法从中获取为商店设置的所有通知。
我在Notification
实体中添加了一个字段,并将其命名为“isRead
”。它是布尔值。
现在,我只想从Store
实体获取未读通知。
我应该在哪里放置方法getUnreadNotifications()
?
UPDATE
更清楚一点:如果我有名为“My Awesome Store”的商店并且该商店有10个通知,我想在页面上显示商店本身的信息以及所有10个通知。这些通知必须由字段isRead过滤,因此仅显示isRead = 0
的通知。
所以我想从数据库中只选择这些通知,而不是所有通知,然后过滤掉那些已经读过的通知。
控制器的代码:
/**
* @Route("store/{id}", name="showStore")
* @Template()
* @param $id
* @return array
*/
public function showAction($id)
{
// Get store info
$store = $this->getDoctrine()->getRepository('AppBundle:Store')->find($id);
...
// Get Orders
$orders = $this->getDoctrine()->getRepository('AppBundle:Order')->findByChannel($store->getId());
...
// Check if the current user is the owner of the store
if (true === $isOwner) {
...
/**
* HERE IS THE PROBLEM
* but I think I should use the same solution
* I used to get Orders: a new query using the
* Notifications repository.
*/
$return['notifications'] = $store->getUnreadNotifications();
...
}
return $return;
}
Store
实体的代码:
/**
* Stores
*
* @ORM\Table(name="stores")
* @ORM\Entity(repositoryClass="\AppBundle\Entity\StoreRepository")
* @ORM\HasLifecycleCallbacks
*/
class Store
{
...
/**
* @ORM\OneToMany(targetEntity="NotificationStore", mappedBy="forStore")
*/
private $notifications;
public function __construct()
{
...
$this->notifications = new ArrayCollection();
...
}
...
/**
* @return ArrayCollection
*/
public function getNotifications()
{
return $this->notifications;
}
...
}
通知实体的代码:
/**
* @ORM\Entity
*/
abstract class Notification
{
...
/**
* @var boolean
*
* @ORM\Column(name="isRead", type="boolean", nullable=false)
*/
private $isRead = false;
...
public function setIsRead($isRead = false)
{
$this->isRead = $isRead;
return $this;
}
public function isRead()
{
return $this->isRead;
}
}
NotificationStore实体的代码:
/**
* @ORM\Entity
* @ORM\Table(name="notifications_stores")
*/
class NotificationStore extends Notification
{
/**
* @var integer
*
* @ORM\ManyToOne(targetEntity="Store", inversedBy="notifications")
* @ORM\JoinColumn(name="for_store", referencedColumnName="id")
*/
protected $forStore;
public function setForStore($forStore)
{
$this->forStore = $forStore;
return $this;
}
public function getForStore()
{
return $this->code;
}
}
答案 0 :(得分:1)
有两种方法可以解决这种情况:
创建一个存储库StoreRepository
并通过使用过滤器“加入”Store
来检索notifications
实体,该过滤器会过滤通知,即:
class StoreRepository extends EntityRepository {
public function findStoreWithNotifications($id) {
return $this->createQueryBuilder('store')
->addSelect('notification')
->leftJoin('store.notifications', 'notification', 'WITH', 'notification.isRead IS false')
->where('store.id = :storeId')
->setParameter('storeId' => $id)
->getQuery()
->getSingleResult()
;
}
}
调用findStoreWithNotifications
方法将返回Store
实体并加入所有Notifications
,按读取状态进行过滤。
在getUnreadNotifications
实体中创建Store
方法,并使用Doctrine Criteria过滤通知收集。如果您选择使用此方法,则应该非常谨慎,因为每次调用getUnreadNotifications
方法时,都会触发对数据库的 new 查询。
您选择哪种方法取决于您的情况。
根据评论更新:
在您的控制器中,您有:
$store = $this->getDoctrine()->getRepository('AppBundle:Store')->find($id);
使用我的目标代码,这一行将成为:
$store = $this->getDoctrine()->getRepository('AppBundle:Store')->findStoreWithNotifications($id);
然后在你的$return
变量中,你只会这样做:
$return['notifications'] = $store->getNotifications();
由于StoreRepository
中的加入,因此只会为您提供已过滤的未读通知。
答案 1 :(得分:0)
我会在Store
实体中添加/**
* Stores
*
* @ORM\Table(name="stores")
* @ORM\Entity(repositoryClass="\AppBundle\Entity\StoreRepository")
* @ORM\HasLifecycleCallbacks
*/
class Store
{
// ...
/**
* @return ArrayCollection|Notification[]
*/
public function getUnreadNotifications()
{
return $this->notifications->filter(function(Notification $notification) {
return !$notification->isRead()
});
}
// ...
}
方法,如下所示:
(defn validate-email
[email]
(let [pattern #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"]
(and (string? email) (re-matches pattern email))))
答案 2 :(得分:0)
你可以尝试这样的事情:
// YourBundle/Entity/StoreRepository.php
/.../
class StoreRepository extends EntityRepository
{
public function findByUnreadNotifications($id)
{
$query = $this->createQueryBuilder('s')
->where('s.id = :idStore')
->setParameter('idStore', $id)
->leftJoin('s.notifications', 'n')
->andwhere('n.isRead = :isRead')
->setParameter('isRead', false)
->getQuery()
;
return $query->getResult();
}
}
在你的控制器中:
/.../
$return['notifications'] = $this->getDoctrine()->getRepository('AppBundle:Store')->findByUnreadNotifications($id);
/.../
答案 3 :(得分:0)
最后我将方法添加到NotificationRepository
类。
这会产生一个新的查询,但是当通知从通知实体获取时保持代码更清晰,而不会造成混淆。
感谢您的回复! :)