Doctrine2 join error - doctrine-orm

Classes Entity
**
* classes
*
* #ORM\Table(name="classes")
* #ORM\Entity
* #Annotation\Name("classes")
* #Annotation\Hydrator("Zend\Stdlib\Hydrator\ClassMethods")
*/
class Classes {
/**
* #var integer
*
* #ORM\Column(name="class_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #Annotation\Exclude()
*/
protected $classId;
/**
* #var string
*
* #ORM\Column(name="class_name", type="string", length=100, nullable=false)
* #Annotation\Filter({"name":"StringTrim"})
* #Annotation\Validator({"name":"StringLength", "options":{"min":1, "max":30}})
* #Annotation\Validator({"name":"Regex", "options":{"pattern":"/^[a-zA-Z][a-zA-Z0-9_-]{0,24}$/"}})
* #Annotation\Attributes({"type":"text"})
* #Annotation\Options({"label":"class name:"})
*/
private $className;
}
Entity Maptechclass
/** #ORM\Entity */
class Maptechclass {
/**
* #var integer
*
* #ORM\Column(name="map_tech_class_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #Annotation\Exclude()
*/
protected $mapTechClassID;
/**
* #var integer
*
* #ORM\Column(name="map_sch_id", type="integer", nullable=true)
*/
protected $mapSchID;
/**
* #var integer
*
* #ORM\Column(name="map_tech_id", type="integer", nullable=true)
*/
protected $mapTechID;
/**
* #ORM\OneToMany(targetEntity="SchoolAdmin\Entity\Classes")
* #ORM\JoinColumn(name="map_class_id", referencedColumnName="classId")
* */
protected $mapClassID;
}
Following Error will show , how to fix it.
OneToMany mapping on field 'mapClassID' requires the 'mappedBy' attribute.

Find:
#ORM\OneToMany(targetEntity="SchoolAdmin\Entity\Classes")
Replace it by:
#ORM\OneToMany(targetEntity="SchoolAdmin\Entity\Classes", mappedBy="classId")

Related

Symfony & Doctrine 2 / Speed up query

