I'm trying to fetch an object from MySQL database using doctrine. It has one-to-one relation with other one. I'm getting this error: Notice: Undefined index: id
What I should correct to make this working?
My fetch code is very simple, I try to fetch all objects:
$emArt = $this->getDoctrine()->getRepository(Article::class);
$articles = $emArt->findAll();
Model is as following:
Article.php
/**
* #ORM\Entity
* #ORM\Table(name="Article")
*/
class Article
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $ID;
/**
* #ORM\OneToOne(targetEntity="ArticleTypes", inversedBy="articleTypeId")
* #ORM\JoinColumn(name="articleTypeId", referencedColumnName="id")
*/
private $articleType;
/**
* #ORM\Column(name="articleName", type="text")
*/
private $articleName;
/**
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #ORM\Column(name="image", type="string")
* #Assert\File(mimeTypes={ "image/png" })
*/
public $image;
public function getArticleImage()
{
return $this->image;
}
public function setArticleImage($newImage)
{
$this->image = $newImage;
}
public function getArticleContent()
{
return $this->content;
}
public function setArticleContent($name)
{
$this->content = $name;
}
public function getArticleName()
{
return $this->articleName;
}
public function setArticleName($name)
{
$this->articleName = $name;
}
public function getArticleType()
{
return $this->articleType;
}
public function setArticleType($type)
{
$this->articleType = $type;
}
}
ArticleTypes.php
/**
* #ORM\Entity
* #ORM\Table(name="ArticleTypes")
*/
class ArticleTypes
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\OneToOne(targetEntity="Article", mappedBy="articleTypeId")
*/
private $ID;
/**
* #ORM\Column(name="articleType", type="text")
*/
private $articleType;
public function getArticleType()
{
return $this->articleType;
}
public function setArticleType($newType)
{
$this->articleType = $newType;
}
}
It's a PHP Notice no ? You should have also the line number in a file with the error ?
But I saw errors in your doctrine mapping too : You can't use doctrine annotation like this with fields, you should link your relationship to objects :
/**
* #ORM\Entity
* #ORM\Table(name="Article")
*/
class Article
{
/**
* #ORM\OneToOne(targetEntity="ArticleTypes", inversedBy="article")
* #ORM\JoinColumn(name="articleTypeId", referencedColumnName="id")
*/
private $articleType;
....
}
And :
/**
* #ORM\Entity
* #ORM\Table(name="ArticleTypes")
*/
class ArticleTypes
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Article $article
* #ORM\OneToOne(targetEntity="Article", mappedBy="articleType")
*/
private $article;
....
}
Even if you have a one to one relationship you can have different ids.
Related
I'm trying to serialize a Entity that has a OneToOne relation to a Image Entity.
When dumping the Entity I can see that the Image Entity is a Doctrine Proxy and not initialized.
It also doesn't show up in the JSON response when trying to access the Endpoint.
I've tried fetch="EAGER" with no success.
How do I go about serializing this to the "Expected Response" ?
Response:
[
{
"id": 7
}
]
Expected Response:
[
{
"id": 7,
"image": {
"webView": "someUrl"
}
}
]
Entity:
/**
* #ORM\Entity(repositoryClass=BatteryTypeRepository::class)
*/
class BatteryType
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*
* #Groups({"type"})
*/
private $id;
/**
* #ORM\OneToOne(targetEntity=Image::class, cascade={"persist", "remove"})
*
* #Groups({"type"})
*/
private $image;
/**
* #return Image|null
*/
public function getImage(): ?Image
{
return $this->image;
}
public function setImage(?Image $image): self
{
$this->image = $image;
return $this;
}
}
Image Entity:
/**
* #ORM\Entity(repositoryClass=ImageRepository::class)
* #ORM\EntityListeners({"App\EventSubscriber\ImageListener"})
*/
class Image
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"type"})
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $filename;
/**
* Auto generated by entity listener
* #var string
*/
private $tempFilename;
/**
* #var File
* #Assert\Image()
* #Assert\NotBlank()
*/
private $file;
/**
* #var string
* #Groups({"type"})
*/
private $webView;
/** Getters & Setters */
}
ImageListener:
class ImageListener
{
/**
* #var S3FileManagerInterface
*/
private S3FileManagerInterface $fileManager;
public function __construct(S3FileManagerInterface $fileManager)
{
$this->fileManager = $fileManager;
}
public function postLoad(Image $image, LifecycleEventArgs $args): void
{
$image->setWebView(
$this->fileManager->getUrl($image->getFilename())
);
if (!$image->getTempFilename()) {
$image->setTempFilename($image->getFilename());
}
}
}
Controller:
public function getBatteryTypes(BatteryTypeRepository $batteryTypeRepository): Response
{
$batteryTypes = $batteryTypeRepository->findAll();
$view = $this->view($batteryTypes, Response::HTTP_OK);
$view->getContext()->setGroups(["type"]);
return $this->handleView($view);
}
In your Image entity, you have to add the #Groups({"type"}) annotation for the webView attribute.
My Problem apparently was just cache related
The idea is that extending my Employee class and setting my isManager property would store it as true in the database whenever a DepartmentHead entity was created. This isn't working. Does anyone know why DepartmentHead entities are being stored with isManager equal to false?
/**
* #Entity
* #InheritanceType("JOINED")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"employee" = "Employee", "dphead" = "DepartmentHead"})
*/
class Employee
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="boolean")
*/
protected static $isManager = false;
/**
* #return bool
*/
public static function isManager(): bool
{
return static::$isManager;
}
/**
* #param bool $isManager
*/
public static function setIsManager(bool $isManager): void
{
static::$isManager = $isManager;
}
}
/**
* #Entity()
*/
class DepartmentHead extends Employee
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
protected $id;
protected static $isManager = true;
}
Do not use static properties, Doctrine cannot cope with them properly.
With a common property, everything works as expected.
/**
* #ORM\Column(type="boolean")
*/
protected $isManager = true;
I have a doubt w.r.t Embedded Forms. I have a "Properties" entity which has 2 fields "id" and "name" and "Amenities" entity which has 2 fields "id" and "value"(id=1,value=wifi,id=2,value=water,id=3,value=food).I have created these 2 entities,but now I want to save the id of "Properties" and "Amenities" into a separate 3rd table.So, I have created a third entity "Properties_Amenities" and its table "properties_amenities".I have created a "one to many" relationship as shown below.I want to embed "Amenities" into "Properties" with the click of an "Add Amenities" button on the "Properties Form".I am not sure as to where to place the "addAmenities()" and "removeAmenities()" functions in the Entity files. Below are 3 entities:-
Properties.php
<?php
namespace EpitaEvents\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Properties
*
* #ORM\Table(name="properties")
* #ORM\Entity
*/
class Properties
{
/**
* #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=100)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="Properties_Amenities", mappedBy="properties",cascade={"persist"})
**/
private $properties_amenities1;
public function __construct() {
$this->properties_amenities1 = new ArrayCollection();
}
/**
* Get id
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*/
public function getName()
{
return $this->name;
}
/**
* Get properties_amenities1
*/
public function getProperties_Amenities1()
{
return $this->properties_amenities1;
}
/**
* Set properties_amenities1
*
*/
public function setProperties_Amenities1($properties_amenities1)
{
$this->properties_amenities1 = $properties_amenities1;
return $this;
}
/**
* Add Amenities
*
* #return Properties
*/
public function addAmenities(\EpitaEvents\FormBundle\Entity\Properties_Amenities $amenities)
{
$amenities->setProperties($this);
$this->amenities[] = $amenities;
return $this;
}
/**
* Remove Amenities
*
*/
public function removeAmenities(\EpitaEvents\FormBundle\Entity\Properties_Amenities $amenities) {
$this->amenities->removeElement($amenities);
}
}
Amenities.php
<?php
namespace EpitaEvents\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Amenities
*
* #ORM\Table(name="amenities")
* #ORM\Entity
*/
class Amenities
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="value", type="string", length=100)
*/
private $value;
/**
* #ORM\OneToMany(targetEntity="Properties_Amenities", mappedBy="amenities")
**/
private $properties_amenities2;
public function __construct() {
$this->properties_amenities2 = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set value
*
* #param string $value
* #return Amenities
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Get value
*
* #return string
*/
public function getValue()
{
return $this->value;
}
/**
* Set Properties
*
*/
public function setProperties_Amenities2($properties_amenities2)
{
$this->properties_amenities2 = $properties_amenities2;
return $this;
}
/**
* Get Properties
*
* #return EpitaEvents\FormBundle\Entity\Properties
*/
public function getProperties_Amenities2()
{
return $this->properties_amenities2;
}
}
(Also should the __construct() be put in these 2 above files or in "Properties_Amenities.php"(Below)???)
Properties_Amenities.php
<?php
namespace EpitaEvents\FormBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Properties_Amenities
*
* #ORM\Table(name="properties_amenities")
* #ORM\Entity
*/
class Properties_Amenities
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Properties", inversedBy="properties_amenities1")
* #ORM\JoinColumn(name="properties_id", referencedColumnName="id")
**/
private $properties;
/**
* #ORM\ManyToOne(targetEntity="Amenities", inversedBy="properties_amenities2")
* #ORM\JoinColumn(name="amenities_id", referencedColumnName="id")
**/
private $amenities;
function getId() {
return $this->id;
}
function getProperties() {
return $this->properties;
}
function getAmenities() {
return $this->amenities;
}
function setProperties($properties) {
$this->properties = $properties;
}
function setAmenities($amenities) {
$this->amenities = $amenities;
}
}
Can any one suggest as to where to place the "addAmenities()" and "removeAmenities()" functions as I want to save the "id's" of "Properties.php" and "Amenities.php" in a "SEPARATE, THIRD" Entity and table??
I have a many to one relation between my entities.
An application can have activities
<?php
namespace AppAcademic\ApplicationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Activity
*
* #ORM\Table()
* #ORM\Entity
*/
class Activity
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="AppAcademic\ApplicationBundle\Entity\Application", inversedBy="activity")
* #ORM\JoinColumn(name="application_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $application;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function setApplication($application)
{
$this->application = $application;
return $this;
}
public function getApplication()
{
return $this->application;
}
/**
* Set title
*
* #param string $title
* #return Activity
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
And the application
/**
* Application
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppAcademic\ApplicationBundle\Entity\ApplicationRepository")
*/
class Application
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="AppAcademic\ApplicationBundle\Entity\Activity", mappedBy="application")
*/
protected $activities;
...
}
I have this in the profiler:
AppAcademic\ApplicationBundle\Entity\Application
The mappings AppAcademic\ApplicationBundle\Entity\Application#activities and AppAcademic\ApplicationBundle\Entity\Activity#application are inconsistent with each other.
AppAcademic\ApplicationBundle\Entity\Application
The mappings AppAcademic\ApplicationBundle\Entity\Application#activities and AppAcademic\ApplicationBundle\Entity\Activity#application are inconsistent with each other.
AppAcademic\ApplicationBundle\Entity\Activity
The association AppAcademic\ApplicationBundle\Entity\Activity#application refers to the inverse side field AppAcademic\ApplicationBundle\Entity\Application#activity which does not exist.
For the mapping annotation ManyToOne on the Activity::$application property, the attribute
inversedBy="activity"
This should be
inversedBy="activities"
I'm having a problem here and I don't know how to fix it. See I have this two entities:
<?php
namespace PI\ProyectoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Event\LifecycleEventArgs;
/**
* #ORM\Entity
* #ORM\Table(name="proyectos")
* #ORM\Entity(repositoryClass="PI\ProyectoBundle\Entity\Repository\ProyectosRepository")
* #ORM\HasLifecycleCallbacks
*/
class Proyectos {
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="string", length=45, unique=true, nullable=false)
*/
protected $nombre;
/**
* #ORM\Column(type="boolean", nullable=true)
*/
protected $estado;
/**
* #ORM\Column(type="string", length=45, nullable=false)
*/
protected $pais;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="PI\ClienteBundle\Entity\Clientes", cascade={"all"})
* #ORM\JoinColumn(name="cliente", referencedColumnName="id")
*/
protected $clientes;
/**
* #ORM\ManyToMany(targetEntity="PI\CentroBundle\Entity\Centros", inversedBy="proyectos", cascade={"persist"})
* #ORM\JoinTable(name="proyectos_has_centros",
* joinColumns={#ORM\JoinColumn(name="proyectos_id", referencedColumnName="id"),
* #ORM\JoinColumn(name="proyectos_cliente", referencedColumnName="cliente")},
* inverseJoinColumns={#ORM\JoinColumn(name="centros_id", referencedColumnName="id")}
* )
*/
protected $centros;
/**
* #ORM\ManyToMany(targetEntity="Application\Sonata\UserBundle\Entity\User", cascade={"persist"})
* #ORM\JoinTable(name="proyectos_has_system_user",
* joinColumns={#ORM\JoinColumn(name="proyectos_id", referencedColumnName="id"),
* #ORM\JoinColumn(name="proyectos_cliente", referencedColumnName="cliente")},
* inverseJoinColumns={#ORM\JoinColumn(name="system_user_id", referencedColumnName="id")}
* )
*/
protected $ingenieros;
public function __construct() {
$this->centros = new \Doctrine\Common\Collections\ArrayCollection();
$this->ingenieros = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getId() {
return $this->id;
}
public function setNombre($nombre) {
$this->nombre = $nombre;
}
public function getNombre() {
return $this->nombre;
}
public function setEstado($estado) {
$this->estado = $estado;
}
public function getEstado() {
return $this->estado;
}
public function setPais($pais) {
$this->pais = $pais;
}
public function getPais() {
return $this->pais;
}
public function setClientes(\PI\ClienteBundle\Entity\Clientes $clientes) {
$this->clientes = $clientes;
}
public function getClientes() {
return $this->clientes;
}
public function setCentros(\PI\CentroBundle\Entity\Centros $centros) {
$this->centros[] = $centros;
}
public function getCentros() {
return $this->centros;
}
public function setIngenieros(\BIT\UserBundle\Entity\User $ingenieros) {
$this->ingenieros[] = $ingenieros;
}
public function getIngenieros() {
return $this->ingenieros;
}
/**
* #ORM\PrePersist
*/
public function prePersist(LifecycleEventArgs $eventArgs) {
$em = $eventArgs->getEntityManager();
$q = $em->createQuery('SELECT MAX(p.id) FROM PIProyectoBundle:Proyectos p');
$id = $q->getSingleResult(\Doctrine\ORM\Query::HYDRATE_SINGLE_SCALAR);
$this->id = $id + 1;
}
}
And this other:
<?php
namespace PI\UnidadBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="horas_por_proyectos")
*/
class HorasPorUnidad {
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", cascade={"all"})
* #ORM\JoinColumn(name="fos_user_user_id", referencedColumnName="id")
*/
protected $fos_user_user_id;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="PI\UnidadBundle\Entity\Unidades", cascade={"all"})
* #ORM\JoinColumn(name="fos_user_user_id", referencedColumnName="id")
*/
protected $unidades_id;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="PI\CentroBundle\Entity\Centros", cascade={"all"})
* #ORM\JoinColumn(name="centros_id", referencedColumnName="id")
*/
protected $centros_id;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="PI\ProyectoBundle\Entity\Proyectos", cascade={"all"})
* #ORM\JoinColumn(name="proyectos_id", referencedColumnName="id")
*/
protected $proyectos_id;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="PI\ClienteBundle\Entity\Clientes", cascade={"all"})
* #ORM\JoinColumn(name="proyectos_cliente", referencedColumnName="id")
*/
protected $proyectos_cliente;
/**
* #ORM\Column(type="date")
*/
protected $fecha;
/**
* #ORM\Column(type="integer")
*/
protected $horas;
public function setUserId(\Application\Sonata\UserBundle\Entity\User $user) {
$this->fos_user_user_id = $user;
}
public function getUserId() {
return $this->fos_user_user_id;
}
public function setUnidadesId(\PI\UnidadBundle\Entity\Unidades $unidad) {
$this->unidades_id = $unidad;
}
public function getUnidadesId() {
return $this->unidades_id;
}
public function setCentrosId(\PI\CentroBundle\Entity\Centros $centro) {
$this->centros_id = $centro;
}
public function getCentrosId() {
return $this->centros_id;
}
public function setHoras($cantidad_horas) {
$this->horas = $cantidad_horas;
}
public function getHoras() {
return $this->horas;
}
public function setFecha($fecha) {
$this->fecha = $fecha;
}
public function getFecha() {
return $this->fecha;
}
}
But when I run the task php app/console doctrine:schema:validate I get this errors:
[Mapping] FAIL - The entity-class 'PI\UnidadBundle\Entity\HorasPorUnidad' mapping is invalid:
Cannot map association 'PI\UnidadBundle\Entity\HorasPorUnidad#proyectos_id as identifier, because the target entity 'PI\ProyectoBundle\Entity\Proyectos' also maps an association as identifier.
The join columns of the association 'proyectos_id' have to match to ALL identifier columns of the target entity 'PI\UnidadBundle\Entity\HorasPorUnidad', however 'id, cliente' are missing.
And I don't know how to fix them, so any help from experts? What I need to fix here?
You foget the mappedBy and inversedBy attributes in the ManyToOne assocciation and also check the other side of your assocciations:
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="PI\ClienteBundle\Entity\Clientes",inversedBy="?" cascade={"all"})
* #ORM\JoinColumn(name="cliente", referencedColumnName="id")
*/
protected $clientes;