I have a table post
with a many-to-many relationship with the tag
and product
tables.
post
\$\rightarrow\$tag
post
\$\rightarrow\$product
How can I make this faster?
For example, if I have post, I can get similar posts similar by tags and products:
Post.php
<?php
namespace Ranger\AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Post
*
* @ORM\Table(name="post")
* @ORM\Entity(repositoryClass="Ranger\AppBundle\Entity\PostRepository")
* @ORM\HasLifecycleCallbacks()
*/
class Post
{
CONST SHOW_PER_PAGE = 3;
CONST SIMILAR_POST_MAX = 3;
/**
* @var string
*
* @ORM\Column(name="title", type="text", nullable=false)
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="content", type="text", nullable=true)
*/
private $content;
/**
* @var boolean
*
* @ORM\Column(name="enabled", type="boolean", nullable=false)
*/
private $enabled;
/**
* @var boolean
*
* @ORM\Column(name="keep_on_top", type="boolean", nullable=false)
*/
private $keepOnTop;
/**
* @var \DateTime
*
* @ORM\Column(name="published", type="datetime", nullable=false)
*/
private $published;
/**
* @var \DateTime
*
* @ORM\Column(name="created", type="datetime", nullable=false)
*/
private $created;
/**
* @var \DateTime
*
* @ORM\Column(name="updated", type="datetime", nullable=true)
*/
private $updated;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Ranger\AppBundle\Entity\Tag", inversedBy="post")
* @ORM\JoinTable(name="post_tag",
* joinColumns={
* @ORM\JoinColumn(name="post_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="tag_id", referencedColumnName="id")
* }
* )
*/
private $tag;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Ranger\AppBundle\Entity\Product", inversedBy="post")
* @ORM\JoinTable(name="post_product",
* joinColumns={
* @ORM\JoinColumn(name="post_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="product_id", referencedColumnName="id")
* }
* )
*/
private $product;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Ranger\AppBundle\Entity\Category", inversedBy="post")
* @ORM\JoinTable(name="post_category",
* joinColumns={
* @ORM\JoinColumn(name="post_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
* }
* )
*/
private $category;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Ranger\AppBundle\Entity\Agency", inversedBy="post")
* @ORM\JoinTable(name="post_agency",
* joinColumns={
* @ORM\JoinColumn(name="post_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="agency_id", referencedColumnName="id")
* }
* )
*/
private $agency;
/**
* @var \Ranger\AppBundle\Entity\Image
*
* @ORM\ManyToOne(targetEntity="Ranger\AppBundle\Entity\Image")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="image_id", referencedColumnName="id")
* })
*/
private $image;
/**
* Constructor
*/
public function __construct()
{
$this->tag = new ArrayCollection();
$this->product = new ArrayCollection();
$this->category = new ArrayCollection();
$this->agency = new ArrayCollection();
}
/**
* Set title
*
* @param string $title
* @return Post
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set content
*
* @param string $content
* @return Post
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set enabled
*
* @param boolean $enabled
* @return Post
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Get enabled
*
* @return boolean
*/
public function getEnabled()
{
return $this->enabled;
}
/**
* Set keepOnTop
*
* @param boolean $keepOnTop
* @return Post
*/
public function setKeepOnTop($keepOnTop)
{
$this->keepOnTop = $keepOnTop;
return $this;
}
/**
* Get keepOnTop
*
* @return boolean
*/
public function getKeepOnTop()
{
return $this->keepOnTop;
}
/**
* Set published
*
* @param \DateTime $published
* @return Post
*/
public function setPublished($published)
{
$this->published = $published;
return $this;
}
/**
* Get published
*
* @return \DateTime
*/
public function getPublished()
{
return $this->published;
}
/**
* Set created
*
* @param \DateTime $created
* @return Post
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* @param \DateTime $updated
* @return Post
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* @return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add tag
*
* @param \Ranger\AppBundle\Entity\Tag $tag
* @return Post
*/
public function addTag(Tag $tag)
{
$this->tag->add($tag);
return $this;
}
/**
* Remove tag
*
* @param \Ranger\AppBundle\Entity\Tag $tag
*/
public function removeTag(Tag $tag)
{
$this->tag->removeElement($tag);
}
/**
* Get tag
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getTag()
{
return $this->tag;
}
/**
* Add product
*
* @param \Ranger\AppBundle\Entity\Product $product
* @return Post
*/
public function addProduct(Product $product)
{
$this->product->add($product);
return $this;
}
/**
* Remove product
*
* @param \Ranger\AppBundle\Entity\Product $product
*/
public function removeProduct(Product $product)
{
$this->product->removeElement($product);
}
/**
* Get product
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getProduct()
{
return $this->product;
}
/**
* Add category
*
* @param \Ranger\AppBundle\Entity\Category $category
* @return Post
*/
public function addCategory(Category $category)
{
$this->category->add($category);
return $this;
}
/**
* Remove category
*
* @param \Ranger\AppBundle\Entity\Category $category
*/
public function removeCategory(Category $category)
{
$this->category->removeElement($category);
}
/**
* Get category
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getCategory()
{
return $this->category;
}
/**
* Add agency
*
* @param \Ranger\AppBundle\Entity\Agency $agency
* @return Post
*/
public function addAgency(Agency $agency)
{
$this->agency->add($agency);
return $this;
}
/**
* Remove agency
*
* @param \Ranger\AppBundle\Entity\Agency $agency
*/
public function removeAgency(Agency $agency)
{
$this->agency->removeElement($agency);
}
/**
* Get agency
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getAgency()
{
return $this->agency;
}
/**
* @return Image
*/
public function getImage()
{
return $this->image;
}
/**
* @param Image $image
* @return Post
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* @ORM\PrePersist
*/
public function setEnabledAfterCreate()
{
$this->enabled = true;
}
/**
* @ORM\PrePersist
*/
public function setCreatedAfterCreate()
{
if(!$this->getCreated())
{
$this->created = new \DateTime();
}
}
/**
* @ORM\PreUpdate
*/
public function setUpdatedAtValue()
{
$this->updated = new \DateTime();
}
}
PostRepository.php
<?php
namespace Company\AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
/**
* Class PostRepository
* @package Company\AppBundle\Entity
*/
class PostRepository extends EntityRepository
{
public function getSimilarPost(Post $post)
{
$qb = $this->createQueryBuilder("p")
->select('p')
->setParameter('post', $post)
->setMaxResults(Post::SIMILAR_POST_MAX)
;
/** @var Tag $tag */
foreach ($post->getTag() as $tag)
{
$id = 'tag'.$tag->getId();
$qb->orWhere(":$id MEMBER OF p.tag AND p != :post")
->setParameter($id, $tag);
}
/** @var Product $product */
foreach ($post->getProduct() as $product)
{
$id = 'product'.$product->getId();
$qb->orWhere(":$id MEMBER OF p.product AND p != :post")
->setParameter($id, $product);
}
return $qb->getQuery()->getResult();
}
}