Symfony2 doctrine ManyToMany associations mapping invalid? - symfony

I have two entities relating to this issue, and I want a join table to be able to cross reference values in each table.
Here is an explanation:
Entity ContainerType.php:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\Containers;
/**
* ContainerType
*
* #ORM\Table(name="container_type")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
*/
class ContainerType
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="type", type="string", length=255)
*/
private $type;
/**
* #var \DateTime
*
* #ORM\Column(name="date_added", type="datetime")
*/
private $dateAdded;
/**
* #var \DateTime
*
* #ORM\Column(name="date_modified", type="datetime", nullable=true)
*/
private $dateModified;
/**
* #ORM\ManyToMany(targetEntity="Containers", inversedBy="type")
* #ORM\JoinTable(name="container_type_containers")
**/
private $container;
public function __construct()
{
$this->container = new ArrayCollection();
}
And entity Containers.php:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\ContainerType;
/**
* Containers
*
* #ORM\Table(name="containers")
* #ORM\Entity
*/
class Containers
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="number", type="string", length=255)
*/
private $number;
/**
* #ORM\ManyToMany(targetEntity="Containers", mappedBy="container")
*/
private $type;
public function __construct()
{
$this->type = new ArrayCollection();
}
And although the schema update works without problems, when I do a doctrine:schema:validate I get the following fail:
[Mapping] FAIL - The entity-class 'AppBundle\Entity\Containers' mapping is invalid:
* The association AppBundle\Entity\Containers#type refers to the owning side field AppBundle\Entity\Containers#container which does not exist.
But the $container field DOES exist in ContainerType so I do not understand why it's trying to reference a field called container in the Containers entity?
Can anyone shed any light on this?
Thank you
Michael

I think this code should works fine for you :)
ContainerType.php
/**
* #ORM\ManyToMany(targetEntity="Containers", inversedBy="containersType")
* #ORM\JoinTable(name="container_type_containers",
* joinColumns={#ORM\JoinColumn(name="container_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="container_type_id", referencedColumnName="id")})
*/
protected $containers;
Containers.php
/**
* #ORM\ManyToMany(targetEntity="ContainerType", mappedBy="containers")
*/
protected $containersType;

I have just realized my error!
I had used the wrong target Entity in the Containers.php file, I should have used ContainerType as the target, instead I had Containers which is why it was trying to find the field in the wrong table!

Related

Error creating relationship with FOSUserBundle and custom entity with easy-extends

I followed this documentation in sonata, step by step and it worked.
Then I added a new entity and tried to generate a relation many to many to user entity, and when I validate it return this error
$ bin/console doctrine:schema:validate
Mapping
-------
[FAIL] The entity-class AppBundle\Entity\Business mapping is invalid:
* The association AppBundle\Entity\Business#user refers to the owning side field Application\Sonata\UserBundle\Entity\User#business which does not exist.
Database
--------
[OK] The database schema is in sync with the mapping files.
This are my two entities
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Business
*
* #ORM\Table(name="business")
* #ORM\Entity(repositoryClass="AppBundle\Repository\BusinessRepository")
*/
class Business
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="BusinessName", type="string", length=255)
*/
private $businessName;
/**
* #var string
*
* #ORM\Column(name="fantasyName", type="string", length=255)
*/
private $fantasyName;
/**
* #var string
*
* #ORM\Column(name="cuit", type="string", length=13)
*/
private $cuit;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\BankAccountType", inversedBy="business")
*/
private $bankAccountType;
/**
* #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;
/**
* #ORM\ManyToMany(targetEntity="\Application\Sonata\UserBundle\Entity\User", mappedBy="business")
*/
private $user;
/**
* #var bool
*
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive = true;
And this
namespace Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* #link https://sonata-project.org/easy-extends
*
* References:
* #link http://www.doctrine-project.org/projects/orm/2.0/docs/reference/working-with-objects/en
*/
class User extends BaseUser
{
/**
* #var int $id
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="\AppBundle\Entity\Business", inversedBy="user")
* #ORM\JoinTable(name="business_user")
*/
private $business;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->business = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id.
*
* #return int $id
*/
public function getId()
{
return $this->id;
}
}
Any idea?
Here is my code for the same thing and it works.
class Role
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="wizai\WMC\UserBundle\Entity\User", mappedBy="customRoles", fetch="EAGER")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
}
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="wizai\WMC\UserBundle\Entity\Role", inversedBy="users", fetch="EAGER")
* #ORM\JoinTable(name="user_role",
* joinColumns={#ORM\JoinColumn(name="user", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role", referencedColumnName="id")}
* )
*/
protected $customRoles;
/**
* User constructor.
*/
public function __construct()
{
$this->customRoles = new ArrayCollection();
}
}
if its still not possible, can you first run a migration or a force update ?
Commands
bin/console doctrine:migrations:diff
bin/console doctrine:migrations:migrate
if not, then try.
bin/console doctrine:schema:update --force --complete

