Doctrine Inheritance and user types - php

im new to Doctrine and ORM in general.
I got 4 user types (Admin, Caretaker, Child, Personal).
They all got some of the same columns (id, name, mail, password, created, type & group)
and they got a few columns special to each of them (Caretaker has a child id etc.)
I'm not quite sure how i should map this.
Like should i make my user types extend the User, giving the Child table the user columns, or what would be best practice here?
I assume the the option to use extend would force some more work when doing a login?
User.php
/**
* #MappedSuperclass
* #Entity #Table(name="users")
*/
class User
{
/**
* #Id #GeneratedValue #Column(type="integer")
* #var int
**/
protected $id;
/**
* #Column(type="string")
* #var string
**/
protected $name;
/**
* #Column(type="string")
* #var string
**/
protected $mail;
/**
* #Column(type="string")
* #var string
**/
protected $password;
/**
* #Column(type="datetime")
**/
protected $created;
/**
* #Column(type="datetime")
**/
protected $lastlogin;
/**
* #ManyToOne(targetEntity="Group")
* #JoinColumn(name="group_id", referencedColumnName="id")
*/
protected $group;
/**
* #ManyToOne(targetEntity="Type")
* #JoinColumn(name="type_id", referencedColumnName="id")
*/
protected $type;
public function __construct() {}
public function getId() { return $this->id; }
public function getName() { return $this->name; }
public function getMail() { return $this->mail; }
public function getCreated() { return $this->mail; }
public function getLastLogin() { return $this->lastlogin; }
public function getGroup() { return $this->group; }
public function getType() { return $this->type; }
public function setName($name) { $this->name = $name; }
public function setMail($mail) { $this->mail = $mail; }
public function setCreated() { $this->created = new DateTime("now"); }
public function setLastLogin() { $this->lastlogin = new DateTime("now"); }
public function setGroup($group) { $this->group = $group; }
public function setType($type) { $this->type = $type; }
}
Child.php
// src/Child.php
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity #Table(name="child")
*/
class Child extends User
{
/**
* #Id #OneToOne(targetEntity="User")
* #JoinColumn(name="id", referencedColumnName="id")
**/
protected $id;
/**
* #Column(type="string")
*/
protected $image;
/**
* #ManyToMany(targetEntity="User")
* #JoinTable(name="child_Contacts",
* joinColumns={#JoinColumn(name="child_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="contact_id", referencedColumnName="id")}
* )
*/
protected $currentContacts;
/**
* #OneToMany(targetEntity="Alarm", mappedBy="child")
*/
protected $alarms;
public function __construct()
{
$this->alarms = new ArrayCollection();
}
}

You can easily solve this problem with doctrine and InheritanceType mapping.
Basically, you can do something like this :
/**
* #MappedSuperclass
* #Entity #Table(name="users")
* #InheritanceType("JOINED")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"Admin" = "Admin", "Caretaker" = "Caretaker", "Child" = "Child", "Personal" = "Personal"})
*/
class User
{
/**
* #Id #GeneratedValue #Column(type="integer")
* #var int
**/
protected $id;
/**
* #Column(type="string")
* #var string
**/
protected $name;
/**
* #Column(type="string")
* #var string
**/
protected $mail;
/**
* #Column(type="string")
* #var string
**/
protected $password;
/**
* #Column(type="datetime")
**/
protected $created;
/**
* #Column(type="datetime")
**/
protected $lastlogin;
/**
* #ManyToOne(targetEntity="Group")
* #JoinColumn(name="group_id", referencedColumnName="id")
*/
protected $group;
}
And then, in each 4 different classes,
// src/Child.php
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity #Table(name="child")
*/
class Child extends User
{
/**
* #Id #OneToOne(targetEntity="User")
* #JoinColumn(name="id", referencedColumnName="id")
**/
protected $id;
/**
* #Column(type="string")
*/
protected $image;
/**
* #ManyToMany(targetEntity="User")
* #JoinTable(name="child_Contacts",
* joinColumns={#JoinColumn(name="child_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="contact_id", referencedColumnName="id")}
* )
*/
protected $currentContacts;
/**
* #OneToMany(targetEntity="Alarm", mappedBy="child")
*/
protected $alarms;
public function __construct()
{
$this->alarms = new ArrayCollection();
}
}
The doctrine docs is really good for this problem : http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html
And you don't need an extra check at login because doctrine create automatically the right class for you.

