In symfony I have a Cliente entity that can have N Reservas:
class Cliente {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Reserva", mappedBy="cliente")
*
*/
private $reservas;
....
}
class Reserva
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Cliente", inversedBy="reservas")
*
*/
private $cliente;
...}
In the ReservaType I have:
class ReservaType extends AbstractType {
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('cliente')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'partes\EscuelaBundle\Entity\Reserva'
));
}
/**
* #return string
*/
public function getName() {
return 'partes_escuelabundle_reserva';
}
}
All that when I create a new reserva show my the typical select option with the list of all customers. I would change that for a ajax input type to select the customer. Any idea how to build it.
Thanks you!
fix it, with a ajax call that bring a list of links. Once clicking in the link it creates the new Reserva.
I have tried to create the database schema by running the artisan command through CLI and got the following error:
The annotation "#Doctrine\ORM\Mapping\Names" in property App\Entity\Vouchers::$names does not exist, or could not be auto-loaded.
Following the Code for my Entity.
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="vouchers")
**/
class Vouchers
{
/**
* #var integer $id
* #ORM\Column(name="id", type="integer", unique=true, nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* #var string $names
* #ORM\Column(name="names", type="string", unique=false, nullable=false)
* #ORM\Names
*
*/
private $names;
/**
* #var string $amount
* #ORM\Column(name="amount", type="string", unique=false, nullable=false)
* #ORM\Amount
*
*/
private $amount;
//Getter And Setters
//ID
public function getId()
{
return $this->id;
}
//name
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
//amount
public function getAmount()
{
return $this->amount;
}
public function setAmount($amount)
{
$this->amount = $amount;
}
}
Please check and let me know if there is any mistake i have made in the above code and how it can be fixed. I have tried many other solution but still i am not able to figure this out.
Fixed it by replacing the name section with the following
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=150, nullable=false)
*/
private $name;
I generated Entities with Doctrine's generating method inside Doctrine.php from CodeIgniter Controller:
function generate_classes(){
$this->em->getConfiguration()
->setMetadataDriverImpl(
new DatabaseDriver(
$this->em->getConnection()->getSchemaManager()
)
);
$cmf = new DisconnectedClassMetadataFactory();
$cmf->setEntityManager($this->em);
$metadata = $cmf->getAllMetadata();
$generator = new EntityGenerator();
$generator->setUpdateEntityIfExists(true);
$generator->setGenerateStubMethods(true);
$generator->setGenerateAnnotations(true);
$generator->generate($metadata, APPPATH."models/Entities");
}
The generated Entity had this syntax:
use Doctrine\ORM\Mapping as ORM;
/**
* Users
*
* #ORM\Table(name="users")
* #ORM\Entityz
*/
class Users
{
/**
* #var integer
*
* #ORM\Column(name="idusers", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idusers;
/**
* #var string
*
* #ORM\Column(name="first_name", type="string", length=45, nullable=true)
*/
private $firstName;
/**
* #var string
*
* #ORM\Column(name="last_name", type="string", length=45, nullable=true)
*/
Now calling these Entities form my model didn't work. The model didn't find the entity. After manually changing the syntax to the following code example, I got it to work:
use Doctrine\ORM\Mapping as ORM;
/**
* Users
*
* #Entity #Table(name="users")
*/
class Users
{
/**
* #var integer
*
* #Column(name="idusers", type="integer", nullable=false)
* #Id
*
*/
private $idusers;
/**
*
* #GeneratedValue
* #Column(name="first_name", type="string", length=45, nullable=true)
*/
private $firstName;
And now everything works!
I am not going to manually change every Entity.
How can I configure Doctrine to produce Entity's with the correct syntax. As used in their tutorials as well? http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html
Noob question. Please help!
Found the solution:
changed in application/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php the constructor from:
public function __construct()
{
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
$this->annotationsPrefix = 'ORM\\';
}
}
To:
public function __construct()
{
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
$this->annotationsPrefix = '';
}
}
I have 3 entities:
/**
* #ORM\Entity
* #ORM\Table(name="table_a")
*/
class A
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* ORM\OneToMany(targetEntity="B", mappedBy="entityA")
*/
protected $entitiesB;
/**
* ORM\OneToMany(targetEntity="C", mappedBy="entityA")
*/
protected $entitiesC;
/**
* #ORM\Column(type="string")
*/
protected $name;
}
/**
* #ORM\Entity
* #ORM\Table(name="table_b")
*/
class B
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* ORM\ManyToOne(targetEntity="A", inversedBy="entitiesB")
*/
protected $entityA;
/**
* #ORM\Column(type="date")
*/
protected $date;
}
/**
* #ORM\Entity
* #ORM\Table(name="table_c")
*/
class C
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* ORM\ManyToOne(targetEntity="A", inversedBy="entitiesC")
*/
protected $entityA;
/**
* #ORM\Column(type="string")
*/
protected $description;
}
And I have the following situation:
$eB = $repositoryB->find(1);
$eA = $eB->getEntityA(); // $eA will be a proxy
$eC = new C();
$eC->setDescription('XXXXXXXXXX')
->setEntityA($eA);
This will generate an error because $eA is a proxy not an entity. Even if I try:
$eB = $repositoryB->find(1);
$eA = $repositoryA->find(1);
$eC = new C();
$eC->setDescription('XXXXXXXXXX')
->setEntityA($eA);
Will still get an error because once you have fetched a B entity it will automatically fetch a proxy of A entity. And when you try to fetch the A entity with the same identifier as the proxy Doctrine will return the proxy object from the Identity Map because you can not have two objects (one proxy and one Entity) for the same db record.
So is there a way to force retrieving an entity from its proxy? Or another way to set an association, by id not by entity?
I have a patner, a buyer and an admin class that inherit a user class
When I want to add a partner, the validator do not work
* #DoctrineAssert\UniqueEntity(fields="username", message="Ce nom d'utilisateur est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
* #DoctrineAssert\UniqueEntity(fields="mail", message="Cette adresse mail est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
If I choose a username to a "partner" that is already in database, it shows me the right validation error. But if I choose the username of a "buyer" which is already in the database, there is no verification, and have a unique field error in my databases.
Class User
<?php
namespace Antho\Test\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
/**
* Antho\Test\CoreBundle\Entity\User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Antho\Test\CoreBundle\Entity\UserRepository")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"user" = "User", "partner" = "Partner", "buyer" = "Buyer", "admin" = "Admin"})
* #ORM\HasLifecycleCallbacks()
* #DoctrineAssert\UniqueEntity(fields="username", message="Ce nom d'utilisateur est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
* #DoctrineAssert\UniqueEntity(fields="mail", message="Cette adresse mail est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"})
*/
class User implements UserInterface
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $username
*
* #ORM\Column(name="username", type="string", length=255, unique=true)
*/
private $username;
/**
* #var string $lastName
*
* #ORM\Column(name="last_name", type="string", length=255)
*/
private $lastName;
/**
* #var string $firstName
*
* #ORM\Column(name="first_name", type="string", length=255)
*/
private $firstName;
/**
* #var string $mail
*
* #ORM\Column(name="mail", type="string", length=255, unique=true)
*/
private $mail;
/**
* #var string $password
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
public function __construct()
{
if ($this->createdAt === null) {
$this->createdAt = new \DateTime('now');
}
$this->isEnabled = true;
}
public function __toString()
{
return $this->username;
}
GETTER and SETTER ...
}
Class Partner
<?php
namespace Antho\Test\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
/**
* Antho\Test\CoreBundle\Entity\Partner
*
* #ORM\Table(name="partner")
* #ORM\Entity(repositoryClass="Antho\Test\CoreBundle\Entity\PartnerRepository")
*/
class Partner extends User
{
/**
* #ORM\OneToMany(targetEntity="Restaurant", mappedBy="partner", cascade={"remove", "persist"})
*/
private $restaurants;
/**
* #var string $company
*
* #ORM\Column(name="company", type="string", length=255)
*/
private $company;
public function __construct()
{
parent::__construct();
$this->restaurants = new \Doctrine\Common\Collections\ArrayCollection();
$this->isValid = false;
}
GETTER and SETTER ...
}
Class Buyer
<?php
namespace Antho\Test\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
/**
* Antho\Test\CoreBundle\Entity\Buyer
*
* #ORM\Table(name="buyer")
* #ORM\Entity(repositoryClass="Antho\Test\CoreBundle\Entity\BuyerRepository")
*/
class Buyer extends User
{
/**
* #var string $address
*
* #ORM\Column(name="address", type="string", length=255)
*/
private $address;
/**
* #var string $city
*
* #ORM\Column(name="city", type="string", length=255)
*/
private $city;
/**
* #var string $zip
*
* #ORM\Column(name="zip", type="string", length=255)
*/
private $zip;
/**
* #var boolean $newsletter
*
* #ORM\Column(name="newsletter", type="boolean")
*/
private $newsletter;
public function __construct()
{
parent::__construct();
if ($this->newsletter === null) {
$this->newsletter = false;
}
}
GETTER and SETTER ...
}
This is an old unanswered question, however people still might face this issue. And this might help and save their time.
The problem is that UniqueEntityValidator by default takes only current (the one which is checking) entity's repository. In other words, if you submit Partner, it checks only Partner entries. It doesn't take into account other entites, such as Buyer or User in your "single_table" inheritance mapping.
To solve your problem, you can just add to your annotation entityClass attribute with your parent class name:
#DoctrineAssert\UniqueEntity(fields="username", message="Ce nom d'utilisateur est déjà utilisé, veuillez en choisir un autre.", groups={"registration", "account"}, entityClass="Antho\Test\CoreBundle\Entity\User")
This part entityClass="Antho\Test\CoreBundle\Entity\User" actually solves your problem.
In this case validator will go through all your user entries (including its child entries too).
My two cents. Not pretend to be the right answer.
Remove all unneeded #Table from the subclasses and make fields visible (protected). I did quite the same (with Symfony 2.0.x) and it works like a charm.
It's slightly different from your code, here a tag (or a keyword) name is unique for each user. But you can test it anyways:
/**
* #ORM\Entity
* #ORM\Table(
* name="meta",
* uniqueConstraints={
* #ORM\UniqueConstraint(columns={"name", "user_id", "type"})
* },
* indexes={
* #ORM\index(columns={"description"}),
* #ORM\index(columns={"type"})
* }
* )
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"tag" = "Tag", "keyword" = "Keyword"})
* #UniqueEntity(fields={"name", "user"})
*/
abstract class Meta
{
protected $name;
protected $user;
}
Child classes:
/**
* #ORM\Entity
*/
class Tag extends Meta { }
/**
* #ORM\Entity
*/
class Keyword extends Meta { }