PHP: Symfony2 MySQL SELECT query in controler - php

I created a database on phpMyAdmin localhost. I have set database configurations in symfony and created doctrine mapper (entity). Now all I need is to make SELECT query and get information from database:
TABLE NAME: Profile
ROWS: 1
CONTROLLER CODE:
...
use Ignas\IgnasBundle\Entity\Profilis;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$profilis = new Profilis();
return new Response('Id '.$profilis->getId());
}
}
getId method is from Entity/Profilis file Profilis class.
Is there any easy way to do this? I searched for a while and all I could find was doctrine syntax that is not familliar to me at all.

you can do it in different ways:
first of all, get the EntityManager in your Controller
$em = $this->getDoctrine()->getEntityManager();
in case it says it's deprecated you can also get it like:
$em = $this->getDoctrine()->getManager();
then you can do it with the QueryBuilder or with the createQuery method
With Select method (as suggested in the comments)
$profilis= $em->select('p.id')
->from('BundleName:EntityName', 'p')
->getQuery()
->getResult();
simple Query:
$query = $em->createQuery("SELECT * FROM Profilis p");
$profilis = $query->getResult();
NOTE
both methods return an array of Profilis so you can simply loop them this way:
foreach($profilis as $p){
// do whatever you want
}

Related

Understanding problem Doctrine 2 ORM Query Builder in Symfony 4

