Invalid mapping for a one-to-one relation - doctrine-orm

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.

Related

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.

Create an entity that will be used by many other entities (Doctrine 2)

How can I do this?
My Entities:
Product entity
/**
* #ORM\Entity
* #ORM\Table(name="products")
*/
class Product
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $name;
/**
* (??)
* #var ArrayCollection
*/
private $images;
}
Article entity
/**
* #ORM\Entity
* #ORM\Table(name="articles")
*/
class Article
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $title;
/**
* (??)
* #var ArrayCollection
*/
private $images;
}
Image entity
/**
* #ORM\Entity
* #ORM\Table(name="images")
*/
class Image
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $name;
/**
* #ORM\Column(type="string", length=1024)
* #var string
*/
private $path;
}
I don't know how to create a link tables with additional fields like the picture. Which association should I use? How to manage these relations in entities?
Usually when you need a many to many approach Doctrine let you define such behaviour with a simple annotation.
#ORM\ManyToMany(targetEntity="full_qualified_namespace")
#ORM\JoinTable(
name="game_schemas_players",
joinColumns={#ORM\JoinColumn(name="this_field_name", referencedColumnName="id")},
inverseJoinColumns={#ORM\JoinColumn(name="that_field_anem", referencedColumnName="id")}
)
This will instruct Doctrine to create a relation the current entity and the target entity.
But that's not your case. For what I can see from your model you need to add some field on the 'middle' entity.
Here what you may want to do:
class Product
{
[...]
/**
* #var ArrayCollection | ProductImage[]
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
private $productImages;
}
class Image
{
[...]
/**
* #var ArrayCollection | ProductImage[]
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="image")
*/
private $productImages;
}
as you can see as defined here either Product and Image have a oneToMany relation with a middle entity which will be named ProductImage**.
The last step will be to implement such entity:
class ProductImage
{
[...]
/**
* #var Image
*
* #ORM\ManyToOne(targetEntity="Image", mappedBy="image")
* #ORM\JoinColumn(name="image_id", referencedColumnName="id")
*/
private $image;
/**
* #var Product
*
* #ORM\ManyToOne(targetEntity="Product", mappedBy="product")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
/**
* #ORM\Column(type="string", length=1024)
* #var string
*/
private $position;
}
The owning side of the relation both for Product and Image is still ProductImage.
As a side note in your entity is common practice to implement an add method in this fashion:
public function __contructor(){
$this->productImages = new ArrayCollection();
}
/**
* Add ProductImage
*
* #param ProductImage $productImage
* #return $this
*/
public function addDocument(ProductImage $productImage)
{
$productImage->addProductImage($productImage);
$this->documents->add($document);
return $this;
}
and then you can use such method with the following approach:
$product = new Product();
$image = new Image();
$productImage = new ProductImage($product,$image);
$product->addProductImage($productImage);
Don't forget to provide the usual setter method as Doctrine need them to initialize the entity.
Hope it helps, Regards.

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.

Doctrine2 join error

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")

OneToMany Relationship Only Returns 1 Row

I am looking for some help as to why my OneToMany relationship in doctrine only returns one value. My data model has three tables. Users, Authorization, and Applications. The Authorization table is the glue that maps users to applications and also contains an accesslevel field to indicate their level of access for that application.
I have a user that has three entries in authorization for three different applications, but for some reason, doctrine is only loading 1 of those authorization records. I've included my full data model below. The attribute in question is "authorization" in the Webusers table.
Anyone know what I am doing wrong?
class Webusers {
/**
* #var integer
*
* #ORM\Column(name="userid", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $userid;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Applications", mappedBy="userid")
*/
private $applications;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\OneToMany(targetEntity="Authorization", mappedBy="user")
*/
private $authorization;
/**
* Constructor
*/
public function __construct() {
$this->applications = new \Doctrine\Common\Collections\ArrayCollection();
$this->authorization = new \Doctrine\Common\Collections\ArrayCollection();
}
class Authorization {
/**
* #var integer
*
* #ORM\Column(name="accesslevel", type="integer", nullable=false)
*/
private $accesslevel;
/**
* #var integer
*
* #ORM\Column(name="applicationid", type="integer", nullable=false)
* $ORM\Id
*/
private $applicationid;
/**
* #var integer
*
* #ORM\Column(name="userid", type="integer", nullable=false)
* #ORM\Id
*/
private $userid;
/**
* #var \Webusers
*
* #ORM\ManyToOne(targetEntity="Webusers")
* #ORM\JoinColumn(name="userid", referencedColumnName="userid")
*/
private $user;
}
class Applications {
/**
* #var integer
*
* #ORM\Column(name="applicationid", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $applicationid;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=50, nullable=false)
*/
private $name;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Webusers", inversedBy="applicationid")
* #ORM\JoinTable(name="authorization",
* joinColumns={
* #ORM\JoinColumn(name="applicationid", referencedColumnName="applicationid")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="userid", referencedColumnName="userid")
* }
* )
*/
private $userid;
/**
* Constructor
*/
public function __construct()
{
$this->userid = new \Doctrine\Common\Collections\ArrayCollection();
}
}
I was able to fix this by making sure I specified both the webusers and application relationship as ManyToOne AND giving them the #ORM\Id property since they make up a composite primary key.
I think the main reason this was failing was because I had not associated authorization to applications.
The key points of my new model are as follows:
class Webusers {
/**
* #var \Doctrine\Common\Collections\Collection
* #ORM\OneToMany(targetEntity="Authorization", mappedBy="user")
*/
private $authorization;
}
class Authorization {
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Applications")
* #ORM\JoinColumn(name="applicationid", referencedColumnName="applicationid")
*/
private $application;
/**
*
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Webusers")
* #ORM\JoinColumn(name="userid", referencedColumnName="userid")
*/
private $user;
}
class Applications {
/**
* #ORM\OneToMany(targetEntity="Authorization", mappedBy="application")
*/
private $authorization;
}