I have a problem with Doctrine woring in my Symfony project.
That's my code:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\Common\Persistence\ObjectManager;
use Factory\MainBundle\Entity\Lastauction;
use Factory\MainBundle\Entity\Offers;
class AuctionListController extends Controller
{
private $em;
private $qb;
private $offer;
public function getAuctionListAction()
{
$this->em = $this->getDoctrine()->getEntityManager();
$this->qb = $this->em->createQueryBuilder();
getAllAccount();
for($offset=0; $offset<20000; $offset++)
{
$this->insertOffers();
}
return new Response('Offers list generated');
}
private function getAllAccount()
{
$this->qb->select('ac.mail')
->from('FactoryMainBundle:Account', 'ac');
$result = $this->qb->getQuery()->getResult();
$this->accounts = array_column($result, 'mail');
}
private function insertOffers()
{
foreach($this->offers as $id => $offer)
{
if($this->checkIfExsistOffer($offer))
{
echo $offer .'<br>';
$offerObj = new Offers();
$offerObj->setOffer($offer);
$offerObj->setPage(2);
$this->em = $this->getDoctrine()->getManager();
$this->em->persist($offerObj);
if (($id % $this->batchSize) == 0)
{
$this->em->flush();
$this->em->clear();
}
}
}
$this->em->flush();
$this->em->clear();
$this->offers = array();
}
private function checkIfExsistOffer($offerUrl)
{
$this->qb->select('o.id')
->from('FactoryMainBundle:Offers', 'o')
->where("o.offer=:offer")
->setParameter('offer', $offerUrl);
$result = $this->qb->getQuery()->getResult();
return (isset($result['0']['id'])) ? 1 : 0;
}
}
And I get this error:
[Semantical Error] line 0, col 134 near 'o WHERE o.of': Error: 'o' is already defined.
[2/2] QueryException: [Semantical Error] line 0, col 134 near 'o WHERE o.of': Error: 'o' is already defined.
[1/2] QueryException: SELECT o.id FROM FactoryMainBundle:Account ac, FactoryMainBundle:Lastauction la, FactoryMainBundle:Offers o, FactoryMainBundle:Offers o WHERE o.offer='123'
Why Doctrine takes tables from other queries?
$this->qb->select('o.id')
->from('FactoryMainBundle:Offers', 'o')
->where("o.offer=:offer")
->setParameter('offer', $offerUrl);
$result = $this->qb->getQuery()->getResult();
Breakdown of your codeflow regarding $this->qb:
1) In getAuctionListAction: $this->qb = $this->em->createQueryBuilder();
2) In getAllAccount:
$this->qb->select('ac.mail')
->from('FactoryMainBundle:Account', 'ac');
3) In checkIfExsistOffer (through insertOffers), 20.000x due to your loop in getAuctionListAction:
$this->qb->select('o.id')
->from('FactoryMainBundle:Offers', 'o')
->where("o.offer=:offer")
->setParameter('offer', $offerUrl);
Long Story short: You're adding multiple tables to your $this->qb querybuilder object (through $this->qb->from(...)), that's why they all get queried.
private function checkIfExsistOffer($offerUrl)
{
$res = $this->getDoctrine()->getRepository('FactoryMainBundle:Offers')
->createQueryBuilder('o')
->select('o.id')
->where("o.id=:offer")
->setParameter('offer', 1)
->getQuery()
->getSingleResult(); //return single result
var_dump($res);die; //test
}
Related
I'm working on symfony, and i have a doctrine problem :
class Utilisateur implements UserInterface, PasswordAuthenticatedUserInterface
{ /**
* #ORM\OneToMany(targetEntity=UserGestionnaire::class, mappedBy="user", cascade={"persist"})
*/
private $userGestionnaires;
class UserGestionnaire
{
/**
* #ORM\ManyToOne(targetEntity=Societe::class, inversedBy="userGestionnaires")
*/
private $gestionnaire;
So here i have a One To Many Relation,and i want to Know how Many user don t have the the usergestionnaire gestionnaire id 1002
I tried a lot of testing and searching, but i didn t found any solution,
Here what i got so far :
public function countUserNoIdSpecificGest()
{
$limitDate = date_format(new \DateTime("now - 2 years"), 'Y-m-d');
$query = $this->createQueryBuilder('u');
$queryB = $query
->select('count(distinct(u.id))')
->join('u.mouvements', 'm')
->join('u.userGestionnaires', 'ug')
->join('ug.gestionnaire', 'sg')
// Here : ->andWhere('sg.id NEVER BE 1002')
->join('m.rules', 'r')
->join('r.avenantModule', 'am')
->join('am.module', 'mod')
->join('mod.manager', 's')
->andWhere('s.id = 1002')
->andWhere('u.deletedAt IS NULL')
->andWhere('m.deletedAt IS NULL')
->andWhere(
$query->expr()->orX(
$query->expr()->orX(
$query->expr()->gte('m.dateOut', ':limitDate'),
)
)
)
->setParameter('limitDate', $limitDate)
->getQuery()
->getSingleScalarResult();
return $queryB;
}
To be more understandable, here is the part of the PHP code that I would like to transfer to WHERE doctrine :
$usersNotVerified = $this->em->getRepository(Utilisateur::class)->getUserNoIdSpecificGest();
$users = array();
foreach ($usersNotVerified as $userNotVerified) {
$gestionnaires = $userNotVerified->getUserGestionnaires();
$finded = false;
foreach ($gestionnaires as $gestionnaire) {
$societyId = $gestionnaire->getGestionnaire()->getId();
if ($societyId == 1002) {
$finded = true;
}
}
if (!$finded) {
array_push($users, $userNotVerified);
}
}
$countNoId = count($users);
public function getUserNoIdSpecificGest()
{
$limitDate = date_format(new \DateTime("now - 2 years"), 'Y-m-d');
$query = $this->createQueryBuilder('u');
$queryB = $query
->join('u.mouvements', 'm')
->join('m.rules', 'r')
->join('r.avenantModule', 'am')
->join('am.module', 'mod')
->join('mod.manager', 's')
->andWhere('s.id = 1002')
->andWhere('u.deletedAt IS NULL')
->andWhere('m.deletedAt IS NULL')
->andWhere(
$query->expr()->orX(
$query->expr()->orX(
$query->expr()->gte('m.dateOut', ':limitDate'),
)
)
)
->setParameter('limitDate', $limitDate)
->addOrderBy('u.id', 'asc')
->getQuery()
->getResult();
return $queryB;
}
I am making some DB query via repository (ORM), I want to get a list of objects.
What's my problem?
I have two methods in the repository: getList() to get a list and getCount() to get the number of total records for information.
getList() gives me 5 records, and getCount() gives the number 9.
public function getList($criteria, $page, $limit, $orderBy, $joins = [])
{
$qb = $this->createQueryBuilder('a')->select('a');
if(!empty($joins)) {
$qb = $this->setCriteriaByJoins($qb, $joins);
}
$qb = $this->setCriteriaToQuery($qb, $criteria);
foreach($orderBy as $order) {
$qb->addOrderBy('a.' . $order[0], $order[1]);
}
if($page && $limit) {
$offset = ($page - 1) * $limit;
$qb->setFirstResult($offset)
->setMaxResults($limit);
}
$result = $qb->getQuery()->getResult();
return $result;
}
public function getCount($criteria = [], $joins = []) {
try {
$qb = $this->createQueryBuilder('a')->select('count(a.id)');
if(!empty($joins)) {
$qb = $this->setCriteriaByJoins($qb, $joins);
}
$qb = $this->setCriteriaToQuery($qb, $criteria);
$result = $qb->getQuery()->getSingleScalarResult();
} catch(\Exception $e) {
$result = 0;
}
return $result;
}
In debugging, I see that the getList() request was built like this:
SELECT r0 _. * FROM film r0_ LEFT JOIN person_film r1_ ON (r0_.id = r1_.film_id) WHERE r1_.person_id IN (45793) AND r0_.status = 1 ORDER BY r0_.`release` DESC, r0_.id DESC LIMIT 48
and getCount()
SELECT count (r0_.id) AS sclr_0 FROM film r0_ LEFT JOIN person_film r1_ ON (r0_.id = r1_.film_id) WHERE r1_.person_id IN (45793) AND r0_.status = 1
Requesting getList() from the repository gives me 5 records. However, if I directly ask the database with this query (without ORM), then I will get 9 records. Of these 9 records, 4 are duplicated due to the fact that the person_film table can contain more than one record with the same film_id and person_id (these records differ in other fields). I found that /vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:hydrateRowData() removes duplicates.
How to do to make the ORM in the getList() request return all 9 records, even if they are duplicates?
And vice versa. How to do to the getCount() to return 5.
it seems like this is the answer to the second question
public function getCount($criteria = [], $joins = [], $distinct = false) {
try {
$sq = ($distinct) ? 'count(distinct(a.id))' : 'count(a.id)';
$qb = $this->createQueryBuilder('a')->select($sq);
if(!empty($joins)) {
$qb = $this->setCriteriaByJoins($qb, $joins);
}
$qb = $this->setCriteriaToQuery($qb, $criteria);
$result = $qb->getQuery()->getSingleScalarResult();
} catch(\Exception $e) {
$result = 0;
}
return $result;
}
I'm trying to pass id from query from one database table to another table to which is related.
But, since they are related I have to pass it as instance of the entity(class) to which is related.
This is error I got:
Argument 1 passed to App\Entity\KeywordRating::setKeywordId() must be an instance of App\Entity\Keywords, integer given, called in C:\xampp\htdocs\ratingAPI\src\Service\KeywordRatingService.php on line 26
This is my code:
public function insertRating($params, ObjectManager $manager, KeywordsRepository $keyRep, ProvidersRepository $provRep)
{
$keywordId = $keyRep->checkKeyword(strtolower($params['keyword']))->getId();
$providerId = $provRep->checkProvider($params['provider'])->getId();
$rating = new KeywordRating();
$rating->setKeywordId(<Keywords instance> $keywordId);
$rating->setProviderId(<Providers instance> $providerId);
if($params['attr'] === 'rocks')
{
$rating->setRocksRating($params['rating']);
$rating->setSucksRating(0);
} else
{
$rating->setRocksRating(0);
$rating->setSucksRating($params['rating']);
}
$rating->setRocksVotes(10);
$rating->setSucksVotes(8);
$rating->setSumVotes(18);
$rating->setScore(2.50);
$manager->persist($rating);
$manager->flush();
}
This is sql query:
public function checkKeyword($keyword)
{
return $this->createQueryBuilder('k')
->where('k.keyword_name = :val')
->setParameter('val', $keyword)
->getQuery()
->getOneOrNullResult();
}
checkProvider() is the same, only different parameters.
How do I do that?
Assuming you have a namespace called Entities where you have all your entities classes, you can try something like this:
$entityManager = $this->getDoctrine()->getManager();
$queryBuilder = $entityManager->createQueryBuilder();
$queryBuilder->select('keyword')
->from('App\Entity\Keywords', 'keyword')
->where($queryBuilder->expr()->eq('keyword.keyword_name', $queryBuilder->expr()->literal($keyword)));
$result = $queryBuilder->getQuery()-> getOneOrNullResult();
return $result;
I have some issues using query builder. First things first I have this repository:
<?php
namespace AppBundle\Entity;
use AppBundle\Entity\Product;
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
public function register($username,$password,$email)
{
//A Generic return Object
$status=array('status'=>true,'data'=>"");
if(empty($username))
{
$status['status']=-1;
$status['data']='Username not given';
return $status;
}
if(empty($password))
{
$status['status']=-1;
$status['data']='Password not given';
return $status;
}
if(empty($email))
{
$status['status']=-1;
$status['data']='Email not given';
return $status;
}
$token=md5(uniqid(gethostname(),true));
try
{
$user=new Users();
$user->setUsername($username)
->setPassword($password)
->setEmail($email)
//->setActivated(false)
->setToken($token);
$em=$this->getEntityManager();
$tmp_user=$user->getUsername();
$tmp_mail=$user->getEmail();
$query=$em->createQueryBuilder('p')
->where('p.username=?',$tmp_user)
->orWhere('p.email=?',$tmp_mail)
->getQuery();
$user=$query->getResult();
var_dump($user);
if(!empty($user))
{
$em->persist($user);
$em->flush();
$status['status']=true;
}
else
{
$result['data'] = -1;
$result['status'] = "User exists";
}
}
catch (\Exception $e)
{
echo $e->getMessage();
$result['data'] = $e->getMessage(); // The exact message of the exception thrown during INSERT
$status['status']=false;
}
return $status;
}
}
What I want to achieve is to check if to check if there are any users with the same username or email. That's why I run:
$tmp_user=$user->getUsername();
$tmp_mail=$user->getEmail();
$query=$em->createQueryBuilder('p')
->where('p.username=?',$tmp_user)
->orWhere('p.email=?',$tmp_mail)
->getQuery();
$user=$query->getResult();
Inside the register function. But the:
echo $e->getMessage();
Returns:
[Syntax Error] line 0, col 7: Error: Expected known function, got 'WHERE'
The select statement is missing, and your where statements must be prepared.
Change your code to :
$query = $em->createQueryBuilder('p')
->select('p')
->where('p.username = :username')
->orWhere('p.email = :email')
->setParameter('username', $tmp_user)
->setParameter('email', $tmp_mail)
->getQuery();
$user = $query->getResult();
Like this, you have a clean prepared query.
See the "Bind parameters to your query" chapter of doctrine QueryBuilder documentation
EDIT
You need to use the repository like follows :
$repository = $em->getRepository('YourBundle:YourEntity');
$query = $repository->createQueryBuilder('p)
->select('p')
//...
Or add a FROM statement :
$query = $em->createQueryBuilder('p')
->from('YourEntityNamespace', 'p')
// ...
I'm not sure if it's that I'm not doing correctly but this is giving me an error:
I have 2 Entities: Task and TaskUser. They are connected by a onetoMany.
What I want to do is this:
foreach($tasks as $task){
echo $task->getTitle;
echo $task->getTaskUser()->getFirstName();
}
This is my query in the Task Repository:
public function findTasksByUsers($user = false)
{
if($user){
$qb = $this->_em->createQueryBuilder();
$qb
->select('t', 'tu')
->from('\Entities\Task', 't')
->leftJoin('\Entities\TaskUser', 'tu', \Doctrine\ORM\Query\Expr\Join::WITH, 't.id = tu.task')
->where('tu = :user')
->setParameter('user', $user)
->orderBy('t.createDate', 'DESC');
return $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_OBJECT);
}
}
When I do this loop:
$tasks = $this->em->getRepository('\Entities\Task')->findTasksByUsers($user);
foreach($tasks as $task){
echo $task->getTitle();
}
I get the the title of the first task, and then an error like this:
Title of first task
Fatal error: Call to undefined method Entities\TaskUser::getTitle() in D:\sites\db\application\controllers\TasksController.php on line 35
Any idea why this is happening? Thanks!
$qb->select('t', 'tu')
the issue is here as you're selecting both entities.
If you want only Task entity modify your DQL as follows
$qb->select('t')
However, to me, you could only procede that way (in your controller; if you aren't into controller, use DI to access entity manager)
//retrieve all TaskUser object
$em = $this->getDoctrine()->getManager();
$tu_repo = $em->getRepository('YourBundleName:TaskUser');
$tu_array_collection = $tu_repo->findBy(array('user'=>$user));
foreach ($tu_array_collection as $tu) {
$first_name = $tu->getFirstName();
foreach ($tu->getTasks() as $task) {
echo $first_name;
echo $task->getTitle();
}
}
of course you may need to adapt your code with right findBy array, and with correct methods from TaskUser entity