Filter by entity collection. Symfony2 - symfony

I have this entities
class Business
{
...
/**
*
* #ORM\ManyToMany(targetEntity="Category", inversedBy="businesses")
*
*/
private $categories;
...
}
class Category
{
...
/**
*
* #ORM\ManyToMany(targetEntity="Business", mappedBy="categories")
*
*/
private $businesses;
...
}
And I try this query in BusinessRepository but does not work
$em = $this->getEntityManager();
$dql = "
SELECT a
FROM BusinessMainBundle:Business a
WHERE a.title LIKE :title AND :category IN (a.categories)";
$query = $em->createQuery($dql)
->setParameter("title", "%".$title."%")
->setParameter("category", $category);
If you can resolve this problem I would be thankful

You need to join categories. Your DQL should look like this:
$dql = "
SELECT a
FROM BusinessMainBundle:Business:Business a
LEFT JOIN a.categories c
WHERE a.title = :title AND c.id IN (:category)
";
Where
->setParameter("category", $category);
$category should be an array of values (in this example id of categories).

Related

Query Build doctrine Symfony

I have 2 entity (Rule and analysisRule)( association one to many)
I try to make a query that counts the number of idAnalyseRule that have an idAnalyse pass as a parameter in the function
example:
I pass idRule = 15 as a parameter, the query will count all IdAnalysisRules that have an idAnalysis = 15
I do not know how it works but I try it like that
$qb = $this->createQueryBuilder('p');
$expr = $qb->expr();
$qb->andWhere(
$expr->eq('p.analyse', ':analyse')
)
->setParameter('analyse', $analyse);
return $qb->getQuery()->getSingleResult();
this is the manager
/**
* #param $analyse
* #return mixed
*/
public function errorsAnalyseRule(Analyse $analyse){
return $this->repository->totalErrors($analyse);
}
this is controller
/**
*
* Get a totalError by idAnalyse.
* #param Analyse $analyse
* #param AnalyseRuleManager $analyseRuleManager
* #return ApiResponse
*
* #SWG\Parameter(name="id", in="path", type="integer", description="Supplier Id"))
* #SWG\Response(response=200, description="Returns the nbErrors")
*
* #Rest\Get("analyses/{id}", requirements={"id"="\d+"})
*/
public function getTotalErrorsAction(Analyse $analyse, AnalyseRuleManager $analyseRuleManager)
{
return new ApiResponse(['nbErrors' => $analyseRuleManager->errorsAnalyseRule($analyse)]);
}
I am in a state of blockage for 3 days
This works with an inner join. In the repository of analysisRule you have to add the function that makes the query and returns the count:
public function countAnalysisRule(Rule $rule)
{
return $this-createQueryBuilder('a')
->select('count(a)')
->innerJoin('a.Rule', 'rule')
->where('rule.id = :rule')
->setParameter('rule', $rule->getId())
->getQuery()
->getSingleScalarResult();
}
Don't forget ofcourse to add a use of the Rule class.
According to https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html
You should use:
$qb = $entityManager->createQueryBuilder();
$qb->select($qb->expr()->count('p.id'))
->from('App:AnalyseRule','p')
->where('p.analyse', ':analyse')
->setParameter('analyse', $analyse);
$count = $qb->getQuery()->getSingleScalarResult();
where $analyse = 15 in your case !
If you are under 2.6 for doctrine prefer:
$qb = $entityManager->createQueryBuilder();
$qb->select('count(p.id)')
->from('App:AnalyseRule','p')
->where('p.analyse', ':analyse')
->setParameter('analyse', $analyse);
$count = $qb->getQuery()->getSingleScalarResult();

Serialize translateble entity