I have a problem with query speed after I joined 3 tables. Before speed was 120-500ms. Now it's 1500-5000ms. It's possible to speed up my query?
Here is my query builder:
public function findByCategory($category)
{
$qb = $this->createQueryBuilder('p');
$qb->select('p');
$qb->leftJoin('p.details', 'd');
$qb->leftJoin('p.model', 'm');
$qb->leftJoin('m.category', 'c');
$qb->where('c.id = :category');
$qb->andWhere('d.quantity > 0');
$qb->setParameter('category', $category);
$qb->addOrderBy('p.id', 'DESC');
$qb->setMaxResults(10);
return $qb->getQuery()->useQueryCache(true)->useResultCache(true, 31536000, uniqid())->getResult();
}
and here is formatted query:
SELECT
p0_.id AS id_0,
p0_.title AS title_1,
p0_.url AS url_2,
p0_.description AS description_3,
p0_.views AS views_4,
p0_.price AS price_5,
p0_.is_active AS is_active_6,
p0_.created_at AS created_at_7,
p0_.updated_at AS updated_at_8,
p0_.model_id AS model_id_9,
p0_.details_id AS details_id_10
FROM
products p0_
LEFT JOIN product_details p1_ ON p0_.details_id = p1_.id
LEFT JOIN models m2_ ON p0_.model_id = m2_.id
LEFT JOIN categories c3_ ON m2_.category_id = c3_.id
WHERE
c3_.id = ?
AND p1_.`quantity` > 0
ORDER BY
p0_.id DESC
LIMIT
10
Thanks
EDIT:
Products model:
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255)
*/
private $url;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #var int
*
* #ORM\Column(name="views", type="bigint", nullable=true)
*/
private $views;
/**
* #ORM\ManyToOne(targetEntity="Models")
* #ORM\JoinColumn(name="model_id", referencedColumnName="id")
*/
private $model;
/**
* #ORM\OneToOne(targetEntity="ProductDetails", cascade={"persist"})
* #ORM\JoinColumn(name="details_id", referencedColumnName="id")
*/
private $details;
/**
* #var File
*
* #ORM\OneToMany(targetEntity="ProductImages", mappedBy="product", cascade={"persist"})
*
*/
private $images;
/**
* #var File
*
* #ORM\OneToMany(targetEntity="Cart", mappedBy="productId", cascade={"persist"})
*
*/
private $cart;
/**
* #var string
*
* #ORM\Column(name="price", type="integer", length=255)
*/
private $price;
/**
* #var bool
*
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* created Time/Date
*
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=false)
*/
protected $createdAt;
/**
* updated Time/Date
*
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=false)
*/
protected $updatedAt;
ProductDetail model:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="`processor`", type="string", length=255, nullable=true)
*/
private $processor;
/**
* #var string
*
* #ORM\Column(name="`graphic_card`", type="string", length=255, nullable=true)
*/
private $graphicCard;
/**
* #var string
*
* #ORM\Column(name="`release_year`", type="string", length=4, nullable=true)
*/
private $releaseYear;
/**
* #var string
*
* #ORM\Column(name="`ram`", type="string", length=255, nullable=true)
*/
private $ram;
/**
* #var string
*
* #ORM\Column(name="`ssd`", type="string", length=255, nullable=true)
*/
private $ssd;
/**
* #var string
*
* #ORM\Column(name="`hdd`", type="string", length=255, nullable=true)
*/
private $hdd;
/**
* #var string
*
* #ORM\Column(name="`battery`", type="string", length=255, nullable=true)
*/
private $battery;
/**
* #var string
*
* #ORM\Column(name="`color`", type="string", length=255, nullable=true)
*/
private $color;
/**
* #var string
*
* #ORM\Column(name="`accessories`", type="string", length=255, nullable=true)
*/
private $accessories;
/**
* #var string
*
* #ORM\Column(name="`guarantee`", type="string", length=255, nullable=true)
*/
private $guarantee;
/**
* #var string
*
* #ORM\Column(name="`condition`", type="string", length=255)
*/
private $condition;
/**
* #var string
*
* #ORM\Column(name="`quantity`", type="string", length=255)
*/
private $quantity;
Models model:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Categories")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255)
*/
private $url;
/**
* #var string
*
* #ORM\Column(name="image", type="string", length=255)
*/
private $image;
Categories Model:
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=50)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255)
*/
private $url;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=140)
*/
private $description;
/**
* #var string
*
* #ORM\Column(name="image", type="string", length=100)
*/
private $image;
/**
* #var bool
*
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* created Time/Date
*
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=false)
*/
protected $createdAt;
/**
* updated Time/Date
*
* #var \DateTime
*
* #ORM\Column(name="updated_at", type="datetime", nullable=false)
*/
protected $updatedAt;
One Join is not necessary. You are joining the category table just for filter the id, but you can do that with IDENTITY, which is really helpful to reference the FK column. Your query should be faster like this:
public function findByCategory($category)
{
$qb = $this->createQueryBuilder('p');
$qb->select('p');
$qb->leftJoin('p.details', 'd');
$qb->leftJoin('p.model', 'm');
// $qb->leftJoin('m.category', 'c'); // this don't go anymore
$qb->where('IDENTITY(m.category) = :category');
$qb->andWhere('d.quantity > 0');
$qb->setParameter('category', $category);
$qb->addOrderBy('p.id', 'DESC');
$qb->setMaxResults(10);
return $qb->getQuery()->useQueryCache(true)->useResultCache(true, 31536000, uniqid())->getResult();
}

Invalid mapping for a one-to-one relation