Add ArrayCollection of Entities in the same entity type

Is it possible to keep an array of entities A in the entity A ? How to do this with Doctrine ?
I have :
class A {
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*/
private $sisters;
}
But I don't know what to add to have Doctrine do what I need.
A can have many sisters, and many sisters can be sister of A (Many-To-Many, Self-referencing):
/**
* #ORM\Entity()
* #ORM\Table()
*/
class A
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\A")
*/
private $sisters;
}
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-self-referencing

Symfony 2 doctrine persist doesn't work after updating Relationship Mapping

I updated my entity file to include relationship mapping.
Persist worked before the update now it doesn't.
Maybe it's something I forgot to do.
namespace classes\classBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* advisersplans
*
* #ORM\Table()
* #ORM\Entity
*/
class advisersPlans
{
/**
*
* #ORM\ManyToOne(targetEntity="plans", inversedBy="adviserPlans")
* #ORM\JoinColumn(name="planid", referencedColumnName="id")
*/
public $plan;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* #var integer
*
* #ORM\Column(name="userid", type="integer")
*
*
*/
public $userid;
/**
* #var integer
*
* #ORM\Column(name="adviserid", type="integer")
*
*
*/
public $adviserid;
/**
* #var integer
*
* #ORM\Column(name="planid", type="integer")
*
*
*/
public $planid;
/**
* #var string
*
* #ORM\Column(name="participantLoginWebsiteAddress", type="string", length=255)
*/
public $participantLoginWebsiteAddress;
public function __construct()
{
$class_vars = get_class_vars(get_class($this));
foreach ($class_vars as $key => $value)
{
if ($key != "plan")
$this->$key = "";
}
}
}
Perist returns error saying planid is null. If I remove the following it works.
/**
*
* #ORM\ManyToOne(targetEntity="plans", inversedBy="adviserPlans")
* #ORM\JoinColumn(name="planid", referencedColumnName="id")
*/
Here is my code while persisting.
$adviserPlan = new advisersPlans();
$adviserPlan->planid = $planid;
$adviserPlan->userid = $this->userid();
$adviserPlan->adviserid = $session->get("editadviserid");
$em->persist($adviserPlan);
Am I supposed to populate the plan field and not the planid field or is my entity file coded wrong.
You shouldn't set ids. You should set entities:
$adviserPlan = new advisersPlans();
// You should retrieve the plan before doing this, of course.
$adviserPlan->setPlan($plan);
$plans->addAdviserPlan(§adviserPlan);
$em->persist($adviserPlan);
The methods for adding an entity to a collection should be generated by doctrine when you run:
php app/console doctrine:generate:entities YourBundle

Doctrine2 [Semantical Error] Couldn't find constant?

I have an error when I am trying to run doctrine:generate:entities:
[Doctrine\Common\Annotations\AnnotationException]
[Semantical Error] Couldn't find constant ?, property Smartnode\TalkBundle\Entity\Post::$postowner.
This is my post entity class:
namespace Smartnode\TalkBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Post
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Smartnode\TalkBundle\Entity\PostRepository")
*/
class Post
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity=“Smartnode\userBundle\Entity\User“)
* #JoinColumn(name="postowner_id", referencedColumnName="id")
*/
protected $postowner;
/**
* #var integer
*
* #ORM\ManyTonOne(targetEntity=“Smartnode\TalkBundle\Entity\Chan“)
*/
private $postchan;
/**
* #var \DateTime
*
* #ORM\Column(name="creationdate", type="datetime")
*/
private $creationdate;
And this is my User entity class:
namespace Smartnode\userBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="Smartnode\userBundle\Entity\UserRepository")
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
The probleme Was the quote :/
with the good quote all is working
Thanks All for help
The answer of the question creator is correct. Anyways it is unclear, what he means by the problem was the quote.
Also ' should be used instead of a " to quote the values of the annotation attributes.
The issue for me was, that a quote was missing.
Wrong code:
/**
* #ORM\OneToMany(targetEntity="UnternehmenBrancheZuordnung", mappedBy=_unternehmen")
* #var ArrayCollection $_branchenZuordnungen
*/
private $_branchenZuordnungen;
Right code:
/**
* #ORM\OneToMany(targetEntity="UnternehmenBrancheZuordnung", mappedBy="_unternehmen")
* #var ArrayCollection $_branchenZuordnungen
*/
private $_branchenZuordnungen;
Here the missing quote is highlighted: mappedBy="_unternehmen"

