Transform SQL to DQL - sql

I tried to transform a SQL function into DQL but i always have errors...
I have 3 tables
/**
* #ORM\Entity(repositoryClass=ArticleRepository::class)
*/
class Article
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $title;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(type="string", length=255, unique=true, nullable=true)
*/
private $slug;
/**
* #ORM\Column(type="boolean", options={"default":"0"})
*/
private $isItalian = false;
/**
* #ORM\Column(type="text")
*/
private $content;
/**
* #ORM\ManyToMany(targetEntity=Contact::class, inversedBy="viewedArticles")
*/
private $contact;
}
class Contact implements UserInterface, JsonSerializable
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
protected ?int $id = null;
/**
* #ORM\Column(type="string", length=255, unique=true)
*/
protected ?string $email = null;
/**
* #ORM\ManyToMany(targetEntity=Article::class, mappedBy="contact")
*/
private $viewedArticles;
}
And a many to many table
article_contact (a manyToMany table) with article_id and contact_id
i want to get all articles who are not in the article_contact table (it's all the articles who're not viewed by the contact)
I tried this request in SQL and it works, but it return an array and i need to return an object to use it in Symfony
$conn = $entityManager->getConnection();
$sql = 'SELECT *
FROM article
LEFT JOIN article_contact
ON article.id = article_id
AND contact_id = '.$id.'
WHERE article.is_italian = '.$isItalian.'
AND article_id IS NULL';
$stmt = $conn->prepare($sql);
$result = $stmt->executeQuery();
return $result->fetchAllAssociative();
DQL request :
return $this->createQueryBuilder('a')
->leftJoin('a.contact', 'contact')
->where('a.isItalian = 0')
->andWhere('contact = 1')
->andWhere('contact.viewedArticles IS NULL')
->getQuery()
->getResult()
;
it's the ->andWhere('contact.viewedArticles IS NULL') part who's not working, i have this error
[Semantical Error] line 0, col 113 near 'viewedArticles': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.

The answer is
$qb->select('a')
->from(Article::class,'a')
->leftJoin('a.contact', 'contact', 'WITH', 'contact.id = :id')
->setParameter('id', $contactId)
->andWhere('a.isItalian = :isItalian')
->setParameter('isItalian', $isItalian)
->groupBy('a.id')
->having('COUNT(contact.id) = 0')
;
return $qb->getQuery()->getResult();
Thanks to Will B. !

Related

ORM ManyToOne Unidirectional fetchAll Object array does not render in phtml Zend Framework 3

The application has built in ZF3. I have to entity with ManyToOne relationship using ORM. The issue is when i render through controller and and if fetch data via index it gives okay result but when i assign that to view and trying to render at phtml it throws an error/
/**
* Subscriptions
*
* #ORM\Table(name="subscriptions", indexes={#ORM\Index(name="CUST_ID", columns={"customer_id"}),#ORM\Index(name="SUB_TYPE_ID", columns={"subscription_type_id"})})
* #ORM\Entity
*/
class Subscriptions
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \Application\Entity\SubscriptionType
*
* #ORM\ManyToOne(targetEntity="Application\Entity\SubscriptionType")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="subscription_type_id", referencedColumnName="id")
* })
*/
protected $subscriptionType;
//set
public function setSubscriptionType(\Application\Entity\SubscriptionType $subscriptionType = null)
{
$this->subscriptionType = $subscriptionType;
return $this;
}
//get
public function getSubscriptionType(){
return $this->subscriptionType;
}
//other setter and getter....
}
Another Class
/**
* SubscriptionType
*
* #ORM\Table(name="subscription_type")
* #ORM\Entity
*/
class SubscriptionType
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="description", type="text", length=65535, nullable=true)
*/
private $description;
/**
* Get id
*enter code here
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set description
*
* #param string $description
*
* #return SubscriptionType
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
}
Now at controller i have wrote...
//some initiations
class AdminController extends AbstractActionController
{
//other initiations including __construct....
public function usersubscriptionsAction(){
$this->subscriptions = $this->entityManager->getRepository(Subscriptions::class)->findAll();
/*
foreach($this->subscriptions as $subscription){
//if i am checking with this it gives proper output
echo $subscription->getSubscriptionType()->getDescription();
die();
}
*/
return new ViewModel(
array(
"subscriptions" => $this->subscriptions
)
);
}
}
///i have phtml file
<?php foreach ($subscriptions as $subscription): ?>
//below line throwing an error
<?php echo $subscription->getSubscriptionType()->getDescription(); ?>
<?php endforeach; ?>
when i run it throw an erro message
Call to a member function getDescription() on null
You've got the relation mapping incorrect. Corrected the property annotation below:
/**
* #var \Application\Entity\SubscriptionType
*
* #ORM\ManyToOne(targetEntity="Application\Entity\SubscriptionType")
* #ORM\JoinColumn(name="subscription_type_id", referencedColumnName="id")
*/
protected $subscriptionType;
You had
/**
* #var \Application\Entity\SubscriptionType
*
* #ORM\ManyToOne(targetEntity="Application\Entity\SubscriptionType")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="subscription_type_id", referencedColumnName="id")
* })
*/
protected $subscriptionType;
The #ORM\JoinColumns is used for when you have a join with multiple columns, please see the docs. Though, the most common usage of JoinColumns is for a JoinTable.

