Doctrine generate Models. Metadata Configuration - codeigniter

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 = '';
}
}

Related

Three level inheritance in doctrine2 not loading second level data

I have a inheritance of three levels using class table inheritance like this:
Class Test
namespace App\Entities\Test;
use Doctrine\ORM\Mapping as ORM;
/**
* Class Test
* #package App\Entities\Test
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"TestA" = "TestA", "TestB" = "TestB"})
* #ORM\Table(name="test")
*/
abstract class Test {
/**
* #var integer
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string
* #ORM\Column(type="string")
*/
protected $columnTest;
}
Class TestM extends Test
namespace App\Entities\Test;
use Doctrine\ORM\Mapping as ORM;
/**
* Class TestM
* #package App\Entities\Test
* #ORM\Entity
*/
abstract class TestM extends Test{
/**
* #var string
* #ORM\Column(type="string")
*/
protected $columnTestM;
}
Class TestA extends TestM
namespace App\Entities\Test;
use Doctrine\ORM\Mapping as ORM;
/**
* Class TestA
* #package App\Entities\Test
* #ORM\Entity
*/
class TestA extends TestM{
/**
* #var string
* #ORM\Column(type="string")
*/
private $columnTestA;
public function __construct(string $columnTest, string $columnTestM, string $columnTestA) {
$this->columnTest = $columnTest;
$this->columnTestM = $columnTestM;
$this->columnTestA = $columnTestA;
}
/**
* #return string
*/
public function getColumnTest(): string {
return $this->columnTest;
}
/**
* #param string $columnTest
*/
public function setColumnTest(string $columnTest): void {
$this->columnTest = $columnTest;
}
/**
* #return string
*/
public function getColumnTestM(): string {
return $this->columnTestM;
}
/**
* #param string $columnTestM
*/
public function setColumnTestM(string $columnTestM): void {
$this->columnTestM = $columnTestM;
}
/**
* #return string
*/
public function getColumnTestA(): string {
return $this->columnTestA;
}
/**
* #param string $columnTestA
*/
public function setColumnTestA(string $columnTestA): void {
$this->columnTestA = $columnTestA;
}
}
I'm having problem because, when I'm going to retrieve the entity from my DB, it comes with the second level with no data, only the first and last levels comes with all the data. Notice that columnTestM is blank. What am I missing? It's persisting with all three levels with data, the problem is only when I have to get it. As an example I put the column's content with it's own name
>>> print_r(\EntityManager::getRepository('App\Entities\Test\Test')->find(1));
App\Entities\Test\TestA Object
(
[columnTestA:App\Entities\Test\TestA:private] => columnTestA
[columnTestM:protected] =>
[id:protected] => 1
[columnTest:protected] => columnTest
)
EDIT:
Maybe it's a bug and I filed an issue at GitHub about a wrong query generation. I put my MariaDB to log all queries to check the query being generated when I try to retrieve the data back and that's the result:
SELECT
t0.id AS id_3,
t0.column_test AS column_test_4,
t0.discr,
t1.column_test_a AS column_test_a_5,
t2.column_test_b AS column_test_b_6
FROM
test t0
LEFT JOIN
test_as t1 ON t0.id = t1.id
LEFT JOIN
test_bs t2 ON t0.id = t2.id
WHERE
t0.id = 1
It tries to left join with TestB instead of doing the join with TestM
As stated by #LBA the problem is two abstract classes in the chain. It should work even with two abstract classes, but only the first is retrieved, but all the others in the middle stays blank. Issue already reported in doctrine's github project.

Error While Creating the schema for doctroin

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;

symfony 2 formbuilder entity error validation

