I have to rewrite application from zf1 to sf2.
But I need to keep old database schema.
And I have problem with many to many relations.
There are 2 entities: Exceptions, Regions and it was too Exceptionregions, but I deleted it.
There are 3 tables in database - exceptions, regions and exceptionregions, which is hash table.
Below I attach screen with relations:
My code:
1. Exception entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Exceptions
*
* #ORM\Table(name="Exceptions")
* #ORM\Entity
*/
class Exceptions
{
/**
* #var integer
*
* #ORM\Column(name="ExceptionID", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $exceptionid;
/**
* Many exceptions have many regions.
* #ORM\ManyToMany(targetEntity="Regions", inversedBy="exceptions")
* #ORM\JoinTable(name="exceptionregions"),
* joinColumns={#ORM\JoinColumn(name="ExceptionID", referencedColumnName="ExceptionID")},
* inverseJoinColumns={#ORM\JoinColumn(name="RegionID", referencedColumnName="RegionID")}
* )
*/
private $regions;
public function __construct()
{
$this->regions = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add region
*
* #param AppBundle\Entity\Regions $region
*/
public function addRegion(\AppBundle\Entity\Regions $regions)
{
$this->regions[] = $regions;
}
/**
* Get regions
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRegions()
{
return $this->regions;
}
...
}
Region entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Regions
*
* #ORM\Table(name="Regions")
* #ORM\Entity
*/
class Regions
{
/**
* #var string
*
* #ORM\Column(name="RegionName", type="string", length=45, nullable=false)
*/
private $regionname;
/**
* #var integer
*
* #ORM\Column(name="RegionID", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $regionid;
/**
* #ORM\ManyToMany(targetEntity="Exceptions", mappedBy="regions")
*/
private $exceptions;
...
}
And I got this error:
The column id must be mapped to a field in class AppBundle\Entity\Exceptions since it is referenced by a join column of another class.
Of course entity Exceptions is connected with few entities, not only regions.
I got stuck with this issue, I can't resolve this problem and continue my project.
Anybody has any idea how to repair this or any advice? What am I doing wrong?
I'd be grateful for any comment.
I found a solution for this problem.
Maybe someone will benefit from this too.
So, the working code:
/**
* Many exceptions have many regions.
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Regions", inversedBy="exceptions")
* #ORM\JoinTable(name="exceptionregions",
* joinColumns={
* #ORM\JoinColumn(name="ExceptionID", referencedColumnName="ExceptionID")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="RegionID", referencedColumnName="RegionID")
* })
*/
private $regions;
#Alvin, thank you for your commitment.
Have you tried to make the relation bi-directional like so:
class Exceptions{
...
/**
* Many exceptions have many regions.
* #ORM\ManyToMany(targetEntity="Regions", inversedBy="exceptions")
* #ORM\JoinTable(name="regions_exceptions")
*/
private $regions;
class Regions{
...
/**
* #ORM\ManyToMany(targetEntity="Exceptions", mappedBy="regions")
*/
private $exceptions;
Not sure if that will work, but can you try it.
Documentation here:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-bidirectional
** EDIT #2 **
Can you try this change:
class Exceptions
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(name="ExceptionID", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $exceptionid;
Also, if that doesn't work, try:
php bin/console doctrine:schema:update --force
Related
Hie there, after having past many times searching how I should have made an error, I have to ask now the question to the community since it is still a mystery.
I have here two tables : Solution and Project.
A solution can own N projects. A project can also be attached to no solution at all.
Here is part of the Solution.php file
/**
* Description of Solution
*
* #ORM\Entity(repositoryClass="X\Project\Repository\SolutionRepository")
* #ORM\Table(name="solution")
* #ORM\HasLifecycleCallbacks
*
* #author michel.strasser
*/
class Solution
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="bigint")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* [...]
*/
/**
* #var \Doctrine\Common\Collections\ArrayCollection
* #ORM\OneToMany(targetEntity="X\Project\Entity\Project", mappedBy="solution")
*/
private $projects;
/**
* [...]
*/
}
Here is part of the Project.php file :
<?php
namespace X\Project\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use DateTime;
/**
* Description of Project
*
* #ORM\Entity(repositoryClass="X\Project\Repository\ProjectRepository")
* #ORM\Table(name="project")
* #ORM\HasLifecycleCallbacks
*
*/
class Project
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="bigint")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \X\Project\Entity\Solution
* #ORM\ManyToOne(targetEntity="X\Project\Entity\Solution", inversedBy="projects")
* #ORM\JoinColumn(name="solution", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $solution;
}
I've got the following error :
Notice: Undefined index: solution in [...]\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php on line 1768
... when I try to access to $solution->getProjects()->toArray();
Any suggestion ? Please.
Bug found.
In fact there was no bug, I had to :
launch the 3 orm:clear-cache-* doctrine commands
delete the content of data/DoctrineModule/cache
I'm using a third party software which neither using Symfony nor Doctrine nor something else. Only PHP & MySQL.
And now I tried to generate entities from this old MySQL structure and using them into my project.
But I don't understand this double primary key situation.
I should split the parameter in explicit field and bind them separately... But in the doctrine documentation it seems possible, too. So what they want? http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#use-case-2-simple-derived-identity
/** #Id #OneToOne(targetEntity="User") */
This is the error message I get.
[Doctrine\ORM\ORMInvalidArgumentException]
Binding an entity with a composite primary key to a query is not supported.
You should split the parameter into the explicit fields and bind them separately.
And this is my first entity:
src/ShMaBundle/Entity/Passage.php
<?php
// src/ShMaBundle/Entity/Passage.php
namespace ShMaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Passage
*
* #ORM\Table(name="passage", #ORM\Index(name="IDX_98AF07F7EC91F2AA", columns={"DcplID"})})
* #ORM\Entity
*/
class Passage
{
/**
* #var boolean
*
* #ORM\Column(name="PositionsIdx", type="boolean", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $positionsidx;
/**
* #var Discipline
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\OneToOne(targetEntity="Discipline")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="DcplID", referencedColumnName="DcplID")
* })
*/
private $dcplid;
}
And this is my second entity.
src/ShMaBundle/Entity/Discipline.php
<?php
// src/ShMaBundle/Entity/Discipline.php
namespace ShMaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Discipline
*
* #ORM\Table(name="discipline")
* #ORM\Entity
*/
class Discipline
{
/**
* #var integer
*
* #ORM\Column(name="DcplID", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $dcplid;
}
And year I don't know why doctrine can't load the entity and ignoring everything else. I can access the id by $passage->dcplid->dcplid. Or they want that I do it more better. Having something like this.
<?php
// src/ShMaBundle/Entity/Passage.php
namespace ShMaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Passage
*
* #ORM\Table(name="passage", #ORM\Index(name="IDX_98AF07F7EC91F2AA", columns={"DcplID"})})
* #ORM\Entity
*/
class Passage
{
/**
* #var boolean
*
* #ORM\Column(name="PositionsIdx", type="boolean", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $positionsidx;
/**
* #var integer
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $dcplid;
/**
* #var Discipline
*
* #ORM\OneToOne(targetEntity="Discipline")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="DcplID", referencedColumnName="DcplID")
* })
*/
private $dcpl;
}
Then I can access the discipline and the id separately.
But if I test this then I have an empty dcplid. But the $dcpl works and is filled. Hmm...
If it's possible, merge the oneToOne tables into one single table.
You should also use better attribute names like :
/**
* Passage
*
* #ORM\Table(name="passage", #ORM\Index(name="IDX_98AF07F7EC91F2AA", columns={"DcplID"})})
* #ORM\Entity
*/
class Passage
{
/**
* #var boolean
*
* #ORM\Column(name="PositionsIdx", type="boolean", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $positionsidx;
/**
* #var Discipline
*
* #ORM\OneToOne(targetEntity="Discipline")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="DcplID", referencedColumnName="DcplID")
* })
*/
private $discipline;
public function getDiscipline(){
return $this->discipline;
}
}
When do you have this error, on a query ?
Why don't you have any getter and setter methods ?
You should use a getter : $passage->getDiscipline()
Then, you can access the Id of the discipline
EDIT :
In the class Passage :
You have to remove the following :
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
that is over the attribute :
private $dcplid
Doctrine fails with a simple bi-directional many-to-one relationship between FoodDes (many) and FoodGroup (one). Both entities are shown here:
/**
* #ORM\Entity
* #ORM\Table(name="FOOD_DES")
*/
class FoodDes
{
public function __construct()
{
$this->foodGroup = new ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(name="NDB_No", type="string", length=10)
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="FoodGroup", inversedBy="fdGroupCode")
* #ORM\JoinColumn(name="FdGrp_Cd", referencedColumnName="FdGrp_CD")
*/
protected $foodGroup;
}
>
/**
* #ORM\Entity
* #ORM\Table(name="FD_GROUP")
*/
class FoodGroup
{
/**
* #ORM\Id();
* #ORM\GeneratedValue(strategy="NONE");
* #ORM\OneToMany(targetEntity="FoodDes", mappedBy="foodGroup")
*/
protected $fdGroupCode;
When I run doctrine orm:schema-tool:create, it fails with error:
No identifier/primary key specified for Entity
'Acme\Entities\FoodGroup'. Every Entity must have an
identifier/primary key.
However, I labeled $fdGroupCode as my only identifier.
Next approach
I've also tried creating a new primary key $id on the FoodGroup entity and removing the primary key label from $fdGroupCode on FoodGroup. Below is the new FoodGroup entity.
/**
* #ORM\Entity
* #ORM\Table(name="FD_GROUP")
*/
class FoodGroup
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", nullable=false)
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="FoodDes", mappedBy="foodGroup")
*/
protected $fdGroupCode;
When I run doctrine orm:schema-tool:create again, it results with a new error:
[Doctrine\ORM\ORMException]
Column name FdGrp_CD referenced for relation from
Acme\Entities\FoodDes towards Acme\Entities\FoodGroup does not exist.
This error doesn't make any sense. Of course it wouldn't exist. I am running it against an empty database!
These error occur running from the command line, but they also occur when querying the entities against a database. Can somebody please help me?
I'd rather give you working example of OneToMany from one of my projects, so you can see the difference and format code in proper way. If it does not work, then try to get a new Symfony dist and start over.
<?php
// SomeBundle/Entity/Shop/Product.php
namespace SomeBundle\Entity\Shop;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="shop_products")
*/
class Product
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="bigint")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="ProductItem", mappedBy="product")
*/
protected $productItem;
}
Related entity:
<?php
// SomeBundle/Entity/Shop/ProductItem.php
namespace SomeBundle\Entity\Shop;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="shop_products_items")
*/
class ProductItem
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="bigint")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Product", inversedBy="productItem")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
protected $product;
}
For reasons why your code does not work could be many (namespaces, folder structure, column names, etc.). This example works and tested. Give it a try : )
I am trying to implement category and subcategory structure entity, but I end up with this error when generating entity with command php app/console generate:doctrine:entities RFQIronilBundle:
[Doctrine\Common\Annotations\AnnotationException]
[Semantical Error] Couldn't find constant production, class RFQ\IronilBundl
e\Entity\ProductionType.
My created ProductionType entity:
<?php
namespace RFQ\IronilBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ProductionType
*
* #ORM\Table(production-type)
* #ORM\Entity
*/
class ProductionType
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
protected $name;
/**
* #ORM\OneToMany(targetEntity="ProductionType", mappedBy="parent")
**/
protected $children;
/**
* #ORM\ManyToOne(targetEntity="ProductionType", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id")
**/
protected $parent;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
How to generate my entity and what could causes this error?
Thank you!
I think it's because you aren't using speech marks around your table name.
#ORM\Table(production-type) // meant (constant) production minus (constant) type
where as you should use
#ORM\Table("production-type")
And it may make more sense to use production_type to stop the need to quotation marks around the table name in MySQL statements.
I'm making entities with Symfony2 and Doctrine2. I made some entities that represent a many-to-many relation between two of my entities.
An example of one of these entities :
/**
* #ORM\Entity
*/
class Contact_Conference_Invitation
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Contact")
*/
private $contact;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\ConferenceBundle\Entity\Conference")
*/
private $conference;
/**
* #var datetime dateInvitation
*
* #ORM\Column(name="dateInvitation", type="datetime")
*/
private $dateInvitation;
//Getters and setters
}
I have tried updating my sql schema, but the tables corresponding to these entities do not appear. Is there somewhere I have to declare them (config or such)? If not, what's wrong?
Thanks a lot
Edit : I had forgotten the namespace for these class, and that's why they were omitted by Doctrine. Another case closed :) thanks for the answers!
Assumptions ...
No, you don't need to declare them anywhere else than in your Entity directory.
What's the error message you got?
I guess you added
use Doctrine\ORM\Mapping as ORM;
on the top of your classes to let them be mapped.
I tried ...
I tried to generate your entities by adding a simple Contact & Conference entities and it's working fine.
Here are the code snippets:
Contact_Conference_Invitation.php
namespace Ahsio\StackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Contact_Conference_Invitation
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Ahsio\StackBundle\Entity\Contact")
*/
private $contact;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Ahsio\StackBundle\Entity\Conference")
*/
private $conference;
/**
* #var datetime dateInvitation
*
* #ORM\Column(name="dateInvitation", type="datetime")
*/
private $dateInvitation;
//Getters and setters
}
Contact.php
namespace Ahsio\StackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Contact
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
Conference.php
namespace Ahsio\StackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Conference
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #param $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
Here are the generated tables:
NB: I used a specific namespace for the entities generation to work fine, you need to change them.
Also don't forget to check that you have automapping enabled.
In your config.yml you should have
doctrine:
orm:
auto_mapping: true
Came across this question because my entities weren't generated as well, this was my issue, it could save some time to people struggling with the same issue.
I don't see the definition of your ManyToMany relation in the sample of code you provided.
As an example, here's a ManyToMany relationship I implemented for a project
Entity Project.php
/**
* #var Provider[]
*
* #ORM\ManyToMany(targetEntity="Provider", mappedBy="projects")
*/
protected $providers = null;
Entity Provider.php
/**
* #var Project[]
*
* #ORM\ManyToMany(targetEntity="Project", inversedBy="providers")
* #ORM\JoinTable(name="PROVIDER_PROJECT")
*/
protected $projects = null;
As you can see, here you define the join table for your ManyToMany relationship.
Of course those entities are specific for my particular project but you get the idea and you can adapt it easily for your needs.