Symfony, Invalid data (AppBundle\Entity\InterventionType), expected "AppBundle\Entity\Intervention

I'm trying to insert a line to my base, from postman to a local api with some foreign keys and I have this bug :
"message": "Invalid data \"1\"(AppBundle\Entity\InterventionType),
expected \"AppBundle\Entity\Intervention\"."
It pointed to the bad Entity and I don't know why. I'm targeting "Intervention", and doctrine seems to go in InterventionType...
Here's my entity :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use \DateTime;
/**
* InterventionRapport
*
* #ORM\Table(name="intervention_rapport", options={"comment":"Table répertoriant les retours associés aux différentes interventions (commerciales et techniques) - Egalement utilisée pour rémunérer les techniciens et calculer les frais kilométriques tech/com"})
* #ORM\Entity
*/
class InterventionRapport
{
/**
* #var integer
* #ORM\OneToOne(targetEntity="AppBundle\Entity\Intervention")
* #ORM\JoinColumn(name="intervention", nullable=false)
*/
private $intervention;
/**
* #var string
*
* #ORM\Column(name="message", type="text", nullable=true)
*/
private $message;
/**
* #var integer
*
* #ORM\Column(name="statut", type="integer", nullable=false)
*/
private $statut = '0';
/**
* some other things
**/
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
and the entity targeted with foreign key:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Intervention
*
* #ORM\Table(name="intervention")
* #ORM\Entity
*/
class Intervention
{
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\InterventionType")
* #ORM\JoinColumn(name="type", nullable=false)
*/
private $type;
/**
* Some other things
**/
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
}
And finally my json:
{
"message": "Steuh plait !",
"statut": 1,
"datemaintenanceprevue": "2017-08-23T15:00:00+00:00",
"heuresintervention": 1,
"heurestrajet": 0.5,
"kmtrajet": 27,
"deleted": 0,
"intervention": 1,
"id": 2
}
Please help, what am I doing wrong?
I found a slution by changing the way I created the line. I don't put the intervention id directly, I pass it into the url :
class RapportController extends Controller
{
/**
* #Rest\Post(
* path = "/reports/intervention={id}",
* name = "app_report_create"
* )
* #Rest\View(StatusCode = 201)
* #ParamConverter("report", converter="fos_rest.request_body")
*/
public function createAction(Request $request, InterventionRapport $report)
{
$em = $this->getDoctrine()->getManager();
$intervention = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Intervention')
->find($request->get('id'));
//$report = new \DateTime($datemaintenanceprevue);
$report->setIntervention($intervention);
$em->persist($report);
$em->flush();
return $report;
}
So, I don't need to post the intervention id from my client' json :
{
"message": "Steuh plait !",
"statut": 1,
"datemaintenanceprevue": "2017-08-23T15:00:00+00:00",
"heuresintervention": 1,
"heurestrajet": 0.5,
"kmtrajet": 27,
"deleted": 0,
"id": 2
}
I don't know if it's the correct way to do it, but it solved the problem. Hope it can help someone else.

How to retrieve entities without their entities associated?

My code is
$bars = $em->getRepository('AppBundle:Bar')->findAll();
And the Entity
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=45, nullable=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="location", type="string", length=45, nullable=true)
*/
private $location;
/**
* #var string
*
* #ORM\Column(name="zipcode", type="string", length=45, nullable=true)
*/
private $zipcode;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=45, nullable=true)
*/
private $description;
/**
* #ORM\OneToMany(targetEntity="Waiter", mappedBy="bar", fetch="EXTRA_LAZY")
*/
protected $waiters;
/**
* #ORM\OneToMany(targetEntity="Table_", mappedBy="bar", fetch="EXTRA_LAZY")
*/
protected $tables;
/** #ORM\OneToMany(targetEntity="Stock_food", mappedBy="bar", fetch="EXTRA_LAZY") */
private $stockfoods;
/** #ORM\OneToMany(targetEntity="Stock_drink", mappedBy="bar", fetch="EXTRA_LAZY") */
private $stockdrinks;
I want retrieve only the bars entity without their entities associated (Waiter, Table_, Stock_drink, Stock_food).
The response is all data but I only need name, location, zipcode and descriptión.
Thanks in advance!!!
Helloo
I found the solution!! I'm using raw SQL queries, DBAL
$conn = $em->getConnection();
$sql = 'SELECT * FROM Bar';
$stmt = $conn->prepare($sql);
$stmt->execute();
$bars = $stmt->fetchAll();
Thankss!!

