I have two entities:
1)
/**
* Post
*
* #ORM\Table(name="article")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository")
*/
class Post
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
...
/**
* #var string
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Image", cascade={"persist"}, fetch="EAGER")
* #ORM\JoinColumn(name="image", referencedColumnName="id", nullable=true)
*/
private $image;
}
and 2)
/**
* Image
*
* #ORM\Table(name="image")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ImageRepository")
*/
class Image
{
/**
* #var int
*
* #ORM\Column(name="id", type="string", length=40)
* #ORM\Id
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="small", type="blob", nullable=true)
*/
private $small;
/**
* #var string
*
* #ORM\Column(name="medium", type="blob", nullable=true)
*/
private $medium;
/**
* #var string
*
* #ORM\Column(name="large", type="blob", nullable=true)
*/
private $large;
...
}
Both entities have getters and setters.
The controller sets the post to update
$requestFile = $request->files->get('image');
$em = $this->getDoctrine()->getManager();
$record = $em->getRepository('AppBundle:Post')->find($id);
if (!$record) {
throw $this->createNotFoundException(
'No product found for id '.$record
);
}
$record->setTitle($request->request->get('title'));
$record->constructAlias($request->request->get('title'));
...
if ($request->files->get('image')) {
// check if image already exists
$imgGeneratedId = sha1_file($request->files->get('image')->getPathName());
$imageRepo = $this->getDoctrine()->getRepository('AppBundle:Image');
$isPresent = $imageRepo->find($imgGeneratedId);
$image = $isPresent;
if (!$isPresent) {
$image = new Image();
$image->setId($imgGeneratedId);
$image->setLarge(file_get_contents($request->files->get('image')->getPathName()));
$mediumImage =
...
$em->persist($image);
}
$record->setImage($em->getReference('AppBundle:Image', $image->getId()));
}
$em->persist($record);
$em->flush();
Please ignore any syntax errors or other kinds; there are none.
The problem is that even if image already exists it is trying to create one which causes error in database. So, in order to avoid this I used getReference, but this causes other issues.
So, how can I force doctrine, not to insert an image if already exists and just set the article image with the image id?
Thanks.
Related
I have an Angular4 app working with Symfony3/Doctrine2 Rest Api.
Both in Angular and Symfony, I have those entities :
Table
TableNode
Node
The relation between Table and Node is :
Table (OneToMany) TableNode (ManyToOne) Node
What is a "ManyToMany" relation with attributes.
In the Angular app, I create a new Table (form a TableModel that has exactly the same properties that the Table entity in the Symfony app).
This Table contains several Node entities that come from the Api (so they already exists in my database).
What I want is to create a new Table that contains new TableNode entities and each TableNode should contain existing Node entities.
When I want to save my table within the db, I call my Api through a Put action :
/**
* PUT Route annotation
* #Put("/tables")
*/
public function putTableAction(Request $request)
{
$em = $this->getDoctrine()->getManager('psi_db');
$serializer = $this->container->get('jms_serializer');
$dataJson = $request->query->get('table');
$table = $serializer->deserialize($dataJson, Table::class, 'json');
// Here, my $table has no id (that's ok), the TableNode subentity has no id (ok) and my Node subentity already have an id (because they come from the db)
$em->persist($table);
// Here, my $table has a new id (ok), my TableNode has a new id (ok) BUT my Node subentity have a NEW id, so it will be duplicated
$em->flush();
$view = $this->view();
$view->setData($table);
return $this->handleView($view);
}
I tried to use $em->merge($table) instead of $em->persist($table) and my node subentities keep there own id (so they may not be duplicated within the flush) BUT the table and tableNode have no id (null) and are not persisted.
The only solution I found is to loop through the TableNode entities, retrieve the Node entity from the database and do a tableNode->setNode :
$tns = $table->getTableNodes();
foreach ($tns as $tn) {
$nodeId = $tn->getNode()->getId();
$dbNode = $nodeRepo->find($nodeId);
$tn->setNode($dbNode);
}
But it's not a good solution because I make a db search within a loop and a table could contains more than a hundred of TableNode/Node so it might take a lot of resources.
Does anyone have a cleaner solution ?
Thanks.
edit : add classes
Table :
/**
* Table_
* Doctrine "Table" is a reserved name, so we call it Table_
*
* #ORM\Table(name="psi_table")
* #ORM\Entity(repositoryClass="AppBundle\Repository\Table_Repository")
*
* #ExclusionPolicy("all")
*/
class Table_
{
public function __construct()
{
$this->tNodes = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Expose
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*
* #Expose
*/
private $name;
/**
* #var \stdClass
*
* #ORM\Column(name="author", type="object", nullable=true)
*
* #Expose
*/
private $author;
/**
* #var \stdClass
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\TableNode", mappedBy="table", cascade={"persist"})
*
* #Expose
* #Type("ArrayCollection<AppBundle\Entity\TableNode>")
* #SerializedName("tNodes")
*/
private $tNodes;
}
TableNode :
/**
* TableNode
*
* #ORM\Table(name="psi_table_node")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TableNodeRepository")
*
* #ExclusionPolicy("all")
*/
class TableNode
{
public function __construct($table = null, $node = null, $position = null)
{
if($table) $this->table = $table;
if($node) $this->node = $node;
if($position) $this->position = $position;
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Expose
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="position", type="integer")
*
* #Expose
*/
private $position;
/**
* #var string
*
* #ORM\Column(name="groupSocio", type="string", nullable=true)
*
* #Expose
* #SerializedName("groupSocio")
*/
private $groupSocio;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Table_", inversedBy="tNodes", cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*
* #Expose
* #Type("AppBundle\Entity\Table_")
*/
private $table;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Node", inversedBy="tables", cascade={"persist", "merge"})
* #ORM\JoinColumn(nullable=false)
*
* #Expose
* #Type("AppBundle\Entity\Node")
*/
private $node;
}
Node :
/**
* TableNode
*
* #ORM\Table(name="psi_table_node")
* #ORM\Entity(repositoryClass="AppBundle\Repository\TableNodeRepository")
*
* #ExclusionPolicy("all")
*/
class TableNode
{
public function __construct($table = null, $node = null, $position = null)
{
if($table) $this->table = $table;
if($node) $this->node = $node;
if($position) $this->position = $position;
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Expose
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="position", type="integer")
*
* #Expose
*/
private $position;
/**
* #var string
*
* #ORM\Column(name="groupSocio", type="string", nullable=true)
*
* #Expose
* #SerializedName("groupSocio")
*/
private $groupSocio;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Table_", inversedBy="tNodes", cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*
* #Expose
* #Type("AppBundle\Entity\Table_")
*/
private $table;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Node", inversedBy="tables", cascade={"persist", "merge"})
* #ORM\JoinColumn(nullable=false)
*
* #Expose
* #Type("AppBundle\Entity\Node")
*/
private $node;
}
Submitted data (example) :
{"tNodes":[{"id":0,"position":0,"groupSocio":"group1","node":{"id":683,"frontId":"1502726228584","level":"synusy","repository":"baseveg","name":"A synusy from my Angular app!","geoJson":{"type":"FeatureCollection","features":[{"type":"Feature","properties":[],"geometry":{"type":"Point","coordinates":[-10.0634765625,42.0982224112]}}]},"lft":1,"lvl":0,"rgt":2,"children":[{"id":684,"frontId":"1502726228586","level":"idiotaxon","repository":"baseflor","name":"poa annua","coef":"1","geoJson":{"type":"FeatureCollection","features":[{"type":"Feature","properties":[],"geometry":{"type":"Point","coordinates":[-10.0634765625,42.0982224112]}}]},"lft":1,"lvl":0,"rgt":2,"validations":[{"id":171,"repository":"baseflor","repositoryIdTaxo":"7075","repositoryIdNomen":"50284","inputName":"poa annua","validatedName":"Poa annua L."}]}],"validations":[]}}]}
The purpose putTableAction is to:
create new instances of Table_
create new instance of TableNode
do nothing with Node
It means that:
1.You do not need to submit any details of Node. Id field is enough:
{"tNodes":[{"id":0,"position":0,"groupSocio":"group1","nodeId": 683}]}
2.You can add one more field to TableNode, called $nodeId, and map it with "node" field in DB. The purpose of this field is to simplify deserialization, in all other places you can use $node field.
/**
* #var integer
*
* #ORM\Column(name="node", type="integer")
*
* #Expose
*/
private $nodeId;
I'm working on Symfony 2.7. I have to create a mail client to retrieve and send mails from the mail server (IMAP protocol); to do this, I used the php-imap classes, with a bundle (included with composer). But I'm not sure about the way I should use them : Do I extend the classes to represent my Mail and Mailbox objects, or should I create new classes from scratch ?
I don't want to manipulate IMAP straight from my controllers, I think it would be too long to process. Is that right?
Is it a good idea to create a "watcher" (periodic command executed by cron) to parse new mails every 2 minutes or so, create new mails entity from them, and send the waiting ones?
Could I do that while extending the php-imap classes? This way I would use one class only? But wouldn't that be too heavy to store for the database ?
What's the correct way to fetch only new mails ? Do I have to use a specific function, like imap_check, or do I do that by a search criteria (like date from the last check) ? I tried with criteria "NEW", but that was unsuccessful.
Also, the mailboxes I have to parse are quite heavy. I tried to make a search in one of them with "ALL" criteria, but it's really long to process ! Am I doing it right ? Do I just have to be patient ?
Here's what I did for the "watcher" function :
use PhpImap\Mailbox as ImapMailbox;
class GetNewMailsCommand extends ContainerAwareCommand
{
$em = $this->getContainer()->get('doctrine')->getEntityManager();
$mailboxes = $em->getRepository('MIPMailBundle:MailBox')->findAllActive();
foreach ($mailboxes as $mailbox){
$imapBox = new ImapMailbox('{'.$mailbox->getServer().':143/notls/norsh/novalidate-cert}INBOX', $mailbox->getAdress(), $mailbox->getPassword());
if ($mailbox->getMails() == null || empty($mailbox->getMails())){
$mailsIds = $imapBox->searchMailbox('ALL');
if(!$mailsIds) {
$output->writeln($mailbox->getAdress() . " is empty");
}
} else {
$mailsIds = $imapBox->searchMailbox('NEW');
if(!$mailsIds) {
$output->writeln("No new mail for " . $mailbox->getAdress());
}
}
foreach ($mailsIds as $mailId){
$imapMail = $imapBox->getMail($mailId);
$mail = new Mail($mailbox, false);
$mail->setSubject($imapMail->subject);
$mail->setSender($imapMail->fromAddress);
$mail->setCc($imapMail->cc);
$mail->setBcc($imapMail->bcc);
$mail->setToString($imapMail->toString);
$mail->setContent($imapMail->textPlain);
$mail->setDate(new \DateTime($imapMail->date));
foreach ($imapMail->to as $toAddress){
$mail->addRecipient($toAddress);
}
$em->persist($mail);
}
}
$em->flush();
And here's my entities :
class MailBox
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var
*
* #ORM\OneToOne(targetEntity="\MIP\CRMBundle\Entity\Agency", inversedBy="mailBox", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
*/
private $user;
/**
* #var Agency
*
* #ORM\ManyToMany(targetEntity="\MIP\CRMBundle\Entity\Agency", inversedBy="mailBoxShared")
* #ORM\JoinTable(name="mailbox_shared")
*/
private $sharedTo;
/**
* #var
*
* #ORM\OneToMany(targetEntity="Mail", mappedBy="mailBox")
*/
private $mails;
/**
* #var boolean
*
* #ORM\Column(name="active", type="boolean")
*/
private $active;
/**
* #var string
*
* #ORM\Column(name="adress", type="string", length=255)
*/
private $adress;
/**
* #var string
*
* #ORM\Column(name="server", type="string", length=255)
*/
private $server;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var integer
*
* #ORM\Column(name="port", type="integer")
*/
private $port;
/**
* MailBox constructor.
*/
public function __construct()
{
$this->sharedTo = new ArrayCollection();
$this->mails = new ArrayCollection();
}
class Mail
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="sender", type="string", length=255)
*/
private $sender;
/**
* #var array
*
* #ORM\Column(name="recipients", type="json_array", nullable=true)
*/
private $recipients;
/**
* #var string
*
* #ORM\Column(name="toString", type="string", nullable=true)
*/
private $toString;
/**
* #var array
*
* #ORM\Column(name="cc", type="json_array", nullable=true)
*/
private $cc;
/**
* #var array
*
* #ORM\Column(name="bcc", type="json_array", nullable=true)
*/
private $bcc;
/**
* #var string
*
* #ORM\Column(name="subject", type="string", length=255, nullable=true)
*/
private $subject;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* #var string
*
* #ORM\Column(name="content", type="text", nullable=true)
*/
private $content;
/**
* #var
*
* #ORM\OneToMany(targetEntity="MIP\CRMBundle\Entity\File", mappedBy="mail", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="file_id", referencedColumnName="id", nullable=true)
*/
protected $files;
/**
* #var ArrayCollection
*/
private $attached;
/**
* #var MailBox
* #ORM\ManyToOne(targetEntity="MailBox", inversedBy="mails")
* #ORM\JoinColumn(name="mailBox_id", referencedColumnName="id")
*/
private $mailBox;
/**
* #var LabelSticker
*
* #ORM\ManyToMany(targetEntity="\MIP\MailBundle\Entity\LabelSticker", mappedBy="mails")
*/
private $labels;
/**
* #var boolean
*/
private $readed;
/**
* #var boolean
*/
private $sent;
/**
* Constructor
* #param MailBox $mailbox
* #param boolean $readed
*/
public function __construct($mailbox, $readed)
{
$this->files = new ArrayCollection();
$this->date = new \DateTime('now');
$this->mailBox = $mailbox;
$this->readed = $readed;
}
Thanks for your help !
I know, there are a lot of posts about this topic, but for me it is imposible to get the right solution.
I have 2 entities with the relationship many-to-many and in that relationship many colums (that means 3 entities). I have two questions:
The SQL is Lazy-loadinig, but I write "SELECT l, ul ...", so I want to select both tables. Why still Lazy-loading?? is There any config anywhere??
How can I show it in my Twig's Templates??
My entities are more or less like that:
Usuario:
/**
* Usuario
*
* #ORM\Table()
*/
class Usuario
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nombre", type="string", length=255)
*/
private $nombre;
...
/**
* #ORM\OneToMany(targetEntity="UsuarioLibro", mappedBy="usuario")
*/
private $libros;
public function __construct()
{
$this->libros = new ArrayCollection();
}
...
/**
* Get libros
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getLibros()
{
return $this->libros;
}
}
Libros:
/**
* Libro
*
* #ORM\Table()
*/
class Libro
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titulo", type="string", length=255)
*/
private $titulo;
...
/**
* #ORM\OneToMany(targetEntity="UsuarioLibro", mappedBy="libro")
*/
private $usuarios;
...
public function __construct()
{
$this->usuarios = new ArrayCollection();
}
...
/**
* Get usuarios
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsuarios()
{
return $this->usuarios;
}
}
UsuariosLibros (the relationship):
/**
* usuario_libro
*
* #ORM\Table(name="usuario_libro")
* #ORM\Entity
*/
class UsuarioLibro
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="tener", type="boolean", options={"default":0})
*/
private $tener;
/**
* #var integer
*
* #ORM\Column(name="leer", type="boolean", options={"default":0})
*/
private $leer;
/**
* #ORM\ManyToOne(targetEntity="usuario", inversedBy="libros")
*/
private $usuario;
/**
* #ORM\ManyToOne(targetEntity="libro", inversedBy="usuarios")
*/
private $libro;
public function __construct(Usuario $usuario, Libro $libro)
{
$this->usuario = $usuario;
$this->libro = $libro;
}
...
/**
* Get usuario
*
* #return \JavierGlez\Osprey\FrontendBundle\Entity\usuario
*/
public function getUsuario()
{
return $this->usuario;
}
/**
* Get libro
*
* #return \JavierGlez\Osprey\FrontendBundle\Entity\libro
*/
public function getLibro()
{
return $this->libro;
}
}
I can serch all the content with this SQL:
$query = $this->getEntityManager()
->createQuery(
"SELECT l, ul FROM JGOspreyFrontendBundle:Libro l
LEFT JOIN l.usuarios ul
LEFT JOIN ul.usuario u
JOIN l.colecciones c
WHERE c.id = :idColeccion AND (u.id = :idUsuario OR u.id IS NULL)")
->setParameters(array('idColeccion'=>$idColeccion, 'idUsuario'=>$idUsuario));
When I try to debug the variable, then the program gets blocked.
Anyone can help me???
Cheers
Im tying to add communication parts to a rootCommunication in my data-fixture, there is no error, but only just NULL in the database field 'root_communication_id'. Why?
Parts of my Model 'Communication'
/**
* Communication
*
* #ORM\Table(name="communication")
* #ORM\Entity(repositoryClass="Mother\BaseBundle\Entity\Repository\CommunicationRepository")
*/
class Communication
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="message", type="text", nullable=true)
*/
private $message;
/**
* #ORM\ManyToOne(targetEntity="Communication", inversedBy="childrenCommunication", cascade={"persist"})
* #ORM\JoinColumn(name="root_communication_id", referencedColumnName="id", nullable=true)
*
*/
private $rootCommunication;
/**
* #ORM\OneToMany(targetEntity="Communication", mappedBy="rootCommunication")
*
*/
private $childrenCommunication;
}
In a first data-fixture i added three communications to the database, in this secound fixture i add the childrenCommunication to the rootCommunication.
/**
* {#inheritDoc}
*/
public function load( ObjectManager $manager ){
$contentRepo = $this->container->get('doctrine')->getManager()->getRepository('MotherBaseBundle:Communication');
$communication1 = $contentRepo->find( $this->getReference('communication1')->getId() );
$communication1->addChildrenCommunication( $this->getReference('communication2') );
$communication1->addChildrenCommunication( $this->getReference('communication3') );
$manager->persist( $communication1 );
$manager->flush();
}
I assume you are not setting the rootCommunication when you are adding the child.
You should add an auto setter to the add method, like..
public function addChildrenCommunication(CommunicationInterface $communication)
{
if (!$this->childrenCommunication->contains($communication)) {
$this->childrenCommunication->add($communication);
$communication->setRootCommunication($this);
}
return $this;
}
.. and the same for the remove..
I need a hand with the following code.
I have this two clases:
Class Expert{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="username", type="string", length=255)
* #Assert\NotBlank()
*/
protected $username;
/**
* #ORM\Column(name="email", type="string", length=255, unique=true)
* #Assert\NotBlank()
*/
protected $email;
/**
* #ORM\Column(name="password", type="string", length=40)
* #Assert\NotBlank()
*/
protected $password;
}
Class Job{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(name="titulo", type="string", length=255)
* #Assert\NotBlank()
*/
protected $title;
/**
* #ORM\Column(name="description", type="text")
* #Assert\NotBlank()
*/
protected $description;
/**
* #ORM\ManyToOne(targetEntity="Expert")
* #ORM\JoinColumn(name="expert_id", referencedColumnName="id")
*/
protected $assigned_expert;
}
And this custom Repository:
class JobRepository extends EntityRepository
{
public function getTechnicianFinishedJobs($id)
{
$Q = $this->getQueryBuilder('j')
->where('j.expert = :expert_id')
->setParameter('expert_id', $id)
->getQuery()
try{
return $q->getResult();
}catch(NoResultException $e){
return false;
}
}
}
When I run this I get the following error:
[Semantical Error] line 0, col 68 near 'expert = :e': Error: Class Job has no field or association named expert
The idea is that one expert can be assigned to many jobs and one job can be assigned to one expert . The job needs to know who's the designated expert but not the other way around, so that's why I use a ManyToOne unidirectional association.
I tried changing the repository to ->where('j.expert_id = :expert_id') and other combinations with no avail.
Can somebody tell me what I'm doing wrong?
Thanks in advance.
If 'j' is your job table, you can't use j.expert, because this is (as far as I can tell) no attribute of your table/entity. You named the field 'expert_id'.
I guess it should be:
$Q = $this->getQueryBuilder('j')
->where('j.assigned_expert = :expert_id')
->setParameter('expert_id', $id)
->getQuery()
#alvk4: He explained why he didn't use bidirectional association. What you suggested, forgive me if I'm wrong, is bidirectional association.
You miss something on your annotation see an working example:
/**
* Fluency\Bundle\DesktopBundle\Entity\Application
*
* #ORM\Table(
* name="desktop.applications",
* uniqueConstraints={
* #ORM\UniqueConstraint(name="applications_jsid_key", columns={"jsid"}),
* #ORM\UniqueConstraint(name="applications_type_key", columns={"type"}),
* #ORM\UniqueConstraint(name="applications_classname_key", columns={"classname"})
* }
* )
* #ORM\Entity(repositoryClass="Fluency\Bundle\DesktopBundle\Entity\Repository\ApplicationRepository")
*/
class Application
{
...
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Fluency\Bundle\DesktopBundle\Entity\ApplicationFile", mappedBy="application", cascade={"persist"})
* #ORM\JoinTable(name="desktop.application_files",
* joinColumns={
* #ORM\JoinColumn(name="idapplication", referencedColumnName="idapplication")
* }
* )
*/
private $files;
...
}
/**
* Fluency\Bundle\DesktopBundle\Entity\ApplicationFile
*
* #ORM\Table(name="desktop.application_files")
* #ORM\Entity
*/
class ApplicationFile
{
...
/**
* #var \Fluency\Bundle\DesktopBundle\Entity\Application
*
* #ORM\ManyToOne(targetEntity="Application", inversedBy="files")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="idapplication", referencedColumnName="idapplication", onDelete="CASCADE")
* })
*/
private $application;
...
}
See a working example of DQL on my repository class:
...
public function getApplicationFilesByJsid($jsid)
{
if(empty($jsid) OR !$jsid OR !is_string($jsid))
{
throw new \Psr\Log\InvalidArgumentException();
}
$query = $this->getEntityManager()->createQueryBuilder()
->select('a, af, m, ft')
->from($this->getEntityName(), 'a')
->innerJoin('a.files', 'af')
->innerJoin('a.module', 'm')
->innerJoin('af.filetype', 'ft')
->where('a.active = 1 AND a.jsid = :jsid')
->setParameter('jsid', $jsid)
->orderBy('af.id', 'ASC')
->getQuery();
$applicationFiles = $query->getSingleResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
return $applicationFiles;
}
...
#enigma: Yes is bidirectional, but your DQL its'n right, would be j.assigned_expert, but anyway the Expert is owning side of relationship, also he needs set mappedBy=assigned_expert on annotation.