I build a form with
$form = $this->createFormBuilder($user)
->add('locations', 'entity', array('class' =>'PrUserBundle:Location',
'property' => 'name',
'query_builder' => function(\Doctrine\ORM\EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.client_id = :client_id')
->setParameter('client_id', $this->clientId)
->orderBy('u.name', 'ASC');
},'required' => true, 'multiple' => true, 'expanded' => true)
)
After submitting,I would like to validate the form. This is done by a validation.yml
Pr\UserBundle\Entity\User:
properties:
usergroups:
- NotBlank: ~
message: You must select a location
I only get a error
Unable to parse at line 15 (near " message: You must select a location").
EDIT: This has been fixe for removing the ~ tilde like Rooneyl already told me (see comment)
How can I implement the validation of this field inside the form?
EDIT: It's a bit more complicativ I guess.
There are two entities. User and e.g. Location.
The User entity contains
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="integer", nullable=true)
*/
protected $client;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $client_id;
/**
* #ORM\Column(type="string", length=16383, nullable=true) //16383 = max varchar utf8
*/
private $imageurl;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $firstname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $lastname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $emailalert;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $phone;
/**
* #ORM\Column(type="integer", nullable = true)
*/
protected $lock_state;
/**
* #ORM\Column(type="array", nullable=true)
*/
private $locations;
/**
* #ORM\Column(type="array", nullable=true)
*/
private $usergroups;
/**
* #ORM\Column(type="string", length=5, options={"fixed" = true, "default" = "de_DE"})
*/
private $locale = 'de_DE';
/**
* #ORM\Column(type="string", length=32)
*/
private $timezone = 'UTC';
/**
* #ORM\Column(type="array", nullable=true)
*/
private $created='1';
For all those fields, I can get a validation. But for the field "locations" I dont get a validation. This will be data from the entity "Location" like you can see below:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* #ORM\Column(type="string", length=20)
*/
public $name; //Raumbezeichnung, Ausgabelinie-Bezeichnung, Freitextbezeichnung, Standortname
/**
* #ORM\Column(type="integer")
*/
public $type;
/**
* #ORM\Column(type="string", length=20)
*/
public $parentLocation;
/**
* #ORM\Column(type="integer", nullable=true)
*/
public $parentlocation_id;
/**
* #ORM\Column(type="integer", nullable=true)
*/
public $client;
/**
* #ORM\Column(type="integer")
*/
public $client_id;
I dont know if I can display this by a many2many connect in the entity, but actually I used to go the way I discribed above (I'm a noob in symfony until now).
I just want to force admins, to setup usergroups for each user at its beeing created within the form.
This will work:
Pr\UserBundle\Entity\User:
properties:
locations:
- NotBlank:
message: { "You must select a location" }

Symfony2/Doctrine2 One-To-Many same object twice

My current Client-Entity has an unloading and a loading Area, which are both ClientArea-Entities.
namespace ACME\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Sorien\DataGridBundle\Grid\Mapping as GRID;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* ACME\DemoBundle\Entity\Client
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="ACME\DemoBundle\Entity\ClientRepository")
*/
class Client
{
/**
* #ORM\OneToMany(targetEntity="ClientArea",mappedBy="client", cascade={"persist", "remove"})
*/
public $unloading_areas;
/**
* #ORM\OneToMany(targetEntity="ClientArea",mappedBy="client", cascade={"persist", "remove"})
*/
public $loading_areas;
}
class ClientArea
{
/**
* #ORM\ManyToOne(targetEntity="Client")
*/
public $client;
}
This does not work because client can only map 1 association.
How can i map the relation properly?
To create entity relations you need to have keys to use when joining tables. Your Client class should have an id key defined and you need to initialize collections, like this:
class Client
{
//....
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="ClientArea", mappedBy="client", cascade={"persist", "remove"})
*/
public $unloading_areas;
/**
* #ORM\OneToMany(targetEntity="ClientArea", mappedBy="client", cascade={"persist", "remove"})
*/
public $loading_areas;
public function __construct() {
// Initialize collections
$this->unloading_areas = new \Doctrine\Common\Collections\ArrayCollection();
$this->loading_areas = new \Doctrine\Common\Collections\ArrayCollection();
}
// ....
}
Your ClientArea class should then look something like this:
class ClientArea
{
// ....
/**
* #ORM\Column(name="client_id", type="int", nullable=false)
*/
private $clientId;
/**
* #ORM\ManyToOne(targetEntity="Client")
* #JoinColumn(name="client_id", referencedColumnName="id")
*/
public $client;
// ....
}
Now, those two entities should be mapped correctly.
To learn more about association mappings in Doctrine, read article here: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html
Hope this helps.

Symfony2 UniqueEntity validation error with entity inheritance

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 { }

Resources