How can i load an entity from another bundle in an entity? - symfony

Let's say i have 2 entities. Card and User.
User it's in UserBundle and Card is in PublicBundle.
In user i have this function:
#namespace Kanban\UserBundle\Entity;
/**
* Add assignment
*
* #param \Kanban\PublicBundle\Entity\Card $assignment
* #return User
*/
public function addAssignment(\Kanban\PublicBundle\Entity\Card $assignment)
{
$this->assignment[] = $assignment;
return $this;
}
Every time i execute this command:
php app/console doctrine:schema:update --dump-sql
It throws this error:
[Doctrine\ORM\Mapping\MappingException]
The target-entity Kanban\UserBundle\Entity\Card cannot be found in 'Kanban\UserBundle\Entity\User#assignm
ent'.
I've tried the statement:
use Kanban\PublicBundle\Entity;
use Kanban\PublicBundle\Entity\Card;
At the beginning of the file but shows the same error.
Any ideas on what i'm doing wrong?

NM!,
Was a problem with the orm.yml file, changed:
manyToMany:
assignment:
targetEntity: Card
cascade: { }
mappedBy: customer
inversedBy: null
joinTable: null
orderBy: null
into
manyToMany:
assignment:
targetEntity: Kanban\PublicBundle\Entity\Card
cascade: { }
mappedBy: customer
inversedBy: null
joinTable: null
orderBy: null
And that solved the problem!

Related

Doctrine "relation does not exist" error

I have two doctrine entities (Company and Supplier) linked together by a CompanySupplier entity. Entities and yaml resources are as below:
class Company
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
}
class Supplier
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
}
class CompanySupplier
{
/**
* #var integer
*/
private $id;
/**
* #var integer
*/
private $company_id;
/**
* #var integer
*/
private $supplier_id;
}
My resources are as below:
AppBundle\Entity\Company:
type: entity
table: companies
id:
id:
type: integer
fields:
name:
type: string
manyToMany:
Suppliers:
targetEntity: Supplier
joinTable:
name: company_suppliers
joinColumns:
company_id:
referencedColumnName: id
inverseJoinColumns:
supplier_id:
referencedColumnName: id
AppBundle\Entity\Supplier:
type: entity
table: suppliers
id:
id:
type: integer
fields:
name:
type: string
AppBundle\Entity\CompanySupplier:
type: entity
table: company_suppliers
id:
id:
type: integer
fields:
company_id:
type: integer
supplier_id:
type: integer
ManyToMany:
Supplier:
targetEntity: Supplier
joinColumn:
name: id
referencedColumnName: supplier_id
The problem is this seems to cause a “relation company_supplier does not exist” error which I can’t see how to resolve. What do I need to do to set the relations up so that these work?
It works if I don't have the CompanySupplier entity and resource, but as soon as I define those errors start appearing.
I'd appreciate any pointers this is driving me mad.
do change the namespaces and you don't need to write the relational table i think
see here
Company:
type: entity
manyToMany:
supplier:
targetEntity: CompanySupplier
inversedBy: company
joinTable:
name: company_suppliers
joinColumns:
name: id
referencedColumnName: supplier_id
inverseJoinColumns:
supplier_id:
referencedColumnName: id
Supplier:
type: entity
manyToMany:
company:
targetEntity: Company
mappedBy: supplier

Doctrine flush() error: Expected value of type "Doctrine\Common\Collections\Collection|array"

