I'm having trouble executing a Doctrine DQL Query. This is the error it gives me.
Doctrine\Common\Annotations\AnnotationException: [Syntax Error] Expected PlainValue,
got 'integer' at position 13 in property Base\Session::$lifetime.
My code looks like this:
$query = $em->createQuery("SELECT s FROM Base\Session s WHERE s.session = \"$id\"");
Where $id is the current session_id. My Model looks like:
namespace Base;
/** #Entity #Table(name="session") */
class Session extends Skeleton {
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/** #Column(length=32) */
protected $session;
/** #Column(type=integer) */
protected $lifetime;
/** #Column(type=integer) */
protected $modified;
/** #Column(type="text") */
protected $data;
}
You have two errors in this:
You have to double quote your annotations, i.e. #Column(type="integer") not #Column(type=integer). Doctrine\Common\Annotations\AnnotationException is thrown when your mapping is wrong. This has nothing to do with the query.
Your query should use prepared statements, i.e.
$query = $em->createQuery("SELECT s FROM Base\Session s WHERE s.session = ?1");
$query->setParameter(1, $id);
Related
Trying to fetch all supplierUsers where the id is DISTINCT and hydrate the results.
The SQL query to get all the results would be the following
SELECT DISTINCT supplier_user_id FROM job_item_quote
The Query builder to fetch the above.
$qb = $this->createQueryBuilder('a')
->select('a.supplierUser')
->distinct(true);
$result = $qb->getQuery()->getResult();
Outputted getQuery(). Which is exactly what I'm looking for.
SELECT DISTINCT a.supplierUser FROM Project\Entities\JobItemQuote a
The error thrown when trying to fetch distinct users
[Semantical Error] line 0, col 18 near 'supplierUser,': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
I've tried adding joins in for supplierUser in hopes it would fix. Same error thrown.
JobItemQuote Entity
/**
* #ORM\Entity(repositoryClass="Project\Repositories\JobItemQuote\JobItemQuoteRepository")
* #ORM\Table(name="job_item_quote")
*/
class JobItemQuote extends BaseEntity
{
public static $joins = [
'supplierUser' => SupplierUser::class,
'jobItem' => JobItem::class
];
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #var int
*/
protected $id; // thekey
/**
* #ORM\ManyToOne(targetEntity="JobItem", inversedBy="quotes")
* #var JobItem
*/
protected $jobItem;
/**
* #ORM\ManyToOne(targetEntity="SupplierUser")
* #var SupplierUser
*/
protected $supplierUser;
....
}
SupplierUser Entity
/**
* #ORM\Entity(repositoryClass="Project\Repositories\SupplierUser\SupplierUserRepository")
* #ORM\Table(name="supplier_user")
*/
class SupplierUser extends User {
public static $joins = [
'supplier' => Supplier::class,
'supplierGroup' => SupplierGroup::class
];
/**
* #ORM\OneToOne(targetEntity="Supplier", inversedBy="supplierUser", cascade={"persist"})
* #var Supplier
*/
protected $supplier;
/**
* #ORM\ManyToOne(targetEntity="SupplierGroup")
* #var Group
*/
protected $supplierGroup;
....
}
Your need is to retrieve the list of supplierUsers associated with JobItemQuote, so you should make the query in JobItemQuoteRepository making a join with supplierUsers, you find bellow the example :
$qb = $this->createQueryBuilder('jiq')
->select('su')
->join(SupplierUser::class, 'su', Join::With, 'su.id = jiq.supplierUser')
->distinct(true)
;
$result = $qb->getQuery()->getResult();
By this query you will have the list of SupplierUser (distinctly) assoiated to JobsItemQuote.
I am trying to build an entity object for my relationship in Neo4j database with GraphAware Neo4j PHP OGM library using this simple method:
public function getRelationshipEntity($entityId) {
$repo = $this->entityManager->getRepository( Entity\Relationship\Fired::class );
return $repo->findOneById($entityId);
}
Here we have the entity classes, relationship first:
namespace Entity\Relationship;
use GraphAware\Neo4j\OGM\Annotations as OGM;
use Entity\Issue;
use Entity\Event;
/**
* #OGM\RelationshipEntity(type="FIRED")
*/
class Fired {
/**
* #OGM\GraphId()
*/
protected $id;
/**
* #OGM\StartNode(targetEntity="Entity\Event")
*/
protected $event;
/**
* #OGM\EndNode(targetEntity="Entity\Issue")
*/
protected $issue;
/**
* #var string
*
* #OGM\Property(type="string")
*/
protected $time;
/**
* #var string
*
* #OGM\Property(type="string")
*/
protected $eventName;
}
Then, start node:
namespace Entity;
use GraphAware\Neo4j\OGM\Annotations as OGM;
/**
* #OGM\Node(label="Event")
*/
class Event {
/**
* #OGM\GraphId()
*/
protected $id;
/**
* #var string
*
* #OGM\Property(type="string")
*/
protected $name;
}
..and end node:
namespace Entity;
use Doctrine\Common\Collections\ArrayCollection;
use GraphAware\Neo4j\OGM\Annotations as OGM;
/**
* #OGM\Node(label="Issue")
*/
class Issue {
/**
* #OGM\GraphId()
*/
protected $id;
/**
* #OGM\Property(type="string")
*/
protected $key;
/**
* #OGM\Property(type="string")
*/
protected $created;
/**
* #OGM\Property(type="string")
*/
protected $updated;
/**
* #OGM\Relationship(type="FIRED", direction="INCOMING", relationshipEntity="Entity\Relationship\Fired", collection=true)
* #var ArrayCollection
*/
protected $eventFires;
public function __construct($key) {
$this->key = $key;
$this->eventFires = new ArrayCollection();
}
public function __wakeup() {
$this->__construct($this->key);
}
/**
* #return ArrayCollection
*/
public function getEventFires() {
return $this->eventFires;
}
public function addEventFire(Entity\Relationship\Fired $eventFired) {
$this->eventFires->add($eventFired);
}
public function removeEventFire(Entity\Relationship\Fired $eventFired) {
$this->eventFires->removeElement($eventFired);
}
}
Apparently, what works really well for node entites, triggers the following error for relationships:
Fatal error: Call to undefined method GraphAware\Neo4j\OGM\Metadata\RelationshipEntityMetadata::hasCustomRepository() in /vendor/graphaware/neo4j-php-ogm/src/EntityManager.php
Any suggestion how I could workaround this? I even tried using EntityManager::createQuery() the following way:
public function getRelationships($eventName) {
$query = $this->entityManager->createQuery('MATCH (e:Event)-[f:FIRED{eventName: {eventName}}]->() RETURN e,f ORDER BY f.time');
$query->addEntityMapping('e', 'Entity\Event' );
$query->addEntityMapping('f', 'Entity\Relationship\Fired' );
$query->setParameter( 'eventName', $eventName);
return $query->execute();
}
But, apparently, addEntityMapping() doesn't work for relationship entities either! (It might be a feature though, not a bug):
Catchable fatal error: Argument 1 passed to GraphAware\Neo4j\OGM\Hydrator\EntityHydrator::hydrateNode() must implement interface GraphAware\Common\Type\Node, instance of GraphAware\Bolt\Result\Type\Relationship given, called in /vendor/graphaware/neo4j-php-ogm/src/Query.php on line 145 and defined in /vendor/graphaware/neo4j-php-ogm/src/Hydrator/EntityHydrator.php on line 232
So, I ended up that I can easily define and store relationship entities in Neo4J with this library but not sure how I could retrieve it easily with EntityManager, in the similar way I can do so with nodes.
Any help would be much appreciated!
As requested in comment below, these are GraphAware packages that I am using:
graphaware/neo4j-bolt 1.9.1 Neo4j Bolt Binary Protocol PHP Driver
graphaware/neo4j-common 3.4.0 Common Utilities library for Neo4j
graphaware/neo4j-php-client 4.8.0 Neo4j-PHP-Client is the most advanced PHP Client for Neo4j
graphaware/neo4j-php-ogm 1.0.0-RC6 PHP Object Graph Mapper for Neo4j
I want to make alternative way for making stored procedures by using Doctrine but I am stuck, could any one help me?
Example stored procedure to be formed:
CREATE PROCEDURE catalog_get_department_details(IN DepartmentName)
BEGIN
SELECT name, description
FROM
department
WHERE name = name;
Departments Entity:
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\departmentsRepository")
* #ORM\Table(name="departments")
*/
class departments
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $department_id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $description;
/**
* #ORM\OneToMany(targetEntity="categories",mappedBy="departments")
*/
private $categories;
function __construct()
{
$this->categories = new ArrayCollection();
}
public function getDepartmentId()
{
return $this->department_id;
}
public function setDepartmentId($department_id)
{
$this->department_id = $department_id;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #return mixed
*/
public function getDescription()
{
return $this->description;
}
/**
* #param mixed $description
*/
public function setDescription($description)
{
$this->description = $description;
}
The scenario is when the route is /index/departmentname/Regional ;
my DefaultController will capture Regional as parameter
DefaultController:
class DefaultController extends Controller
{
/**
* #Route ("/index/department/{department_name}")
*/
function departmentAction($department_name)
{
// accessing departmentsRepository
$categoriesRepository = $this->getDoctrine()->getManager()
->getRepository('AppBundle:departments');
$categoriesRepository->getDepartmentDetails($department_name);
}
departmentsRepository:
class departmentsRepository extends \Doctrine\ORM\EntityRepository
{
function getDepartmentDetails($departmentName)
{
$em=$this->getEntityManager()->getRepository('AppBundle:departments');
$qb=$em->createQueryBuilder('dep');
$qb->select('dep.name','dep.description');
$qb->where("dep.name=$departmentName");
When I call var_dump($qb->getDQL());die; it shows me exactly what I want:
SELECT dep.name, dep.description FROM AppBundle\Entity\departments dep WHERE dep.name=Regional
I then execute it by calling
$qb->getQuery()->execute();
But I receive the following error:
[Semantical Error] line 0, col 86 near 'Regional': Error: 'Regional'
is not defined.
Any idea what I'm doing wrong?
Your dep.name value isn't being escaped. You would expect the query to look like this instead:
WHERE dep.name='Regional'
But what you should be doing, and what is safer, is binding that to a parameter, like so:
$em = $this->getEntityManager()->getRepository('AppBundle:departments');
$qb = $em->createQueryBuilder('dep');
$qb->select('dep.name', 'dep.description');
$qb->where("dep.name = :departmentName");
$qb->setParameter('departmentName', $departmentName);
Doctrine will handle the escaping for you, and safely. This also allows you to avoid SQL injection attacks. Also since you are already in your departments repository you should be able to use the _em value as a shortcut, and also not have to re-specify the departments entity, like so:
$qb = $this->_em->createQueryBuilder('dep');
$qb->select('dep.name', 'dep.description');
$qb->where("dep.name = :departmentName");
$qb->setParameter('departmentName', $departmentName);
Side not, in your controller action you are calling the repository function but not actually saving the results to any variable.
I have a view on nomencladores schema called obtenerPaisesPorFabricanteProductoSolicitud. This is the content for the view:
SELECT
ps.id AS psid,
ps.nombre,
fps.id AS fpsid
FROM
(
(
nomencladores.pais ps
JOIN nomencladores.pais_fabricante_producto_solicitud pfps ON ((pfps.pais_id = ps.id))
)
JOIN negocio.fabricante_producto_solicitud fps ON (
(
pfps.fabricante_producto_solicitud_id = fps.id
)
)
);
I'm trying to map the view as follow:
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="nomencladores.obtenerPaisesPorFabricanteProductoSolicitud", schema="nomencladores")
*/
class ObtenerPaisesPorFabricanteProductoSolicitud
{
/**
* #ORM\Id
* #ORM\Column(name="psid", type="integer", nullable=false, unique=true)
*/
protected $ps;
/**
* #ORM\Column(name="fpsid", type="integer")
*/
protected $fps;
/**
* #ORM\Column(name="nombre", type="string")
*/
protected $nombre;
public function getPs()
{
return $this->ps;
}
public function getFps()
{
return $this->fps;
}
public function getNombre()
{
return $this->nombre;
}
}
But any time I run this code on it:
$ent = $em->getRepository("AppBundle:ObtenerPaisesPorFabricanteProductoSolicitud")->findBy(
array(
"fps" => $entF->getId()
)
);
I got this result:
An exception occurred while executing 'SELECT t0.psid AS psid1,
t0.fpsid AS fpsid2, t0.nombre AS nombre3 FROM
nomencladores.obtenerPaisesPorFabricanteProductoSolicitud t0 WHERE
t0.fpsid = ?' with params [22]:
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "nomencladores.obtenerpaisesporfabricanteproductosolicitud" does not
exist LINE 1: ...d1, t0.fpsid AS fpsid2, t0.nombre AS nombre3 FROM
nomenclado...
If I remove the annotations then the error transform on this:
"Class
"AppBundle\Entity\ObtenerPaisesPorFabricanteProductoSolicitud"
is not a valid entity or mapped super class."
Why Doctrine2 or Symfony tries to execute the query instead go through the view? How I can execute the view from Symfony2/Doctrine2 side?
EDIT
As a side note I'm using PostgreSQL as DB and it haves several squemas, in this case I wrote the view at nomencladores schemas but I tried putting also in public schema and none works, apparently Doctrine doesn't find the view on the schema
I am using both Doctrine2 and Symfony2 but Symfony2 fails me at a task I am able to accomplish in Doctrine2 (the 'standalone' version).
In Doctrine2:
I have 2 classes, Outcome, Ticket as such:
namespace Entity;
/** #Entity #Table(name="tickets") */
class Ticket {
/** #Id #Column(type="integer") #GeneratedValue(strategy="AUTO") */
private $id;
/** #Column(type="string", length=100) */
private $title;
/** #OneToMany(targetEntity="Outcome", mappedBy="ticket") */
private $outcomes;
/* with setters and getters for title and outcomes */
public function __toString() {
return $this->getTitle().' ('.$this->getId().')';
}
public function __construct () {
$this->outcomes=new \Doctrine\Common\Collections\ArrayCollection();
}
}
and
namespace Entity;
/** #Entity #Table(name="outcomes") */
class Outcome {
/** #Id #Column(type="integer") #GeneratedValue(strategy="AUTO") */
private $id;
/** #Column(type="string", length=100) */
private $text;
/** #ManyToOne(targetEntity="Ticket", inversedBy="outcomes") #JoinColumn(nullable=false) */
private $ticket;
public function __toString() {
return $this->getText().' ' .' ('.$this->getId().')';
}
}
in my index.php I use
$query = $em->createQuery ("SELECT t,o FROM Entity\Ticket t LEFT JOIN t.outcomes o WHERE t.id=1");
$query->useResultCache(true);
$tickets_2 = $query->execute();
$ticket_2 = $tickets_2[0];
$amount=count($ticket_2->getOutcomes());
echo $ticket_2." --ticket\n";
echo $amount." --outcomes\n";
and I get the correct output
now in Symfony2 I use the following definitions for the entities:
namespace test\DemoBundle\Entity;
/** #orm:Entity #orm:Table(name="tickets") */
class Ticket {
/** #orm:Id #orm:Column(type="integer")
#orm:GeneratedValue(strategy="AUTO") */
private $id;
/** #orm:Column(type="string", length=100) */
private $title;
/** #orm:OneToMany(targetEntity="Outcome", mappedBy="response") */
private $outcomes;
...
}
namespace test\DemoBundle\Entity;
/** #orm:Entity #orm:Table(name="outcomes") */
class Outcome {
/** #orm:Id #orm:Column(type="integer") #orm:GeneratedValue(strategy="AUTO") */
private $id;
/** #orm:Column(type="string", length=100) */
private $text;
/** #orm:ManyToOne(targetEntity="Ticket", inversedBy="outcomes") #orm:JoinColumn(nullable=false) */
private $ticket;
....
}
now, I've set up a controller with a test function:
namespace test\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use test\DemoBundle\Entity\Ticket as Ticket;
use test\DemoBundle\Entity\Outcome as Outcome;
class TicketController extends Controller {
...
public function testAction() {
$em = $this->get('doctrine.orm.entity_manager');
$query = $em->createQuery ("SELECT t, o
FROM test\DemoBundle\Entity\Ticket t
LEFT JOIN t.outcomes o
WHERE t.id=1");
$query->useResultCache(true);
$tickets_2 = $query->execute();
$ticket_2 = $tickets_2[0];
$amount=count($ticket_2->getOutcomes());
$prepared_result=$ticket_2." --ticket ".$amount." --outcomes ";
$response = new Response($prepared_result);
return $response;
}
}
at this point I get an error while trying to execute the last query like so:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE t0_.id = 1' at line 1
from the webdebugger I get the following syntax from PDO:
SELECT t0_.id AS id0,
t0_.title AS title1,
o1_.id AS id2,
o1_.text AS text3,
o1_.ticket_id AS ticket_id4
FROM tickets t0_
LEFT JOIN WHERE t0_.id = 1
so I guess I am missing something after the LEFT JOIN so that's why I am gettint the error in the first place?
What am I doing wrong?/What should I do?