Doctrine2 OneToMany relation is null within the same request

So i have the following mapping:
Order entity
/**
* Order
*
* #ORM\Table(name="`order`")
* #ORM\Entity
*/
class Order
{
/**
* #var integer
*
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
// ... //
/**
* #ORM\OneToMany(targetEntity="OrderItem", mappedBy="order")
*/
private $items;
// ... //
OrderItem entity
/**
* OrderItem
*
* #ORM\Table(name="order_item")
* #ORM\Entity
*/
class OrderItem
{
/**
* #var integer
*
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
// ... //
/**
* #ORM\ManyToOne(targetEntity="Order", inversedBy="items")
* #ORM\JoinColumn(referencedColumnName="id")
*/
private $order;
// ... //
The problem I experience is when I try to dump $order->getItems() after flushing it remains NULL. Eveything is inserted fine to the database with the correct ids and when I try to get the order in the NEXT request it does contain items in $order->getItems() so no doubt it does work.
But it does not work (giving NULL) with the same request.
Look at the code below:
$manager = $this->getDoctrine()->getManager();
$order = new Order();
$orderItem = new OrderItem();
$orderItem
->setOrder($order)
;
$manager->persist($order);
$manager->persist($orderItem);
dump($order->getItems()); // returns NULL
// but in the next request it will contain items
So how can I get those items within the same request? I need to generate the order and return the items... any idea?
In class OrderItem, maybe.
public setOrder(Order $order)
{
$order->addItem($this);
$this->ordder = $order;
}

Doctrine insert table using joined table entities as reference

I have spent the last day trying to find a solution to a problem that I am having and now turn to you to see if you can offer some advice.
Ill start with the table and then the entity
I have three tables,
table_a
table_b
table_c
each table row has a unique id
table_c contains a reference to table_a_id and to table_b_id
This reference should be unidirectional as table_a and table_b have no need to ever know of table_c's existence.
Also, there is no cascading, if an id from table_a or table_b does not exist, then table_c should not be able to insert a row.
ok, now for entities. (I am going to cut out irrelevant code to keep it short)
Entity A defines table_a
/**
* A
* #ORM\Entity(repositoryClass="Sample\Bundle\MyBundle\Entity\ARepository")
* #ORM\Table("table_a")
*/
class A
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
* #param string $name
* #return A
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
* #return string
*/
public function getName()
{
return $this->name;
}
}
Entity B defines table_b
/**
* B
*
* #ORM\Table("table_b")
* #ORM\Entity
*/
class B
{
/**
* #var integer
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
* #param string $name
* #return B
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
* #return string
*/
public function getName()
{
return $this->name;
}
}
Entity C maps table_c and has many to one relationships with table_a and table_b
/**
* C
*
* #ORM\Table("table_c")
* #ORM\Entity(repositoryClass="Sample\Bundle\MyBundle\Entity\CRepository")
*/
class PricesAverage
{
/**
* #var integer
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \Sample\Bundle\MyBundle\Entity\A
* #ORM\ManyToOne(targetEntity="Sample\Bundle\MyBundle\Entity\A", inversedBy="id")
* #ORM\JoinColumn(name="a_id",unique=false)
*/
private $a;
/**
* #var \Sample\Bundle\MyBundle\Entity\B
* #ORM\ManyToOne(targetEntity="Sample\Bundle\MyBundle\Entity\B", inversedBy="id")
* #ORM\JoinColumn(name="b_id",unique=false)
*/
private $b;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #return A
*/
public function getA() {
return $this->a;
}
/**
* #param A $a
* #return $this
*/
public function setA($a) {
$this->a = $a;
return $this;
}
/**
* #return B
*/
public function getB() {
return $this->b;
}
/**
* #param B $b
* #return $this
*/
public function setB($b) {
$this->b = $b;
return $this;
}
}
No what I do is the following. (this is just simplified logic but it is the same process)
$days = 5;
$aCollection = {get collection of A's)
for($i = 0,$i<$days,$i++){
foreach($aCollection as $a){
$b = {get a single b}
$c = new C();
$c->setA($a)
->setB($b);
{use doctrine to persist and flush $c}
}
}
What is happening is that on the first insert the id for a is correct, but on the second insert, doctrine seems to think that competitor is a new entity and tries to persist and create a new id.
I have dumped my collection without activating the doctrine insert and I see that the id on A is correct, I then do the same thing after doctrine and find that doctrine is somehow clearing away my object.
How can I resolve this?
UPDATE:
I resolved this issue.
The problem that I was having is that the related entity was being removed from the entity manager after I did my batch insert.
The was a result of doing clear after every flush.
I moved clear to the end of the process so I flush as much as I need but only clear once.