I have a strange problem using a many-to-many relation in Symfony (with Doctrine), I've never had before in symfony projects with many-to-many relations and I can't find any difference to the other projects.
I have the two entitys Product and Tag and a many-to-many relation to each other. Unfortunately, if I try to add a product to a tag or vice versa, the error
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "TestBundle\Entity\Product#$tags", got "TestBundle\Entity\Tag" instead.
appears.
The code used to add a tag to a product:
$tag1 = $em->getRepository('TestBundle:Tag')->findOneBy(array(
'tag' => "Bla"
));
$tag1->addProduct($product);
$em->persist($tag1);
$em->persist($product);
$em->flush();
Of course, the variable $tag1 and $product both contain a valid entity.
The YAML file for the many-to-many relations (I cut away irrelevant parts):
TestBundle\Entity\Tag:
type: entity
table: tags
repositoryClass: TestBundle\Repository\TagRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
tag:
type: string
length: 255
unique: true
manyToMany:
products:
targetEntity: Product
mappedBy: tags
lifecycleCallbacks: { }
Product:
TestBundle\Entity\Product:
type: entity
table: products
repositoryClass: TestBundle\Repository\ProductRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 255
unique: true
manyToOne:
manufacturer:
targetEntity: Manufacturer
inversedBy: products
joinColumn:
name: manufacturer_id
referencedColumnName: id
onDelete: CASCADE
manyToMany:
tags:
targetEntity: Product
inversedBy: products
joinTable:
name: tags2products
joinColumns:
tag_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
lifecycleCallbacks: { }
The setter and getter functions also don't contain any special tricks:
The Tag.php entity file contains:
/**
* Constructor
*/
public function __construct()
{
$this->product = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add product
*
* #param \TestBundle\Entity\Product $product
*
* #return Tag
*/
public function addProduct(\TestBundle\Entity\Product $product)
{
$product->addTag($this);
$this->product[] = $product;
return $this;
}
public function removeProduct(\TestBundle\Entity\Product $product)
{
$this->product->removeElement($product);
}
/**
* Get products
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
While the Product.php contains:
/**
* Add tag
*
* #param \TestBundle\Entity\Tag $tag
*
* #return Product
*/
public function addTag(Tag $tag)
{
$this->tags->add($tag);
//$this->tags[] = $tag;
return $this;
}
/**
* Remove tag
*
* #param \TestBundle\Entity\Tag $webpage
*/
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tag) ;
}
/**
* Get webpages
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
return $this->tags;
}
I also tried to add a $this->tags = new ArrayCollection(); to the constructor of the product, but it didnt change anything.
Also, there is no problem adding, reading and persisting tags to products. The error is thrown as soon as I call $em->flush().
Does anybody know why my Product entity expects a array collection? I never told him to expect one! Thank you very much in advance!
The error is telling you that the property "#tags" of the entity TestBundle\Entity\Product that you are trying to flush, contains an object of type TestBundle\Entity\Tag instead of a collection of this object. Doctrine expects this collection/array because the metadata for that property states that TestBundle\Entity\Product is in a many-yo-many with TestBundle\Entity\Tag and the relation is done via the property "#tags". This should happen if:
//You did this
$this->tags = $tag;
//instead of what you actually did which is correct
$this->tags->add($tag);
//Or
$this->tags[] = $tag;
But the code that you posted here should not produce that exception.
Are you sure there is no other place where an accessor method is called that changes the tags property of TestBundle\Entity\Product? Something like and event listener?
I finally found out what the strange problem was. Thank you Alexandr Cosoi for confirming the way I tried to add my entity.
The Problem was a configuration error I didn't notice.
manyToMany:
tags:
targetEntity: Product
inversedBy: products
joinTable:
name: tags2products
joinColumns:
tag_id:
referencedColumnName: id
inverseJoinColumns:
product_id:
referencedColumnName: id
targetEntity was set to Product but it had to be set to "Tag". Changing it just solved my problem as expected. :)

query entities contained in a composite entity in doctrine2

I have a Friendship class that contains a $user and a $friend. I'd like to get a list of a all friends for a user. I'm unsure on how to create a query builder to do this.
Here's my yml.
Acme\Project\Domain\User\Entity\Friendship:
type: entity
table: friendships
id:
user:
associationKey: true
friend:
associationKey: true
fields:
createdAt:
type: datetimetz
column: created_at
manyToOne:
user:
targetEntity: Acme\Project\Domain\User\Entity\User
joinColumn:
name: user_id
referencedColumnName: id
onDelete: CASCADE
friend:
targetEntity: Acme\Project\Domain\User\Entity\User
joinColumn:
name: friend_id
referencedColumnName: id
onDelete: CASCADE
I've tried this
$qb->select('f.friend')
->from(Friendship::CLASS, 'f')
->where('IDENTITY(f.user) = :user_id')
->setParameter('user_id', $user->getId());
But get the following error.
[Semantical Error] line 0, col 9 near 'friend FROM Acme\\Project\\Domain\\User\\Entity\\Friendship': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
I'm almost certain it's because the select portion contains a ".".
OK you have an error "must be a statefield expression" because as you say there is a dot in your select, you select a member of your root variable 'f'.
But in your case I think your mapping is wrond and that's why you encounter difficulties to write your query.
I think you shouldn't have a Friendship class, and some ManyToOne associations.
But only a ManyToMany association in User class with self-referencing
Here from the official doc :
many-to-many-self-referencing
I quote :
You can even have a self-referencing many-to-many association. A
common scenario is where a User has friends and the target entity of
that relationship is a User so it is self referencing. In this
example it is bidirectional so User has a field named $friendsWithMe
and $myFriends.
You have to translate the following mapping with annotations, to mapping with yml in your case :
<?php
/** #Entity **/
class User
{
// ...
/**
* #ManyToMany(targetEntity="User", mappedBy="myFriends")
**/
private $friendsWithMe;
/**
* #ManyToMany(targetEntity="User", inversedBy="friendsWithMe")
* #JoinTable(name="friends",
* joinColumns={#JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="friend_user_id", referencedColumnName="id")}
* )
**/
private $myFriends;
public function __construct() {
$this->friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection();
$this->myFriends = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
And the query :
$qb->select('u')
->from(User::CLASS, 'u')
->join('u.friendsWithMe', 'friendWithMe')
->where('IDENTITY(friendWithMe) = :user_id')
->setParameter('user_id', $user->getId());

Reflection Exception Property sava\UserBundle\Entity\User Tickets does not exist

for some reason whenever i use php app/console doctrine:schema:update --dump-sql it gives me this error:
[ReflectionException]
Property sava\UserBundle\Entity\User::$Tickets does not exist
usually i first create the orm and then generate with doctrine:generate:entities, my problem is whenever im trying to update the schema, it gives me this error, i have already tried:
clear doctrine cache with php app/console doctrine:cache:clear-query, clear mapping, ect.
manually deleting the cache folder.
deleting ticket entity and generating them again.
setting all the fields to protected.
i ran out of ideas.
error this are my dependencys.
User.Orm:
sava\UserBundle\Entity\User:
type: entity
table: User
fields:
id:
id: true
type: integer
generator:
strategy: AUTO
nombreCliente:
type: string
length: 200
fixed: false
nullable: false
column: nombre_cliente
rifCedula:
type: string
length: 40
fixed: false
nullable: false
column: rif_cedula
telefono:
type: string
length: 30
fixed: false
nullable: true
celular:
type: string
length: 30
fixed: false
nullable: true
direccion:
type: string
length: 250
fixed: false
nullable: true
oneToMany:
Tickets:
targetEntity: sava\SoporteBundle\Entity\TblTicket
mappedBy: idUser
cascade: ["persist", "remove"]
lifecycleCallbacks: { }
Ticket.Orm.
sava\SoporteBundle\Entity\TblTicket:
type: entity
table: tbl_ticket
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
titulo:
type: string
length: '80'
contenido:
type: text
isClosed:
type: boolean
fecha:
type: date
oneToMany:
respuestas:
targetEntity: sava\SoporteBundle\Entity\TblRespuesta
mappedBy: ticket
cascade: ["persist", "remove"]
oneToOne:
idUser:
targetEntity: sava\UserBundle\Entity\User
inversedBy: Tickets
#nullable: true
joinColumn:
name: id_user
referencedColumnName: id
lifecycleCallbacks: { }
Ticket entity(deleted some unrelated fields for clarity):
<?php
namespace sava\SoporteBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TblTicket
*/
class TblTicket
{
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
public function __construct()
{
$this->respuestas = new \Doctrine\Common\Collections\ArrayCollection();
}
protected $idUser;
public function setIdUser(\sava\UserBundle\Entity\User $idUser = null)
{
$this->idUser = $idUser;
return $this;
}
/**
* Get idUser
*
* #return \sava\UserBundle\Entity\User
*/
public function getIdUser()
{
return $this->idUser;
}
}
>
this is my ticket entity extended by fos/user/bundle (some fields where deleted for clarity):
namespace sava\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
/**
* user
*
*/
class User extends BaseUser
{
public function __construct()
{
parent::__construct();
//$this->User = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #var \Doctrine\Common\Collections\Collection
*/
protected $Tickets;
/**
* Add Tickets
*
* #param \sava\SoporteBundle\Entity\TblTicket $tickets
* #return User
*/
public function addTicket(\sava\SoporteBundle\Entity\TblTicket $tickets)
{
$this->Tickets[] = $tickets;
return $this;
}
/**
* Remove Tickets
*
* #param \sava\SoporteBundle\Entity\TblTicket $tickets
*/
public function removeTicket(\sava\SoporteBundle\Entity\TblTicket $tickets)
{
$this->Tickets->removeElement($tickets);
}
/**
* Get Tickets
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTickets()
{
return $this->Tickets;
}
}
nevermind, an old bundle where i was testing the userbundle had an entity that somehow was being targeted by doctrine. deleted the old bundle and its working fine.
if you ever have this problem check your bundles for extra unwanted entities or the namespaces.
You have to update your entity first:
php app/console doctrine:generate:entities [YourBundle:YouEntity]

How to associate the database record with the object

I follow the docs from here http://symfony.com/doc/current/book/doctrine.html
and I have a issue.
I created a relation between the category and the product model. The database has been updated correctly, model classes have right getters and setters, but if I try to run following code:
$product = $this->getDoctrine()->getRepository('AcmeStoreBundle:Product')
->findById(1);
$categoryName = $product->getCategory()->getName();
I gets an error:
FatalErrorException: Error: Call to a member function getName() on a
non-object in
D:\www\Symfony\src\Acme\StoreBundle\Controller\DefaultController.php
line 28
I checked it out and the category model class has getName() method and it is a public method.
My Product.orm.yml looks like
Acme\StoreBundle\Entity\Product:
type: entity
manyToOne:
category:
targetEntity: Category
inversedBy: products
joinColumn:
name: category_id
referencedColumnName: id
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: 255
price:
type: decimal
lifecycleCallbacks: { }
Category.orm.yml
Acme\StoreBundle\Entity\Category:
type: entity
oneToMany:
products:
targetEntity: Product
mappedBy: category
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: '255'
lifecycleCallbacks: { }
Product.php
...
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
...
Category.php
...
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
protected $products;
public function __construct() {
$this->products = new ArrayCollection();
}
...
What's the problem?
You are retrieving a $category instead of a $product in your sample code.
$product = $this->getDoctrine()->getManager()->getRepository('AcmeStoreBundle:Product')->findOneById(1);
$categoryName = $product->getCategory()->getName();
note that you forgot the getManager()
Edit : You need to use findOneById() instead of findById. The first method will return only one single result (your object), the findBy* will return you an array of results on which you can't call getCategory() without traversing it inside a loop.

Resources