For translate my entity product use next code
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
class Product
{
/**
* #Groups({"prod_translate"})
*/
use ORMBehaviors\Translatable\Translatable;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Groups({"prod"})
*/
private $id;
...
Translatable create new entity ProductTranslation with table in DB product_translation with id, translatable_id, locale and translatble properties.
Translation work perfectly. In page just write {{ product.translation.en/sp.name }}
When use ajax pagenation use serializer for return data.
Tried JMS\Serializer\SerializerBuilder and Symfony\Component\Serializer\Serializer
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Doctrine\Common\Annotations\AnnotationReader;
$products = $em->getRepository('AppBundle:Product')->findNextPageByBrandCategoryIds( array($cat), $brand, $offset, $limit );
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new ObjectNormalizer($classMetadataFactory);
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getID();
});
$serializer = new Serializer(array($normalizer));
$jsonObject = $serializer->normalize($products, 'json', array('groups' => array('prod', 'prod_translate')) );
Without groups serializet return "Maximum execution time 180second".
With groups return only Product data without translations.
What annotation or else manipulation must do for fix this issue? Please help!
Edit:
Tried Use next queries:
public function findNextPageByBrandCategoryIds(array $cat_ids, $brand_id, $offset=0, $limit=8 )
{
$qb = $this->createQueryBuilder('p');
if( !empty($cat_ids) ){
$cat_ids = implode(',', $cat_ids);
$qb->join('p.categories', 'c')
->where($qb->expr()->in('c.id', $cat_ids ) );
}
if( !empty($brand_id) ){
$qb->andWhere('p.brand = :brand')
->setParameter('brand', $brand_id);
}
if( $offset>0 ){
$qb->setFirstResult( $offset );
}
$qb->setMaxResults( $limit );
return $qb->getQuery()->getResult();
}
private function findNextPageByBrandCategoryIds($cat_id, $brand_id, $offset=0, $limit=8 )
{
$em = $this->getDoctrine()->getManager();
$sql = "SELECT p.id, t.id AS translate_id " .
"FROM product p INNER JOIN product_translation t ON t.translatable_id = p.id";
$where .= ' WHERE 1=1 ' ;
$rsm = new ResultSetMappingBuilder($em);
if( !empty($cat_id) ){
$sql .= " LEFT JOIN products_categories c ON c.product_id = p.id ";
$where .= " AND c.category_id = ".$cat_id;
}
if( !empty($brand_id) ){
$where .= " AND p.brand = ".$brand_id;
}
$limit = ' LIMIT '.$limit;
if( $offset>0 ){
$limit .= ' OFFSET '.$offset;
}
$sql = $sql.$where.$limit;
$rsm->addRootEntityFromClassMetadata('AppBundle\Entity\Product', 'p');
$rsm->addJoinedEntityFromClassMetadata('AppBundle\Entity\ProductTranslation', 't', 'p', 'product', array('id' => 'translatable_id'));
$query = $em->createNativeQuery($sql, $rsm);
return $query->getResult();
}
Debug almost every line - they are right.
If use setHint(\Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD, true) - work but return products only, without translations.
The Maximum execution time 180 second message is an error that has nothing to do with annotations or the serializer.
In your php.ini you have a max_execution_time option to configure the limit of a script in seconds. You can also set it with the function set_time_limit($seconds)by code, but I would not recommend to use it.
Anyway, I would bet that you are doing a very large query. How many results are you limiting?
Nik fix this issue:
On Brand, Category and Product Entities
use JMS\Serializer\Annotation\MaxDepth;
/**
* #MaxDepth(1)
*/
private $products;
/**
* #MaxDepth(1)
*/
private $categories;
/**
* #MaxDepth(1)
*/
private $brand;

Mysql Views Table in Symfony 2