I'm trying to create a One-to-one bidirectional mapping between two Entitiesbut what I get is this error:
# app/console doctrine:schema:validate --env=dev_local
[Mapping] FAIL - The entity-class 'Belka\AuthBundle\Entity\Globaltoken' mapping is invalid:
* The association Belka\AuthBundle\Entity\Globaltoken#user refers to the inverse side field Belka\AuthBundle\Entity\User#globaltoken which does not exist.
[Mapping] FAIL - The entity-class 'Belka\AuthBundle\Entity\User' mapping is invalid:
* The mappings Belka\AuthBundle\Entity\User#globalToken and Belka\AuthBundle\Entity\Globaltoken#user are inconsistent with each other.
These are my entities:
User entity
/**
* #ORM\Entity
* #ORM\Table(name="app_auth.""User""", schema="app_auth")
* #ORM\Entity(repositoryClass="UserRepository")
* #UniqueEntity("username", groups={"strict"})
* #UniqueEntity("email", groups={"strict"})
* #Assert\GroupSequence({"User", "strict"})
*/
class User implements EncoderAwareInterface
{
/**
* #ORM\Id
* #ORM\Column(type="string")
* #Assert\NotBlank(message = "user.username.not_blank")
* #ORM\GeneratedValue(strategy="NONE")
* #Serializer\Groups({"default"})
*/
private $username;
/**
* #ORM\Id
* #ORM\Column(type="string")
* #Assert\NotBlank(message = "user.email.not_blank")
* #Assert\Email(message = "user.email.not_valid")
* #Serializer\Groups({"default"})
*/
private $email;
/**
* #ORM\Column(type="string", nullable=true)
* #Serializer\Groups("personal")
*/
private $password;
/**
* #ORM\Column(type="string")
* #Serializer\Groups({"default"})
*/
private $name;
/**
* #ORM\Column(type="string")
* #Serializer\Groups({"default"})
*/
private $surname;
/**
* #ORM\Column(type="string", length=5)
* #Serializer\Groups({"default"})
*/
private $lang;
/**
* #ORM\Column(type="boolean")
* #Serializer\Groups({"strict_adm"})
*/
private $deleted = false;
/**
* #ORM\OneToOne(targetEntity="Globaltoken", mappedBy="user", cascade={"persist"})
* #Serializer\Groups({"strict"})
*/
private $globalToken;
<removed methods>
}
Globaltoken entity
/**
* #ORM\Entity
* #ORM\Table(name="app_auth.""Globaltoken""", schema="app_auth")
* #ORM\Entity(repositoryClass="GlobaltokenRepository")
* #UniqueEntity("token", groups={"strict"})
* #UniqueEntity("last_use", groups={"strict"})
* #Assert\GroupSequence({"Globaltoken", "default", "strict"})
* #ORM\HasLifecycleCallbacks()
*/
class Globaltoken
{
//10 minutes, expressed in seconds
const VALIDITYINTERVAL = 600;
/**
* #ORM\Id
* #ORM\Column(type="string")
* #ORM\GeneratedValue(strategy="NONE")
* #Serializer\Groups({"strict"})
*/
private $token;
/**
* #ORM\OneToOne(targetEntity="User", inversedBy="globaltoken")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="owned_by_username", referencedColumnName="username"),
* #ORM\JoinColumn(name="owned_by_email", referencedColumnName="email")
* })
* #Serializer\Groups({"strict"})
*/
private $user;
/**
* #ORM\Column(type="datetime")
* #Assert\NotBlank()
* #Serializer\Groups({"strict"})
*/
private $last_use;
/**
* #Serializer\Groups({"default"})
*/
private $expiring;
<removed methods>
}
what do you think it could be?
Got it. The uppercase-typo is the responsible of everything:
User::globalToken is NOT what inversedBy="globaltoken" expects. User::globaltoken is.
I fell into one of the most classic pitfalls in IT development I'd say that could drive yourself into distraction. I'm quite disappointed by the PHPStorm's support about Symfony annotations though.

Doctrine 2 ManyToOne multipy JoinColumns

