Performing a custom query inside Doctrine entity - php

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.

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();

How to access Doctrine defined methods after custom Repository is made?

I am developing a site using ZF2 and Doctrine. The problem I am facing is I am using Doctrine predefined object methods like findAll(), findOneBy(), findBy() etc in my code. For some custom actions I have prepared a custom Repository for one of my entities. Now I can't access the predefined methods. I have already written code by using findAll() method. But after building a repository I can't simply access findAll() method. How can I both access my custom defined methods along with Doctrine defined methods?
For example:
I am using findOneBy() like this:
$udata = $this->em()->getRepository('Application\Entity\Usermain')->findOneBy(array('userEmail' => 'subh.laha#gmail.com'));
Now I have prepared UsermainRepository like below:
namespace Application\Entity\Repositories;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Persistence\ObjectRepository;
class UsermainRepository extends EntityRepository
{
protected $sl;
public function __construct($sl){
$this->sl = $sl;
}
public function customFind($arr)
{
$qb = $this->sl->createQueryBuilder();
$whereStr = '';
if(count($arr)){
foreach($arr as $kvarr=>$varr){
$whereStr .= "u.$kvarr = '".$varr."'";
}
}
$qry = $qb->select('u')
->from('Application\Entity\Usermain','u')
->where($whereStr)
->getQuery()
->getResult();
return $qry;
}
}
Now I can access
$udata = $this->em()->getRepository('Application\Entity\Usermain')->customFind(array('userEmail' => 'subh.laha#gmail.com'));
But Not
$udata = $this->em()->getRepository('Application\Entity\Usermain')->findOneBy(array('userEmail' => 'subh.laha#gmail.com'));
Why? I have already written code by using doctrine defined methods. What can I do now?
I believe you are getting this error because you have overridden the repository's constructor method but aren't calling the parent constructor so required parameters aren't being properly set.
I think your code is not correct, You can use the below query instead of writing complex custom object.
$query = $this->getEntityManager()->createQueryBuilder()
->select('U.id,U.name')
->from('Application\Entity\StudentClass', 'U')
->where('U.pkStudentClass = :pkStudentClass')
->setParameter('pkStudentClass', 1)
->setMaxResults(20);
->orderBy('id', 'DESC')
->getQuery();
$result = $query->getScalarResult();
There are several problems exist in your approach;
I think trying to access the service locator's itself in an entity repository is bad idea. You shouldn't need service container in repository level.
The second detail is, when extending any class, you need to check out, read and respect the signature of the parent. In your case, you're overriding the parent's __construct. Calling parent::__construct() may seems like a solution but it's not. You'll soon realize that you also need a custom repository factory to pass additional arguments to constructor while keeping the current functionality. No way.
This is more important than others: you believe that $this->sl->createQueryBuilder() returns query builder instance. Theoretically seems like working but $this->sl is not service locator, service locator doesn't knows anything about query builders, it's just EntityManager instance which passed to your constructor.
Try this:
<?php
namespace Application\Entity\Repositories;
use Doctrine\ORM\EntityRepository;
class UsermainRepository extends EntityRepository
{
public function customFind($arr)
{
// Just pass an alias for your entity
$qb = $this->createQueryBuilder('u');
$whereStr = '';
if (count($arr)) {
foreach ($arr as $kvarr => $varr) {
$whereStr .= "u.$kvarr = '".$varr."'";
}
}
return $qb->where($whereStr)
->getQuery()
->getResult();
}
}
Finally, in your Application\Entity\Usermain entity, you'll also need telling about your custom repository to doctrine since you don't want to use default EntityRepository :
namespace Application\Entity;
/**
* #ORM\Entity(repositoryClass="Application\Entity\Repositories\UsermainRepository")
*/
class Usermain
{
}
Now in your controller (or service) level, you can test:
$em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
$repo = $em->getRepository('Application\Entity\Usermain');
// repo is a UsermainRepository instance
// this should work:
$udata = $repo->customFind(array('userEmail' => 'subh.laha#gmail.com'));
// this should also work
$udata = $repo->findOneBy(array('userEmail' => 'subh.laha#gmail.com'));
I strongly recommend carefully reading of Working With Objects section of the documentation before diving into deeps.

Manually writing DQL

I am trying this part in the Doctrine Documentation wherein you can:
Manually writing DQL
For you SQL buffs, we didn't forget about you. You can optionally write your DQL queries manually and parse them in to a Doctrine_Query instance or just execute them.
$dql = "FROM User u, u.Phonenumbers p";
$q = Doctrine_Query::create()->parseQuery($dql);
Or you can just execute them by using the query() method of Doctrine_Query.
$dql = "FROM User u, u.Phonenumbers p";
$q = Doctrine_Query::create()->query($dql);
Yet I'm having difficulties since I've encountered the following error:
Attempted to load class "Doctrine_Query" from namespace "AppBundle\Controller".
Did you forget a "use" statement for another namespace?
Could you please help me with this?
<?php
namespace AppBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use AppBundle\Entity\TblProduct;
class DefaultController extends Controller
{
/**
* #Route("/", name="homepage")
*/
public function indexAction()
{
$products = "SELECT * FROM TblProduct";
$q = Doctrine_Query::create()->query($products);
if (!$products) {
throw $this->createNotFoundException(
'No products registered yet.'
);
}
return $this->render('default/index.html.twig', array('products' => $products));
}
This is part of Doctrine 1.2 and not Doctrine 2.5. In the latest version you would just create queries in the Doctrine Query Language with createQuery().
<?php
$dql = "FROM User u, u.Phonenumbers p";
$query = $em->createQuery($dql);
$users = $query->getResult();
Alternatively you can write Native SQL.

PHP: Symfony2 MySQL SELECT query in controler

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
}

Laravel 4 - Using Eloquent Models in a custom library class

I made a library class that I am using for some common functions not provided by Laravel. It's been loaded into /config/app.php under the 'aliases' array, so that shouldn't be the problem.
When I call a method from my class ("InfoParse"), my conroller returns a blank page. I think this has to do with the fact that I'm calling a method from the library which uses Eloquent to interface with the database. I tried adding
use Illuminate\Database\Eloquent\Model;
to the top of the file, but that didn't help either.
Is there a specific way I should be setting up my class file so I can use either the DB:: class or Eloquent class?
Below is the function in question:
/**
* Check to see if this student is already recorded in our student table.
* If not, add the entry, then return true.
* #param int $cwid
* #return boolean
*/
public static function checkStudentTableRecords($cwid)
{
if(Student::where('cwid', '=', $cwid)->count() != 0)
{
return TRUE;
}
else
{ ##insert the student into our student table
$studentInfo = self::queryInfoFromCWID($cwid);
$studentEntry = new Student;
$studentEntry->cwid = $cwid;
$studentEntry->fName = $studentInfo['fName'];
$studentEntry->lName = $studentInfo['lName'];
$studentEntry->email = $studentInfo['email'];
$studentEntry->save();
return TRUE;
}
}
(note: the self::queryInfoFromCWID() function is calling a function defined earlier in the class)
After some investigation, it turns out I need to format my Eloquent Model calls like this:
if(\Student::where('cwid', '=', $cwid)->count() != 0)
...
$studentEntry = new \Student;
The backslash is necessary to avoid namespace collision within the Laravel4 application.

Categories