Related

Failed to create object. Many-To-Many relation

I have a problem with my code. It's about a restaurant. I have two objects with a Many-To-Many relation: Products and Days. When I try to create a Day, I receive this error: "Failed to create object: App\Entity\Day\Day". Where am I wrong?
I put the code for entities here. If you need more just tell me. I don't think that it is from admin part.
Here is the Product entity:
<?php
namespace App\Entity\Product;
use App\Entity\Category\Category;
use App\Entity\Day\Day;
use App\Entity\ProductEntry\ProductEntry;
use App\Entity\Restaurant\Restaurant;
use App\Entity\Schedule\Schedule;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
/**
* Class Product
* #ORM\Entity(repositoryClass="App\Repository\Product\ProductRepository")
* #ORM\Table(name="products")
* #package App\Entity\Product
*/
class Product
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255, nullable=true)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="added_date", type="datetime", nullable=false)
*/
private $addedDate;
/**
* #var boolean
*
* #ORM\Column(name="availability", type="boolean", nullable=true)
*/
private $availability;
/**
* #var Category
*
* #ORM\ManyToOne(targetEntity="App\Entity\Category\Category", inversedBy="products", cascade={"persist"})
* #ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
*/
private $category;
/**
* #var float
*
* #ORM\Column(name="price", type="float", length=255, nullable=true)
*/
private $price;
/**
* #var ProductEntry
*
* #ORM\OneToMany(targetEntity="App\Entity\ProductEntry\ProductEntry", mappedBy="originalProduct", cascade={"persist"})
* #Serializer\Exclude()
*/
private $productsEntries;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Schedule\Schedule", inversedBy="products", cascade={"persist"})
* #ORM\JoinColumn(name="schedule_id", referencedColumnName="id", onDelete="CASCADE")
*
* #var Schedule
*/
private $schedule;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Restaurant\Restaurant", inversedBy="products", cascade={"persist"})
* #ORM\JoinColumn(name="restaurant_id", referencedColumnName="id", onDelete="CASCADE")
*
* #var Restaurant
*/
private $restaurant;
/**
* #var Day
*
* #ORM\ManyToMany(targetEntity="App\Entity\Day\Day", mappedBy="products", cascade={"persist"})
*/
private $days;
public function __toString()
{
return $this->name ?: "";
}
public function __construct()
{
$this->addedDate = new \DateTime();
$this->days = new ArrayCollection();
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id)
{
$this->id = $id;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #param string $name
*/
public function setName(string $name)
{
$this->name = $name;
}
/**
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* #param string $description
*/
public function setDescription(string $description)
{
$this->description = $description;
}
/**
* #return mixed
*/
public function getAddedDate()
{
return $this->addedDate;
}
/**
* #param mixed $addedDate
*/
public function setAddedDate($addedDate)
{
$this->addedDate = $addedDate;
}
/**
* #return bool
*/
public function isAvailability()
{
return $this->availability;
}
/**
* #param bool $availability
*/
public function setAvailability($availability)
{
$this->availability = $availability;
}
/**
* #return float
*/
public function getPrice()
{
return $this->price;
}
/**
* #param float $price
*/
public function setPrice($price)
{
$this->price = $price;
}
/**
* #return Category
*/
public function getCategory()
{
return $this->category;
}
/**
* #param Category $category
*/
public function setCategory($category): void
{
$this->category = $category;
}
/**
* #return ProductEntry
*/
public function getProductsEntries()
{
return $this->productsEntries;
}
/**
* #param ProductEntry $productsEntries
*/
public function setProductsEntries(ProductEntry $productsEntries): void
{
$this->productsEntries = $productsEntries;
}
/**
* #return Schedule
*/
public function getSchedule()
{
return $this->schedule;
}
/**
* #param Schedule $schedule
*/
public function setSchedule(Schedule $schedule): void
{
$this->schedule = $schedule;
}
/**
* #return Restaurant
*/
public function getRestaurant()
{
return $this->restaurant;
}
/**
* #param Restaurant $restaurant
*/
public function setRestaurant(Restaurant $restaurant): void
{
$this->restaurant = $restaurant;
}
/**
* #return Day
*/
public function getDays()
{
return $this->days;
}
/**
* #param Day $days
*/
public function setDays(Day $days): void
{
$this->days = $days;
}
}
Here is Day entity:
<?php
namespace App\Entity\Day;
use App\Entity\Product\Product;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Class Day
* #package App\Entity\Day
* #ORM\Entity(repositoryClass="App\Repository\Day\DayRepository")
* #ORM\Table(name="days")
*/
class Day
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", nullable=false)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="current_date", type="datetime", nullable=false)
*/
private $currentDate;
/**
* #var \DateTime
*
* #ORM\Column(name="max_date", type="datetime", nullable=true)
*/
private $maxDate;
/**
* #var Product
*
* #ORM\ManyToMany(targetEntity="App\Entity\Product\Product", inversedBy="days", cascade={"persist"})
* #ORM\JoinTable(name="product_day",
* joinColumns={#ORM\JoinColumn(name="day_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="product_id", referencedColumnName="id")})
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #param string $name
*/
public function setName(string $name): void
{
$this->name = $name;
}
/**
* #return \DateTime
*/
public function getCurrentDate()
{
return $this->currentDate;
}
/**
* #param \DateTime $currentDate
*/
public function setCurrentDate(\DateTime $currentDate): void
{
$this->currentDate = $currentDate;
}
/**
* #return \DateTime
*/
public function getMaxDate()
{
return $this->maxDate;
}
/**
* #param \DateTime $maxDate
*/
public function setMaxDate(\DateTime $maxDate): void
{
$this->maxDate = $maxDate;
}
/**
* #return Product
*/
public function getProducts()
{
return $this->products;
}
/**
* #param Product $products
*/
public function setProducts(Product $products): void
{
$this->products = $products;
}
}
It seems that you created a column for your Day Entity that is called current_date
/**
* #var \DateTime
*
* #ORM\Column(name="current_date", type="datetime", nullable=false)
*/
private $currentDate;
If you are using MySQL, current_date is a reserved word. Please check https://dev.mysql.com/doc/refman/5.5/en/keywords.html for further reference.
Like Vincent said in comment, your namespaces are fishy...
Unless you really placed them in a sub-folder, it should be namespace App\Entity
In Product entity you can shorten you JoinColumn for some parameters.
Unless you really need something specific, you don't need to write that much. Symfony have 'default' values.
Also, you don't add #var on a mapping. Symfony will take is as a parameter only instead of mapping.
/**
* #var Category
*
* #ORM\ManyToOne(targetEntity="App\Entity\Category\Category", inversedBy="products", cascade={"persist"})
* #ORM\JoinColumn(onDelete="CASCADE", nullable=true)
*/
private $category;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Schedule\Schedule", inversedBy="products", cascade={"persist"})
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $schedule;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Restaurant\Restaurant", inversedBy="products", cascade={"persist"})
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $restaurant;
The same apply to your Day entity.
/**
* #var Product
*
* #ORM\ManyToMany(targetEntity="App\Entity\Product\Product", inversedBy="days", cascade={"persist"})
* #ORM\JoinTable(name="product_day")
*/
private $products;
Doing so will prevent you to make some smalls mapping errors.
Try to correct those points first, then let us know if you still have your problem.