I have next entities:
/**
* Customer
*
* #ORM\Table(name="customer")
* #ORM\Entity()
*/
class Customer
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Account[]|ArrayCollection
*
* #ORM\OneToMany(targetEntity="Account", mappedBy="customer")
*/
private $accounts;
/**
* #var Account
*
* #ORM\OneToOne(targetEntity="Account")
*
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id",referencedColumnName="customer_id"),
* #ORM\JoinColumn(name="default_account_id", referencedColumnName="id")
* })
*/
private $defaultAccount;
}
/**
* Account
*
* #ORM\Table(name="account")
*/
class Account
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Customer
*
* #ORM\ManyToOne(targetEntity="Customer", inversedBy="accounts")
* #ORM\JoinColumn(nullable=false)
*/
private $customer;
}
Idea that customer has multiply accounts, onr of the account should be default for customer. I would like to use foreign key with multiply fields to ensure that default customer account belongs to this customer, but I'm getting next error:
Column name `customer_id` referenced for relation from MyBundle\Entity\Customer towards MyBundle\Entity\Account does not exist.
Actually there is no "customer_id" field on ORM level, because it is "customer.id" but I dont know how to reference it.
It seems that line #ORM\JoinColumn(name="id",referencedColumnName="customer_id"), is redundant. Try to configure this field as following:
/**
* #var Account
*
* #ORM\OneToOne(targetEntity="Account")
*
* #ORM\JoinColumn(name="default_account_id", referencedColumnName="id")
*/
private $defaultAccount;
By the way, I think it would be better if you just added a boolean column is_default into your Account entity.

zf2 + Doctrine2 Integrity constraint violation: 1048 Column '' cannot be null

