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
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 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.
Here's my table :
My Category entity (without getter/setter):
/**
* #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=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="slug", type="string", length=255, nullable=true)
*/
private $slug;
/**
* #var int
* #Gedmo\TreeLeft
* #ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* #var int
* #Gedmo\TreeLevel
* #ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* #var int
* #Gedmo\TreeRight
* #ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\ManyToOne(targetEntity="Category")
* #ORM\JoinColumn(name="root", referencedColumnName="id", onDelete="CASCADE")
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
In my controller, if I do this :
$category= $this->container->get('app.category.manager')->getCategoryBySlug($category_slug);
$root = $term->getRoot();
Doctrine execute 2 queries, one for the category itself, and one for the root of the category. I would like to create my own repository function to join the 2 entities in one query. I've tried so many things with the query builder, now I'm completly lost.
First, create a custom Repository class for your entity.
Then, paste the a method like the following into:
class CategoryRepository extends EntityRepository
{
public function getRootByCategorySlug($slug)
{
return $this->getEntityManager()
->createQueryBuilder()
->from('YourBundle:Category', 'c')
->where('c.slug = :slug')
->setParameter('slug', $slug)
->leftJoin('c.root', 'r') // Join the association
->select('r') // Fetch the association only
->getQuery()
->getResult()
;
}
}
And use it like follows:
$repo = $this->getDoctrine()->getManager()->getRepository('YourBundle:Category');
$rootCategory = $repo->getRootByCategorySlug('your_slug');
I've used Translatable with a personal translation; I've implemented PysTranslationand I've used ORM query hint in PysRepository. All of this works fine, the problem has been when I've translated the entity Genero. This entity has a many-to-many relationship with Pys entity and the above method doesn't work. How I can translate the $genNombre attribute of Generoentity?
/**
* Pys
*
* #ORM\Table(name="pys")
* #ORM\Entity(repositoryClass="Filmboot\PYSBundle\Entity\PysRepository")
* #Gedmo\TranslationEntity(class="Filmboot\PYSBundle\Entity\PysTranslation")
*/
class Pys
{
/**
* #var integer
*
* #ORM\Column(name="PYS_ID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $pysId;
/**
* #var string
*
* #ORM\Column(name="PYS_STR", type="string", length=255, nullable=false)
* #Gedmo\Translatable
*/
private $pysStr;
/**
* #var string
*
* #ORM\Column(name="PYS_TITULO", type="string", length=255, nullable=true)
* #Gedmo\Translatable
*/
private $pysTitulo;
/**
* #var integer
*
* #ORM\Column(name="PYS_DURACION", type="integer", nullable=true)
*/
private $pysDuracion;
/**
* #var integer
*
* #ORM\Column(name="PYS_ANYO", type="integer", nullable=true)
*/
private $pysAnyo;
/**
* #var string
*
* #ORM\Column(name="PYS_PAIS", type="string", length=255, nullable=true)
* #Gedmo\Translatable
*/
private $pysPais;
/**
* #var string
*
* #ORM\Column(name="PYS_SINOPSIS", type="string", length=3000, nullable=true)
* #Gedmo\Translatable
*/
private $pysSinopsis;
/**
* #var string
*
* #ORM\Column(name="PYS_GUIONISTA", type="string", length=255, nullable=true)
*/
private $pysGuionista;
/**
* #ORM\ManyToOne(targetEntity="Filmboot\DirectorBundle\Entity\Director", cascade={"remove"})
* #ORM\JoinColumn(name="DIR_ID", referencedColumnName="DIR_ID", onDelete="CASCADE")
*/
private $director;
/**
* #var string
*
* #ORM\Column(name="PYS_IMAGEN", type="string", length=255, nullable=true)
*/
private $pysImagen;
/**
* #var string
*
* #ORM\Column(name="PYS_IMAGEN_GRANDE", type="string", length=255, nullable=true)
*/
private $pysImagenGrande;
/**
* #ORM\ManyToMany(targetEntity="\Filmboot\ActorBundle\Entity\Actor", mappedBy="peliculas", cascade={"remove"})
*/
private $actores;
/**
* #ORM\ManyToMany(targetEntity="\Filmboot\PYSBundle\Entity\Genero", mappedBy="peliculas", cascade={"remove"})
*/
private $generos;
/**
* #ORM\OneToMany(targetEntity="\Filmboot\PYSBundle\Entity\Premio", mappedBy="pys", cascade={"remove"})
* #ORM\JoinColumn(name="PRE_ID", referencedColumnName="PRE_ID", onDelete="CASCADE")
*/
private $premios;
/**
* #ORM\OneToMany(targetEntity="\Filmboot\UsuarioBundle\Entity\Voto", mappedBy="pys", cascade={"remove"})
* #ORM\JoinColumn(name="PYS_ID", referencedColumnName="PYS_ID", onDelete="CASCADE")
*/
private $votaciones;
/**
* #ORM\OneToMany(targetEntity="PysTranslation", mappedBy="object", cascade={"persist", "remove"})
*/
private $translations;
public function __construct()
{
$this->actores = new ArrayCollection();
$this->generos = new ArrayCollection();
$this->votaciones = new ArrayCollection();
$this->translations = new ArrayCollection();
}
public function getTranslations()
{
return $this->translations;
}
public function addTranslation(PysTranslation $t)
{
if (!$this->translations->contains($t)) {
$this->translations[] = $t;
$t->setObject($this);
}
}
This is Genero
<?php
namespace Filmboot\PYSBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Genero
*
* #ORM\Table(name="genero")
* #ORM\Entity
*/
class Genero
{
/**
* #var integer
*
* #ORM\Column(name="GEN_ID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $genId;
/**
* #var string
*
* #ORM\Column(name="GEN_NOMBRE", type="string", length=255, nullable=true)
* #Gedmo\Translatable
*/
private $genNombre;
/**
* #ORM\ManyToMany(targetEntity="\Filmboot\PYSBundle\Entity\Pys", inversedBy="generos")
* #ORM\JoinTable(name="P_GENERO",
* joinColumns={#ORM\JoinColumn(name="GEN_ID", referencedColumnName="GEN_ID")},
* inverseJoinColumns={#ORM\JoinColumn(name="PYS_ID", referencedColumnName="PYS_ID")}
* )
*/
private $peliculas;
This is PysTranslation
/**
* #ORM\Entity
* #ORM\Table(name="pys_translation", uniqueConstraints={#ORM\UniqueConstraint(name="lookup_unique_idx", columns={"locale", "object_id", "field"})})
*/
class PysTranslation extends AbstractPersonalTranslation
{
/**
* Convinient constructor
*
* #param string $locale
* #param string $field
* #param string $value
*/
public function __construct($locale, $field, $value)
{
$this->setLocale($locale);
$this->setField($field);
$this->setContent($value);
}
/**
* #ORM\ManyToOne(targetEntity="Pys", inversedBy="translations")
* #ORM\JoinColumn(name="object_id", referencedColumnName="PYS_ID", onDelete="CASCADE")
*/
protected $object;
}
This is PysRepository
class PysRepository extends EntityRepository
{
public function findPeliculas()
{
$em = $this->getEntityManager();
$consulta = $em->createQuery('
SELECT p, a, d, g, pr, v
FROM PYSBundle:Pys p
JOIN p.actores a JOIN p.director d JOIN p.generos g JOIN p.premios pr JOIN p.votaciones v
ORDER BY p.pysTitulo ASC
');
return $consulta->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker')->getResult();
}
/**
*
* #param string $pysStr El slug de la pelĂcula
*/
public function findPys($pysStr)
{
$em = $this->getEntityManager();
$consulta = $em->createQuery('
SELECT p, a, d, g, pr, v
FROM PYSBundle:Pys p
JOIN p.actores a JOIN p.director d JOIN p.generos g JOIN p.premios pr JOIN p.votaciones v
WHERE p.pysStr = :pysStr
');
$consulta->setParameter('pysStr', $pysStr);
return $consulta->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker')->getSingleResult();
}
}
I've solved the problem by adding this line in Genero entity annotations:
/**
* Genero
*
* #ORM\Table(name="genero")
* #ORM\Entity
* #Gedmo\TranslationEntity(class="Filmboot\PYSBundle\Entity\GeneroTranslation")
*/
class Genero
I am trying to build a log of some action performed on some site using Symfony2 and Doctrine. I have 2 tables Sites and Logs. The Logs table will contain a siteid which is a foreign key to the id column of sites table. The Logs table can have multiple logs for same site.
When I try to insert an entry in the log table I get siteid is null error.
Here is my code:
Sites Entity:
<?php
namespace A\SHB\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Sites
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="A\SHB\Entity\SitesRepository")
*/
class Sites
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var ArrayCollection $siteLog
*
* #ORM\OneToMany(targetEntity="Logs", mappedBy="log", cascade={"persist"})
* #ORM\OrderBy({"siteid" = "ASC"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="log_id", referencedColumnName="siteid")
* })
*/
private $siteLog;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Constructor
*/
public function __construct()
{
$this->siteLog = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add siteLog
*
* #param \A\SHB\Entity\SiteLog $siteLog
* #return Sites
*/
public function addSiteLog(\A\SHB\Entity\SiteLog $siteLog)
{
$this->siteLog[] = $siteLog;
return $this;
}
/**
* Remove siteLog
*
* #param \A\SHB\Entity\SiteLog $siteLog
*/
public function removeSiteLog(\A\SHB\Entity\SiteLog $siteLog)
{
$this->siteLog->removeElement($siteLog);
}
/**
* Get siteLog
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getSiteLog()
{
return $this->siteLog;
}
}
Logs Entity:
<?php
namespace A\SHB\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Logs
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="A\SHB\Entity\LogsRepository")
*/
class Logs
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="siteid", type="integer")
*/
private $siteid;
/**
* #var integer
*
* #ORM\Column(name="dateline", type="integer")
*/
private $dateline;
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
* })
*/
private $log;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set siteid
*
* #param integer $siteid
* #return Logs
*/
public function setSiteid($siteid)
{
$this->siteid = $siteid;
return $this;
}
/**
* Get siteid
*
* #return integer
*/
public function getSiteid()
{
return $this->siteid;
}
/**
* Set dateline
*
* #param integer $dateline
* #return Logs
*/
public function setDateline($dateline)
{
$this->dateline = $dateline;
return $this;
}
/**
* Get dateline
*
* #return integer
*/
public function getDateline()
{
return $this->dateline;
}
/**
* Set log
*
* #param \A\SHB\Entity\Log $log
* #return Logs
*/
public function setLog(\A\SHB\Entity\Log $log = null)
{
$this->log = $log;
return $this;
}
/**
* Get log
*
* #return \A\SHB\Entity\Log
*/
public function getLog()
{
return $this->log;
}
}
Controller :
public function indexAction()
{
$sites = $this->getDoctrine()->getRepository('ASHB:Sites')->findAll();
foreach ($sites as $site)
{
$host = $site->getForum();
// Do something ....
$log = new Logs();
$log->setSiteid($site->getId());
$log->setDateline($temp['dateline']);
$em = $this->getDoctrine()->getManager();
$em->persist($log);
$em->flush();
}
return $this->render('ASHB:Default:index.html.twig', array('sites' => $output, 'counters' => $counters));
}
Now when I run this code, I get the following error:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'siteid' cannot be null"
If I var_dump $log, before $em->persist($log);, the siteid is there. I am not sure what is wrong and why the siteid is getting set to null.
Update 1:
I tried to make the following changes and still get the same error:
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites", inversedBy="siteLog")
*/
private $log;
OneToMany doesn't need a JoinColumn. So it should look like, according to the documentation.
class Sites
{
/**
* #ORM\OneToMany(targetEntity="Logs", mappedBy="log")
*/
private $site_log;
}
class Logs
{
/**
* #ORM\ManyToOne(targetEntity="Sites", inversedBy="site_log")
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
*/
private $log;
}
orderBy and cascade were ignored for simplicity.
you have problem in your sturcture,
Remove this from Logs Entity
/**
* #var integer
*
* #ORM\Column(name="siteid", type="integer")
*/
private $siteid;
And then replace this part
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="site_id", referencedColumnName="id")
* })
*/
private $log;
with
/**
* #var Log
*
* #ORM\ManyToOne(targetEntity="Sites" inversedBy="logs")
*/
private $site;
And in your sites entity replace this with
/**
* #var ArrayCollection $siteLog
*
* #ORM\OneToMany(targetEntity="Logs", mappedBy="logs", cascade={"persist"})
* #ORM\OrderBy({"siteid" = "ASC"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="log_id", referencedColumnName="siteid")
* })
*/
private $logs;
with
/**
* #var ArrayCollection $siteLog
*
* #ORM\OneToMany(targetEntity="Logs", mappedBy="site", cascade={"persist"})
* #ORM\OrderBy({"siteid" = "ASC"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="log_id", referencedColumnName="id")
* })
*/
private $logs;
And then use proper setters and getters for these new feilds mean pass object to setter functions, for the class they are being mapped for(if you dont know this part write in comment i will do it as well)