Why my symfony entity is not managed?

I have a Portfolio entity which is working well to create or update but I can't delete it. Symfony throws this error:
Entity matthieu-appriou is not managed. An entity is managed if its
fetched from the database or registered as new through
EntityManager#persist
Here is my entity:
<?php
namespace CreasensoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use SensoBundle\Entity\Talent;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;
use JMS\Serializer\Annotation\MaxDepth;
use JMS\Serializer\Annotation\Exclude;
/**
* Portfolio
*
* #ORM\Entity
* #ORM\Table(name="portfolio")
* #ORM\Entity(repositoryClass="CreasensoBundle\Repository\PortfolioRepository")
*/
class Portfolio
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var bool
*
* #ORM\Column(name="visible", type="boolean", nullable=true)
*/
private $visible;
/**
* #Exclude
* #ORM\OneToOne(targetEntity="SensoBundle\Entity\Talent", cascade={"persist", "remove"}, inversedBy="portfolio")
* #ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $talent;
/**
* #Exclude
* #ORM\OneToOne(targetEntity="SensoBundle\Entity\Image", cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=true, onDelete="SET NULL")
*/
private $image;
/**
* #var string
*
* #ORM\Column(name="folio_label", type="string", length=400, nullable=true)
* #Gedmo\Translatable
*/
private $folioLabel;
/**
* #var string
*
* #ORM\Column(name="main_customers", type="string", length=400, nullable=true)
*/
private $mainCustomers;
/**
* #var string
*
* #ORM\Column(name="main_agencies", type="string", length=400, nullable=true)
*/
private $mainAgencies;
/**
* #var string
*
* #ORM\Column(name="publications", type="string", length=700, nullable=true)
*/
private $publications;
/**
* #var string
*
* #ORM\Column(name="description_title", type="string", length=400, nullable=true)
* #Gedmo\Translatable
*/
private $descriptionTitle;
/**
* #var string
*
* #ORM\Column(name="description_content", type="text", nullable=true)
* #Gedmo\Translatable
*/
private $descriptionText;
/**
* #MaxDepth(2)
* #ORM\ManyToMany(targetEntity="SensoBundle\Entity\Expertise", cascade={"persist"})
*/
private $expertises;
/**
* #var \DateTime $created
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $created;
/**
* #var \DateTime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $updated;
/**
* #var \DateTime $updated
*
* #ORM\Column(type="datetime", nullable=true)
*/
private $mostRecentProjectDate;
/**
* #var \DateTime $featuredTime
* #ORM\Column(type="datetime", nullable=true)
*/
private $featuredTime;
/**
* #var \DateTime $submissionTime
* #ORM\Column(type="datetime", nullable=true)
*/
private $submissionTime;
/**
* #Gedmo\Locale
*/
protected $locale;
public function __construct()
{
$this->setVisible(false);
$this->expertises = new ArrayCollection();
}
public function __toString() {
return $this->getSlug();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
public function getSlug()
{
return $this->getTalent()->getSlug();
}
/**
* Set visible
*
* #param boolean $visible
*
* #return Portfolio
*/
public function setVisible($visible)
{
$this->visible = $visible;
return $this;
}
/**
* Get visible
*
* #return bool
*/
public function getVisible()
{
return $this->visible;
}
/**
* #return mixed
*/
public function getTalent()
{
return $this->talent;
}
/**
* #param mixed $talent
*/
public function setTalent($talent)
{
$this->talent = $talent;
$talent->setPortfolio($this);
}
/**
* #return mixed
*/
public function getImage()
{
return $this->image;
}
/**
* #param mixed $image
*/
public function setImage($image)
{
if ($image) {
$image->setParentType('portfolio');
}
$this->image = $image;
}
/**
* #return string
*/
public function getMainCustomers()
{
return $this->mainCustomers;
}
/**
* #param string $mainCustomers
*/
public function setMainCustomers($mainCustomers)
{
$this->mainCustomers = $mainCustomers;
}
/**
* #return string
*/
public function getMainAgencies()
{
return $this->mainAgencies;
}
/**
* #param string $mainAgencies
*/
public function setMainAgencies($mainAgencies)
{
$this->mainAgencies = $mainAgencies;
}
/**
* #return string
*/
public function getDescriptionTitle()
{
return $this->descriptionTitle;
}
/**
* #param string $descriptionTitle
*/
public function setDescriptionTitle($descriptionTitle)
{
$this->descriptionTitle = $descriptionTitle;
}
/**
* #return string
*/
public function getDescriptionText()
{
return $this->descriptionText;
}
/**
* #param string $descriptionText
*/
public function setDescriptionText($descriptionText)
{
$this->descriptionText = $descriptionText;
}
public function addExpertise($expertise)
{
$this->expertises[] = $expertise;
return $this;
}
public function removeExpertise($expertise)
{
$this->expertises->removeElement($expertise);
}
public function getExpertises()
{
return $this->expertises;
}
public function setExpertises($expertises)
{
$this->expertises = $expertises;
}
/**
* #return mixed
*/
public function getCreated()
{
return $this->created;
}
/**
* #param mixed $created
*/
public function setCreated($created)
{
$this->created = $created;
}
/**
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* #param \DateTime $updated
*/
public function setUpdated($updated)
{
$this->updated = $updated;
}
/**
* #return \DateTime
*/
public function getFeaturedTime()
{
return $this->featuredTime;
}
/**
* #param \DateTime $featuredTime
*/
public function setFeaturedTime($featuredTime)
{
$this->featuredTime = $featuredTime;
}
/**
* #return string
*/
public function getPublications()
{
return $this->publications;
}
/**
* #param string $publications
*/
public function setPublications($publications)
{
$this->publications = $publications;
}
/**
* #return mixed
*/
public function getSubmissionTime()
{
return $this->submissionTime;
}
/**
* #param mixed $submissionTime
*/
public function setSubmissionTime($submissionTime)
{
$this->submissionTime = $submissionTime;
}
/**
* #return string
*/
public function getFolioLabel()
{
return $this->folioLabel;
}
/**
* #param string $folioLabel
*/
public function setFolioLabel($folioLabel)
{
$this->folioLabel = $folioLabel;
}
public function getType()
{
return 'portfolio';
}
/**
* #return \DateTime
*/
public function getMostRecentProjectDate()
{
return $this->mostRecentProjectDate;
}
/**
* #param \DateTime $mostRecentProjectDate
*/
public function setMostRecentProjectDate($mostRecentProjectDate)
{
$this->mostRecentProjectDate = $mostRecentProjectDate;
}
public function setTranslatableLocale($locale)
{
$this->locale = $locale;
}
}
And here is the code sample I use to reproduce this error:
<?php
// namespace and use ...
/**
* Tool controller.
*
* #Route("/admin/test")
*/
class TestController extends Controller
{
/**
*
* #Route("/testTwo", name="testTwo")
* #Method({"GET", "POST"})
*/
public function indexTwoAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$pr = $this->get('creasenso.portfolio_repo');
$p = $pr->find(32);
$em->remove($p);
$em->flush();
return new Response("<html><head></head><body><hr />Done</body></html>");
}
}
Here is the repository linked to this entity:
<?php
namespace CreasensoBundle\Repository;
use Doctrine\ORM\EntityRepository;
/**
* PortfolioRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class PortfolioRepository extends EntityRepository
{
protected $qb;
public function init()
{
$this->qb = $this->createQueryBuilder('p');
}
public function isVisible()
{
$this->qb
->andWhere('p.visible = :visible')
->setParameter(':visible', 1);
}
public function getAllPublicPortfolioCount()
{
$this->init();
$this->isVisible();
$this->qb->select('COUNT(p)');
return $this->qb->getQuery()->getSingleScalarResult();
}
public function getQueryBuilder()
{
return $this->qb;
}
}
Do you have any clue about this behavior? Thank you very much.
You are getting your repository directly from the service container when you should be getting it from your EntityManager through getRepository().
You are not loading your entity from the entityManager that you flush so it is not managed

Mapping FAIL - The entity-class 'PI\UnidadBundle\Entity\HorasPorUnidad' mapping is invalid

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;

Symfony2 Entity doctrine2 don't update field

I have this entity:
Profile.php
/**
* LoPati\BlogBundle\Entity\Profile
*
* #ORM\Table(name="profile")
* #ORM\Entity
* #Gedmo\TranslationEntity(class="LoPati\BlogBundle\Entity\ProfileTranslation")
*/
class Profile
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Gedmo\Translatable
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
protected $name=null;
/**
* #var text $description
* #Gedmo\Translatable
* #ORM\Column(name="description", type="text", nullable=true)
*/
protected $description=null;
/**
* #ORM\OneToMany(targetEntity="ProfileTranslation", mappedBy="object", cascade={"persist", "remove"})
*/
protected $translations;
/**
* Required for Translatable behaviour
* #Gedmo\Locale
*/
protected $locale;
public function __construct()
{
$this->translations = new ArrayCollection;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
public function getLocale()
{
return $this->locale;
}
public function setLocale($locale)
{
$this->locale = $locale;
}
public function setName($name)
{
$this->name=$name;
}
public function getName()
{
return $this->name;
}
public function setDescription($description)
{
}
public function getDescription()
{
return $this->description;
}
public function getTranslations()
{
return $this->translations;
}
public function addTranslation(ProfileTranslation $t)
{
$this->translations->add($t);
$t->setObject($this);
$this->name = $this->translations[0];
$this->description = $this->translations[1];
}
public function removeTranslation(ProfileTranslation $t)
{
$this->translations->removeElement($t);
}
public function setTranslations($translations)
{
$this->translations = $translations;
$this->name = $this->translations[0];
$this->description = $this->translations[1];
}
public function __toString()
{
return "hola";
}
}
And ProfileTranslation.php
/**
* #ORM\Entity
* #ORM\Table(name="profile_translations",
* uniqueConstraints={#ORM\UniqueConstraint(name="lookup_unique_idx", columns={
* "locale", "object_id", "field"
* })}
* )
*/
class ProfileTranslation extends AbstractPersonalTranslation
{
/**
* Convinient constructor
*
* #param string $locale
* #param string $field
* #param string $content
*/
public function __construct($locale = null, $field = null, $content = null)
{
$this->setLocale($locale);
$this->setField($field);
$this->setContent($content);
}
/**
* #ORM\ManyToOne(targetEntity="Profile", inversedBy="translations")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $object;
public function __toString()
{
return $this->getContent();
}
}
I want that when edit arraycollection that is a ProfileTranslation table, then also update the name and description field but form Profile Table, and it be the first element that collection.
It work when I create new Profile, but when I edit this profile, only update the ProfileTranslation Table and not Profile table.
How I can do it?
Your implementation turns away a little too classic Translatable use.
You could maybe have a look about TranslationFormBundle and its Demo if it right for you.

Doctrine 2.1 - Call to undefined method + MyMethod(Proxy)?

I have two classes:
News:
/** #Entity #Table(name="news") */
class News {
/**
* #Id #GeneratedValue #Column(type="integer")
* #var integer
*/
protected $id;
/**
* #Column(type="string", length=100)
* #var string
*/
protected $title;
/**
* #Column(type="text")
* #var string
*/
protected $content;
/**
* #ManyToOne(targetEntity="User", inversedBy="news")
* #JoinColumn(referencedColumnName="id")
*/
protected $author;
/**
* #ManyToOne(targetEntity="NewsCategory", inversedBy="news")
* #JoinColumn(referencedColumnName="id")
*/
protected $category;
/**
* #Column(type="datetime")
*/
protected $add_date;
# CATEGORY methods
public function setCategory($val) { if($val instanceof NewsCategory) $this->category = $val; }
public function getCategory() { return $this->category; }
}
NewsCategory:
/** #Entity #Table(name="news_category") */
class NewsCategory {
/**
* #Id #GeneratedValue #Column(type="integer")
* #var integer
*/
protected $id;
/**
* #Column(type="string", length=50, unique=TRUE)
* #var string
*/
protected $name;
/**
* #OneToMany(targetEntity="News", mappedBy="category")
*/
protected $news;
public function __construct() {
$this->news = new \Doctrine\Common\Collections\ArrayCollection;
}
public function setName($name) { $this->name = $name; }
public function getName() { return $this->name; }
public function getNews() { return $this->news; }
}
I want to download one news with this query:
$q = $this->db->createQuery("SELECT n FROM News n WHERE n.id = :id");
$q->setParameter('id', $_GET['id']);
$news = $q->getResult();
And next, I want to get id of a Category related to this news with
$news->getCategory()->getId()
With code above, I'm getting this error:
Fatal error: Call to undefined method DoctrineProxies\NewsCategoryProxy::getId() in C:\[...]\newsController.php on line 61
What's wrong? Why my NewsCategory class can't see getId() method?
It's a good practice to allways declare your class' members private and to generate getters and setters on your class members.
In your case, you don't generate getters and setters (there is no getId() method on your NewCategory class).
That's how your NewCategory class should look like :
/** #Entity #Table(name="news_category") */
class NewsCategory {
/**
* #Id #GeneratedValue #Column(type="integer")
* #var integer
*/
private $id;
/**
* #Column(type="string", length=50, unique=TRUE)
* #var string
*/
private $name;
/**
* #OneToMany(targetEntity="News", mappedBy="category")
*/
private $news;
public function __construct() {
$this->news = new \Doctrine\Common\Collections\ArrayCollection;
}
public function getId(){ return $this->id;}
public function setId($id){ $this->id = $id;}
public function setName($name) { $this->name = $name; }
public function getName() { return $this->name; }
public function setNews($news) {$this->news = $news;}
public function getNews() { return $this->news; }
}
The generated proxies will not generate magically getters and setters on every of your properties (it would break the OOP's encapsulation principle).
You can find more documentations about proxies here : http://www.doctrine-project.org/docs/orm/2.0/en/reference/configuration.html#proxy-objects

Categories