I hope there are a few helpful and prefer German Symfony experts. For many years I have been working with PHP and now I tryed in a framework. I chose Symfony now because I like the components the most. The QueryBuilder and I stand on a war foot - I just do not understand it. Storing values works very well so far, though I doubt that I'm doing this in the sense of the framework. I'm really helpless. Currently I managing it by chasing everything in raw format but I'm not really happy with it.
How I can implement the following with Doctrine?
use App\Entity\Questions;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityManager;
class QuestionsController extends AbstractController
{
/**
* #Route("/addquestion", methods={"POST","HEAD"})
*/
public function addQuestion()
{
$entityManager = $this->getDoctrine()->getManager();
$RAW_QUERY = 'SELECT COUNT(*) AS c FROM questions WHERE questToID = '.$_POST['u'].' AND questFrom = '.$this->getUser()->getId().';';
$statement = $entityManager->getConnection()->prepare($RAW_QUERY);
$statement->execute();
$total = $statement->fetchAll();
if($total[0]['c'] >= 3)
{
return new Response('error|Du kannst der selben Person maximal drei Fragen stellen.');
}
[...]
I have already tried to implement this, and many other things (no avail):
Count Rows in Doctrine QueryBuilder
Since I speak bad English, I very much hope that you understand me…
so getting the value with $_POST['u'] is not recommended her you can either pass the value with the route an retrieve it as a parameter for the function:
/**
* #Route("/addquestion/{u}", methods={"POST","HEAD"})
*/
public function addQuestion($u)
or you can get it out from the request it self:
/**
* #Route("/addquestion", methods={"POST","HEAD"})
*/
public function addQuestion(Request $request)
if you want to use the query builder the best practice would be to create a repository for you entity and make you the query there:
namespace App\Repository;
use App\Entity\Questions;
use Doctrine\ORM\EntityRepository;
class QuestionsRepository extends EntityRepository
{
public function findUserQuestions($user, $u)
{
$queryBuilder = $this->createQueryBuilder('c')
->where('c.questToID = :questToID')
->andWhere('c.questFrom = :questFrom')
->setParameters(['questToID'=>$u,'questFrom'=>$user]);
return $queryBuilder->getQuery()->getResult();
}
and in you controller you can get the result:
$userQuestions = $this->getDoctrine()->getRepository(Questions::class)->findUserQuestions($this->getUser(), $u);
count($userQuestions);
i hope this will be useful in your case and explain you a bit how its done in symfony
One simple way of doing that would be something like this (with the assumption that you have a "Question" entity - and that the fields defined there are matching with the column names from your raw query).
$em = $this->getDoctrine()->getManager();
$userQuestions = $em->getRepository(Question:class)->findAll(['questToID' => $_POST['u'], 'questFrom ' => $this->getUser()->getId()]);
$total = count($userQuestion);
Or if you prefer to have just the count from the query instead of fetching all the matching objects and counting them, you can write the query builder part something like this (in this format this is meant to be written in your controller as you have with your raw query - in general the "correct" place would be QuestionRepository.php class from where this would be just called in controller):
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder('q');
$qb->select('count(q)');
$qb->andWhere('q.questToID = :questToID');
$qb->andWhere('q.questFrom = :questFrom');
$qb->setParameter('questToID', $_POST['u']);
$qb->setParameter('questFrom ', $this->getUser()->getId());
$total = $qb->getQuery()->getSingleScalarResult();

Mapping myself form in Symfony2

I'd like to map an entity of a form by myself. The thing is I'm working with 36 000 cities in a database and Doctrine doesn't return any result when I'm performing a request using findBy. But I set this up by writting my owns methods.
The problem is in a form I need to ask for a city through an entity field (because there are a lot of data, I'm using select2 with remote's data). So far, no problem but when I'm submiting the form, Symfony can't bind the city's id to a database entry because of the none result of the classic method of Doctrine.
So, my question is : How can I tell Symfony to use my repository's method instead of the Doctrine's one to bind my data?
Thank you very much ! And have a good day ;)
The method findBy() request an array parameter sometimes people miss that:
$result = $this->getDoctrine()->getManager()
->getRepository("AcmeDemoBundle")->findBy(array(
"city" => $city)
);
If you want to use repository you just need to map it to your class:
/**
* #ORM\Entity(repositoryClass="Acme/DemoBundle/Repository/CountryRepository")
*/
class Country
{ ... }
Then in
class CountryRepository extends EntityRepository
{
public function getMySpecificCity($city)
{
$qb = $this->createQueryBuilder('c');
$cities = $qb->select(*)
->where("c.city =:city ")->setParameter('city', $city)
->getQuery()
->getResult();
return $cities;
}
...
}
So you can use it as follow:
$result = $this->getDoctrine()->getManager()
->getRepository("AcmeDemoBundle")->getMySpecificCity($city);

Performing a custom query inside Doctrine entity

I have an entity (B) which is responsible for managing custom templates. Upon updating entity A I need to query entity B to fetch the desired template and do the necessary processing.
Something like:
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\EntityRepository;
use Bundle\EmailsBundle\Entity\Email;
use Symfony\Component\Validator\ExecutionContextInterface;
class MemberApplication extends EntityRepository
{
public function sendUpdateNotificationEmails()
{
// Send email to user
$emailRow = $this->getEntityManager()
->createQuery("SELECT * FROM emails where `type` = 'x' LIMIT 1")
->getResult();
}
(...)
}
This returns me an error:
Fatal error: Call to a member function createQuery() on a non-object in Classpath/Classname.php
Both $this->getEntityManager() and $this->_em is NULL.
I read a similar approach in http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes and I'm unable to figure out why this isn't working.
Thanks
this->getEntityManager() returns null because the dependence on doctrine is not injected. Try $this->getDoctrine()->getEntityManager(); instead. This should be done in the controller side though so something like this:
$em = $this->getDoctrine()->getManager();
$memberRepo = $em->getRepository('MyBundle:MemberApplication');
$result = $memberRepo->sendUpdateNotificationEmails();
then in your function you should return $emailRow or what you want.

How to retrieve results from joined table in doctrine

I'm doing a join between two tables using the doctrine that comes bundled in the current symfony release. This is my controller code:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Acme\GearDBBundle\Entity\TbGear;
use Acme\GearDBBundle\Entity\TbDships;
class DefaultController extends Controller
{
public function indexAction()
{
$repository = $this->getDoctrine()
->getRepository('AcmeGearDBBundle:TbGear');
$query = $repository->createQueryBuilder('p')
->select('p', 'q')
->innerJoin('p.fkShip', 'q', 'WITH', 'p.fkShip = q.id')
->getQuery();
$result = $query->getResult();
foreach ( $result as $p ) {
$gear[] = array('shortname' => $p->getGearShortName(), 'name' => $p->getGearName(), 'shipname' => $p->getShipName /* Does not work, since the getter is in a different entity */);
}
return $this->render('AcmeGearDBBundle::index.html.twig', array('gear' => $gear));
}
}
The query generated by this is correct and delivers the expected fields if I execute it in phpmyadmin.
SELECT t0_.GEAR_NAME AS GEAR_NAME0, t0_.GEAR_SHORT_NAME AS GEAR_SHORT_NAME1, t0_.STATUS AS STATUS2, t0_.ID AS ID3, t1_.SHIP_NAME AS SHIP_NAME4, t1_.CONTACT_NAME AS CONTACT_NAME5, t1_.CONTACT_EMAIL AS CONTACT_EMAIL6, t1_.ID AS ID7, t0_.FK_SHIP_ID AS FK_SHIP_ID8, t0_.FK_TYPE AS FK_TYPE9
FROM tb_gear t0_
INNER JOIN tb_dships t1_ ON t0_.FK_SHIP_ID = t1_.ID
AND (t0_.FK_SHIP_ID = t1_.ID)
However, I have no clue how do access those fields in the returned result set. The way I expected it to work ( by accessing the getter of the joined table entity ) does not work. The error message reads: FatalErrorException: Error: Call to undefined method Acme\GearDBBundle\Entity\TbGear::getShipName() in /var/www/symfony/src/Acme/GearDBBundle/Controller/DefaultController.php line 24
which makes sense since the TbGear entity doesn't have a getter method called getShipName() , since that's a method from the joined entity. But how do I access those values? This probably is a stupid question, but I just can't figure it out. Any help is appreciated.
$p->getFkShip()->getShipName() maybe?
This should work since it will retrieve only TbGear that satisfies you relationship. So you could be able to access to all FkShip (I suppose that is a many-to-one relation) that should be only one, and then .... you got it!
EDIT
Of course I suppose that you have correctly designed your class so that you have a getter from TbGear to access the relation with FkShip
Can you add that custom getter: getShipName()?
public function getShipName(){
if ( $this->ship != null ){
return $this->ship->getName();
}
return null; // or an empty string
}

doctrine 2 and zend paginator

i want to use doctrine with zend_paginator
here some example query :
$allArticleObj =
$this->_em->getRepository('Articles');
$qb = $this->_em->createQueryBuilder();
$qb->add('select', 'a')
->add('from', 'Articles a')
->setFirstResult(0)
->setMaxResults(5);
is there any example code to show we can write a zend_paginator adapter for doctrine 2 query builder?
You don't need to implement Zend_Paginator_Adapter_Interface. It is already implement by Zend_Paginator_Adapter_Iterator.
You can simply pass Doctrines' Paginator to Zend_Paginator_Adapter_Iterator, which you pass to Zend_Paginator. Then you call Zend_Paginator::setItemCountPerPage($perPage) and Zend_Paginator::setCurrentPageNumber($current_page). Like this:
use Doctrine\ORM\Tools\Pagination as Paginator; // goes at top of file
SomeController::someAction()
{
$dql = "SELECT s, c FROM Square\Entity\StampItem s JOIN s.country c ".' ORDER BY '. $orderBy . ' ' . $dir;
$query = $this->getEntityManager()->createQuery($dql);
$d2_paginator = new Paginator($query); \\
$d2_paginator_iter = $d2_paginator->getIterator(); // returns \ArrayIterator object
$adapter = new \Zend_Paginator_Adapter_Iterator($d2_paginator_iter);
$zend_paginator = new \Zend_Paginator($adapter);
$zend_paginator->setItemCountPerPage($perPage)
->setCurrentPageNumber($current_page);
$this->view->paginator = $zend_paginator; //Then in your view, use it just like your currently use
}
Then you use paginator in the view script just like you ordinarly do.
Explanation:
Zend_Paginator's constructor can take a Zend_Paginator_Adapter_Interface, which Zend_Paginator_Adpater_Iterator implements. Now, Zend_Paginator_Adapter_Iterator's constructor takes an \Iterator interface. This \Iterator must also implement \Countable (as you can see by looking at Zend_Paginator_Adapter_Iterator's constructor). Since Paginator::getIterator() method returns an \ArrayIterator, it by definition it fits the bill (since \ArrayIterator implements both \Iterator and \Countable).
See this port from Doctrine 1 to Docrine 2 of the code for "Zend Framework: A Beginner's Guide" from Doctrine 1 to Doctrine: https://github.com/kkruecke/zf-beginners-doctrine2. It includes code for paginating with Zend_Paginator using Zend_Paginator_Adapter_Iterator with Doctrine 2' Doctrine\ORM\Tools\Pagination\Paginator.
Code is here (although it might not all work with latest DoctrineORM 2.2) but the example is valid: https://github.com/kkruecke/zf-beginners-doctrine2/tree/master/ch7
I was very surprised how hard it was to find an adapter example that doesn't cause performance issues with large collections for Doctrine 2 and ZF1.
My soultion does use the the Doctrine\ORM\Tools\Pagination\Paginator from Doctrine 2.2 just like #Kurt's answer; however the difference that this will return the doctrine paginator (Which is it's self an \Iterator) from getItems without the entire query results being hydrated.
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;
use Doctrine\ORM\Query;
class DoctrinePaginatorAdapter implements \Zend_Paginator_Adapter_Interface
{
protected $query;
public function __construct(Query $query)
{
$this->query = $query;
}
public function count()
{
return $this->createDoctrinePaginator($this->query)->count();
}
public function getItems($offset, $itemCountPerPage)
{
$this->query->setFirstResult($offset)
->setMaxResults($itemCountPerPage);
return $this->createDoctrinePaginator($this->query);
}
protected function createDoctrinePaginator(Query $query, $isFetchJoinQuery = true)
{
return new DoctrinePaginator($query, $isFetchJoinQuery);
}
}
The upshot, of course, is that you have to implement the Zend_Paginator_Adapter_Interface, which essentially means implementing the two methods:
count()
getItems($offset, $perPage)
Your adapter would accept the Doctrine query as a constructor argument.
In principle, the getItems() part is actually straightforward. Simply, add the $offset and $perPage restrictions to the query - as you are doing in your sample - and execute the query.
In practice, it's the count() business that tends to be tricky. I'd follow the example of Zend_Paginator_Adapter_DbSelect, replacing the Zend_Db operations with their Doctrine analogues.
Please change
use Doctrine\ORM\Tools\Pagination as Paginator;
to
use Doctrine\ORM\Tools\Pagination\Paginator as Paginator;

Categories