Multiple JoinColumns in Symfony2 using Doctrine annotations?

Here is the problem:
Class Routing with attributes objectId and objectType. objectId is an int, and objectType is a string. The reason for this was to allow the same table to hold data for different kind of routings. For instance for the routing of Products, Department and Brand. So, the combination of the objectType and the objectId is my JoinColumn.
How do I create such a bidirectional relationship with Doctrine2? I looked at inherited relationships, but none of the concepts seemed to be what I'm looking for.
I could create some views in the database and just have a couple of different Routing entities, but this does not seem the best route.
Here are my entities Department, Product and Brand.
../Entity/Department.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\Table(name="departments")
*/
class Department implements DescribableInterface
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", length=11)
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="status", type="string", length=1)
*/
private $status;
/**
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
...
../Entity/Product.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="products")
*/
class Product implements DescribableInterface
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", length=11)
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="status", type="string", length=1)
*/
private $status;
/**
* #ORM\Column(name="product_code", type="string", length=100, nullable=true)
*/
private $productCode = '';
/**
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
...
../Entity/Brand.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="brands")
*/
class Brand
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", length=11)
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="status", type="string", length=1)
*/
private $status = 'a';
/**
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
...
Each product, brand and department has its own URL that is held in the routing table set by the object_type and object_id where the object_type is simply department, product or brand and the object_id is the unique id of the corresponding product, brand or department.
../Entity/Routing.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="routing")
*/
class Routing
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", length=11)
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="object_id", type="integer", length=11)
*/
private $objectId;
/**
* #ORM\Column(name="object_type", type="string", length=100)
*/
private $objectType;
/**
* #ORM\Column(name="url", type="text")
*/
private $url;
...
What I am really struggling with is how do I setup the relationship, so the departments, products and brands can access their URL from the single routing entity.
I have tried adding the relationships to the $objectId, but it doesn't seem to like that. Is it possible to set this up like this?
What I am basically trying to achieve is to get the data object and have the ability to get the URL of an object, for example:
$departments = $em->getRepository("AdamStaceySiteBundle:Department")->findAll();
foreach ($departments as $department)
{
echo ''.$department->getMenuTitle().';
}
Can anyone help?
After further researching I found a man (Dirk Olbertz) in the know who had the same problem.
Information can be found at: Google Groups: Multiple JoinColumns?
I have now implemented this and I will explain how I did it incase it might help anyone else.
The answer to my problem was the use of single table inheritance.
The first thing I needed to do was update the routing entity to use single table inheritance:
../Entity/Routing.php
/**
* #ORM\Entity
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="object_type", type="string")
* #ORM\DiscriminatorMap({"product" = "ProductRouting", "department" = "DepartmentRouting", "brand" = "BrandRouting"})
* #ORM\Table(name="routing")
*/
class Routing
{
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", length=11)
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
...
The DiscriminatorColumn allowed me to specify what column would be used to link, which in this case was the object_type field.
The DiscriminatorMap allowed me to specify what object_type will link with what entities.
These entities then had to be created that extended the Routing entity.
../Entity/ProductRouting.php
/**
* #ORM\Entity
*/
class ProductRouting extends Routing
{
/**
* #ORM\ManyToOne(targetEntity="Product")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id")
*/
protected $product;
...
../Entity/DepartmentRouting.php
/**
* #ORM\Entity
*/
class DepartmentRouting extends Routing
{
/**
* #ORM\ManyToOne(targetEntity="Department")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id")
*/
protected $department;
...
../Entity/BrandRouting.php
/**
* #ORM\Entity
*/
class BrandRouting extends Routing
{
/**
* #ORM\ManyToOne(targetEntity="Brand")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id")
*/
protected $brand;
...
Then in each of the Product, Department and Brand entities I needed to add the new $routings.
../Entity/Product.php
...
class Product
{
...
/**
* #ORM\OneToMany(targetEntity="ProductRouting", mappedBy="product", cascade={"all"})
*/
private $routings;
...
../Entity/Department.php
...
class Department
{
...
/**
* #ORM\OneToMany(targetEntity="DepartmentRouting", mappedBy="department", cascade={"all"})
*/
private $routings;
...
../Entity/Brand.php
...
class Brand
{
...
/**
* #ORM\OneToMany(targetEntity="BrandRouting", mappedBy="brand", cascade={"all"})
*/
private $routings;
...
Hope that helps...

Resources