I have view table in my Database, how can I retrieve the data from this views?
I tried to use
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery('SELECT * FROM my_views');
$result = $query->getResult();
but it doesn't work.
If you want to perform a simple SQL query, you can do that :
$con = $this->getDoctrine()->getEntityManager()->getConnection();
$stmt = $con->executeQuery('SELECT * FROM my_views');
foreach ($stmt->fetchAll() as $row){
print_r($row);
}
When you use $em->createQuery(), you need to work with Doctrine entities.
If you want to use the mapping with your view, juste create an entity :
namespace Your\Bundle\Entity;
/**
* #ORM\Entity
* #ORM\Table(name="my_view")
*/
class MyView
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $someVarcharColumn;
public function getId()
{
return $this->id;
}
public function getSomeVarcharColumn()
{
return $this->someVarcharColumn;
}
}
And you can query it with DQL like this :
$results = $em->createQuery('
SELECT v
FROM YourBundle:MyView v
')->getResult();

Doctrine DQL doesn't set ON JOIN automatically

I thought if I don't want to override relation's on condition I just use WITH to add an additional condition. I'm not sure if my mapping is wrong, but DQL without join condition in WITH makes a CROSS Join
Here My Entities Relations (Symfony):
Movie:
/**
* #ORM\OneToMany(targetEntity="MovieInterest", mappedBy="movie")
*/
private $movieInterests;
MovieInterest:
/**
* #ORM\ManyToOne(targetEntity="Movie", inversedBy="movieInterests")
*/
private $movie;
Here my Query in MovieInterestRepository:
public function deleteByMovieId($id, $user)
{
$em = $this->getEntityManager();
$result = $em->createQuery(
"SELECT mi FROM CineupsWebAppBundle:MovieInterest mi
JOIN CineupsWebAppBundle:Movie m WITH m.id=mi.movie
WHERE m.id=".$id." AND mi.user=".$user->getId())
->getResult();
foreach ($result as $entity) {
$em->remove($entity);
}
$em->flush();
}
If I remove WITH m.id=mi.movie the Query gets too many results
Try to do it this way:
$result = $em->getRepository('CineupsWebAppBundle:MovieInterest')
->createQuery('mi')
->innerJoin('mi.Movie', 'm')
->andWhere('m.id = :id')
->andWhere('mi.user = :user')
->getQuery()
->setParameter(':id', $id)
->setParameter(':user', $user->getId())
->getResult();
This will also solve sqj-injection vulnerability at your original query
You need to add mapping information to your entity:
/**
* #ORM\ManyToOne(targetEntity="Movie", inversedBy="movieInterests")
* #ORM\JoinColumn(name="id", referencedColumnName="movie")
*/
private $movie;
I found the problem: I joined with table and not with relation. Here the correct code:
"SELECT mi FROM CineupsWebAppBundle:MovieInterest mi
JOIN mi.movie m
WHERE m.id=".$id." AND mi.user=".$user->getId())

doctrine create query with 2 association

i have this entity
Post
/**
* #ORM\ManyToOne(targetEntity="SottoCategoria")
* #ORM\JoinColumn(name="sottocategoria_id", referencedColumnName="id", nullable=false)
*/
public $sottocategoria;
SottoCategoria
/**
* #ORM\ManyToOne(targetEntity="Categoria")
* #ORM\JoinColumn(name="categoria_id", referencedColumnName="id", nullable=false)
*/
public $categoria;
Categoria
/**
* #ORM\OneToMany(targetEntity="SottoCategoria", mappedBy="categoria")
*/
protected $sottocategorie;
how can I make this query? i need to find all post from categoria
post.sottocategoria.categoria
$query = $repository->createQueryBuilder('p')
->where('p.enabled = :enabled AND p.sottocategoria.categoria = :categoria')
->setParameters(array(
'enabled' => true,
'categoria' => $idCat,
))
i can't use p.categoria because i not have relation with post
my relation is post -> sottocategoria -> categoria
so my question is how i get all post from categoria? i have to use innerjoin?
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
'SELECT p,g,c FROM AcmeBlogBundle:Post p JOIN p.sottocategoria g JOIN g.categoria c WHERE p.enabled = :enabled AND g.categoria = :categoria ORDER BY p.id DESC')
solved

Resources