I have a problem with Doctrine2 it throws me this exception:
An exception occurred while executing 'INSERT INTO sesion (Contrasena, Estado, UsuarioIdentificacion) VALUES (?, ?, ?)' with params ["j15474874654j", "1", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'UsuarioIdentificacion' cannot be null
I am a beginner with doctrine 2 and I could not resolve this error, I think the error is in relationships. I've read other similar problems, but I have not succeeded.
I would greatly appreciate the help. this is my code:
In my controller:
$usuario = new Usuario();
$data = $request->getPost();
$usuario->setNombre($data['nombre']);
$usuario->setApellidos($data['apellidos']);
$usuario->setIdentificacion($data['identificacion']);
$usuario->setTitulo($data['titulo']);
$usuario->setContacto($data['contacto']);
$usuario->setCorreo($data['correo'] . "#correounivalle.edu.co");
$sesion = new Sesion();
$sesion->setUsuarioidentificacion($usuario);
$sesion->setEstado("1");
$sesion->setContrasena($data['nombre'][0].$data['identificacion'].$data['apellidos'][0]);
$em->persist($usuario);
$em->persist($sesion);
$em->flush();
class usuario:
<?php
namespace DBAL\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Usuario
*
* #ORM\Table(name="usuario", uniqueConstraints={#ORM\UniqueConstraint(name="Identificacion", columns={"Identificacion"}), #ORM\UniqueConstraint(name="Correo", columns={"Correo"})})
* #ORM\Entity
* #ORM\Entity(repositoryClass="DBAL\Repository\UsuarioRepository")
*/
class Usuario
{
/**
* #var integer
*
* #ORM\Column(name="Id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="Identificacion", type="integer", nullable=false)
*/
private $identificacion;
/**
* #var string
*
* #ORM\Column(name="Nombre", type="string", length=50, nullable=false)
*/
private $nombre;
/**
* #var string
*
* #ORM\Column(name="Apellidos", type="string", length=50, nullable=false)
*/
private $apellidos;
/**
* #var string
*
* #ORM\Column(name="Correo", type="string", length=100, nullable=false)
*/
private $correo;
/**
* #var integer
*
* #ORM\Column(name="Contacto", type="integer", nullable=true)
*/
private $contacto;
/**
* #var string
*
* #ORM\Column(name="Titulo", type="string", length=20, nullable=true)
*/
private $titulo;
/*with their respective setter and getter*/
class sesion:
<?php
namespace DBAL\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Sesion
*
* #ORM\Table(name="sesion", indexes={#ORM\Index(name="UsuarioIdentificacion", columns={"UsuarioIdentificacion"}), #ORM\Index(name="sesion", columns={"UsuarioIdentificacion"})})
* #ORM\Entity
*/
class Sesion
{
/**
* #var integer
*
* #ORM\Column(name="Id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="Contrasena", type="string", length=50, nullable=false)
*/
private $contrasena;
/**
* #var boolean
*
* #ORM\Column(name="Estado", type="boolean", nullable=false)
*/
private $estado;
/**
* #var \Usuario
*
*
* #ORM\OneToOne(targetEntity="Usuario")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="UsuarioIdentificacion", referencedColumnName="Correo")
* })
*/
private $usuarioidentificacion;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Roles", mappedBy="sesionusuarioidentificacion")
*/
private $rolesid;
/**
* Constructor
*/
public function __construct()
{
$this->rolesid = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set contrasena
*
* #param string $contrasena
*
* #return Sesion
*/
public function setContrasena($contrasena)
{
$this->contrasena = $contrasena;
return $this;
}
/**
* Get contrasena
*
* #return string
*/
public function getContrasena()
{
return $this->contrasena;
}
/**
* Set estado
*
* #param boolean $estado
*
* #return Sesion
*/
public function setEstado($estado)
{
$this->estado = $estado;
return $this;
}
/**
* Get estado
*
* #return boolean
*/
public function getEstado()
{
return $this->estado;
}
/**
* Set usuarioidentificacion
*
* #param \DBAL\Entity\Usuario $usuarioidentificacion
*
* #return Sesion
*/
public function setUsuarioidentificacion(\DBAL\Entity\Usuario $usuarioidentificacion)
{
$this->usuarioidentificacion = $usuarioidentificacion;
return $this;
}
/**
* Get usuarioidentificacion
*
* #return \Usuario
*/
public function getUsuarioidentificacion()
{
return $this->usuarioidentificacion;
}
/**
* Add rolesid
*
* #param \Roles $rolesid
*
* #return Sesion
*/
public function addRolesid(\Roles $rolesid)
{
$this->rolesid[] = $rolesid;
return $this;
}
/**
* Remove rolesid
*
* #param \Roles $rolesid
*/
public function removeRolesid(\Roles $rolesid)
{
$this->rolesid->removeElement($rolesid);
}
/**
* Get rolesid
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRolesid()
{
return $this->rolesid;
}
If someone could help me, I really need it and I have already searched a lot and attempted in many ways, but really not fix it.

Unwanted cascade delete by Doctrine2

I am working on a product catalog, and have two entities, PcatSalesItem and PcatCategory with a many-to-many relationship between them. If I delete a category, and there are still sales items associated with it, I want an exception to be thrown, I do NOT want cascading delete. On the RDBMS level (PostgreSQL), in the join table, I have set the foreign keys to "ON DELETE RESTRICT". However, when I delete a category that has sales items, Doctrine does a cascading delete. Nowhere have I specified cascade=remove to Doctrine!
Here are the entities:
/**
* PcatSalesItem
*
* #ORM\Table(name="pcat_sales_item")
* #ORM\Entity
* #Gedmo\Loggable(logEntryClass="Qi\Bss\BaseBundle\Entity\Business\LogEntryBusiness")
*/
class PcatSalesItem
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="pcat_sales_item_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=64, nullable=false)
* #Gedmo\Versioned
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=true)
* #Gedmo\Versioned
*/
private $description;
/**
* #var array $categories
*
* #ORM\ManyToMany(targetEntity="PcatCategory")
* #ORM\JoinTable(name="pcat_category_x_sales_item",
* joinColumns={#ORM\JoinColumn(name="sales_item_id", referencedColumnName="id", onDelete="RESTRICT")},
* inverseJoinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="RESTRICT")}
* )
*/
private $categories;
...
}
/**
* PcatCategory
*
* #ORM\Table(name="pcat_category")
* #ORM\Entity
* #Gedmo\Loggable(logEntryClass="Qi\Bss\BaseBundle\Entity\Business\LogEntryBusiness")
*/
class PcatCategory
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
* #ORM\SequenceGenerator(sequenceName="pcat_category_id_seq", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=64, nullable=false)
* #Gedmo\Versioned
*/
private $name;
/**
* #var array $salesItems
*
* #ORM\ManyToMany(targetEntity="PcatSalesItem")
* #ORM\JoinTable(name="pcat_category_x_sales_item",
* joinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="RESTRICT")},
* inverseJoinColumns={#ORM\JoinColumn(name="sales_item_id", referencedColumnName="id", onDelete="RESTRICT")}
* )
*/
private $salesItems;
....
}
Here is the code I use to delete a category:
$em = $this->getDoctrine()->getManager();
$cat = $em->getRepository('QiBssBaseBundle:PcatCategory')->find(15);
$em->remove($cat);
$em->flush();
Any help will be greatly appreciated!