Get repeated childs in parent collection - doctrine-orm

Well, I have this design on my doctrine 2:
Disc
id, name
Lyric
id, name, artist
list (the join table for many-to-many)
id, disc, lyric
So, when I call $disc->getLyrics() it returns the current lyrics on disc buuut it does not allow to have the same lyric more than once. How can I deal with that?
edit:
at "list table" I can see the lyric stored several times for the same disc
These are my entities
Disc
/**
* #Entity
* #Table(name="disc")
*/
class Disc
{
/**
* #Id #Column(type="integer", nullable=false, name="id_disc")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", nullable=false, name="name")
*/
protected $name;
/**
* #ManyToMany(targetEntity="Lyric")
* #JoinTable(name="playlist",
* joinColumns={#JoinColumn(name="disc", referencedColumnName="id_disc")},
* inverseJoinColumns={#JoinColumn(name="lyric", referencedColumnName="id_lyric")}
* )
*/
protected $lyrics;
public function __construct(){
$this->lyrics = new ArrayCollection();
}
Lyric
/**
* #Entity
* #Table(name="lyric")
*/
class Lyric
{
/**
* #Id #Column(type="integer", nullable=false, name="id_lyric")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", nullable=false, name="name")
*/
protected $name;
/**
* #Column(type="string", nullable=false, name="artist")
*/
protected $artist;
Playlist (joint table many-to-many), this is the table structure:
id_playlist | disc | lyric
1 | 1 | 1
2 | 1 | 1
3 | 1 | 1
The disc 1 have the lyric 1 three times.

Related

Doctrine2, DQL, association not initialized

is here some doctrine expert, who can explain me, why these DQLs will not initialize tallyRevs field on Tally entity? I supposed, that when I fetch TallyRevs (owner side) and fetchJoin Tally entity to them, that field tallyRevs will be initialized. What am I doing wrong? I need to select TallyRev based on some criteria via DQL and since it is a bi-directional association, I would like it to be initialized from the other (Tally.tallyRevs) side also.
Screen of dump
<?php
/**
* #ORM\Entity
* #ORM\Table(name="v3_overview_calloff_tally")
*/
class Tally
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var TallyRev[]|Collection
* #ORM\OneToMany(targetEntity="STI\Model\Entity\V3\Overview\CallOff\TallyRev", mappedBy="tally")
*/
private $tallyRevs;
}
/**
* #ORM\Entity
* #ORM\Table(name="v3_overview_calloff_tallyrev")
*/
class TallyRev
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var int
* #ORM\Column(type="integer", nullable=false)
*/
private $revision;
/**
* #var Tally
* #ORM\ManyToOne(targetEntity="STI\Model\Entity\V3\Overview\CallOff\Tally", inversedBy="tallyRevs")
* #ORM\JoinColumn(name="tally_id", referencedColumnName="id", nullable=false)
*/
private $tally;
}
Here is some repository code:
$qb = $repository->createQueryBuilder();
$qb
->select('tallyRev')
->from(TallyRev::class, 'tallyRev', 'tallyRev.id')
// complicated filtering, this is just an example
->andWhere($qb->expr()->in('tallyRev.revision', ':rev'))
->setParameter('rev', $rev)
;
$tallyRevs = $qb->getQuery()->getResult();
$ids = array_keys($tallyRevs);
$qb2 = $repository->createQueryBuilder();
$qb2
->select('partial tallyRev.{id}')
->from(TallyRev::class, 'tallyRev', 'tallyRev.id')
->andWhere($qb2->expr()->in('tallyRev.id', ':ids'))
->setParameter('ids', $ids)
->leftJoin('tallyRev.tally', 'tally')
->addSelect('tally')
;
$qb2->getQuery()->getResult();
I know, that I can write DQL from the Tally side like this:
$qb
->select('tally')
->from(Tally::class, 'tally', 'tally.id')
->leftJoin('tally.tallyRev', 'tallyRev')
->addSelect('tallyRev')
->andWhere($qb->expr()->in('tallyRev.revision', ':rev'))
->setParameter('rev', $revs)
;
If you want to fetch join tally when you fetch tallyRev you should write something like this in the first qb, and delete qb2
->select(['tallyRev', 'tally'])
->from(TallyRev::class, 'tallyRev', 'tallyRev.id')
->join('tallyRev.tally', 'tally')
// complicated filtering, this is just an example
->andWhere($qb->expr()->in('tallyRev.revision', ':rev'))
->setParameter('rev', $rev)
;

Create an entity that will be used by many other entities (Doctrine 2)

How can I do this?
My Entities:
Product entity
/**
* #ORM\Entity
* #ORM\Table(name="products")
*/
class Product
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $name;
/**
* (??)
* #var ArrayCollection
*/
private $images;
}
Article entity
/**
* #ORM\Entity
* #ORM\Table(name="articles")
*/
class Article
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $title;
/**
* (??)
* #var ArrayCollection
*/
private $images;
}
Image entity
/**
* #ORM\Entity
* #ORM\Table(name="images")
*/
class Image
{
/**
* #ORM\Id()
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
private $id;
/**
* #ORM\Column(type="string", length=512)
* #var string
*/
private $name;
/**
* #ORM\Column(type="string", length=1024)
* #var string
*/
private $path;
}
I don't know how to create a link tables with additional fields like the picture. Which association should I use? How to manage these relations in entities?
Usually when you need a many to many approach Doctrine let you define such behaviour with a simple annotation.
#ORM\ManyToMany(targetEntity="full_qualified_namespace")
#ORM\JoinTable(
name="game_schemas_players",
joinColumns={#ORM\JoinColumn(name="this_field_name", referencedColumnName="id")},
inverseJoinColumns={#ORM\JoinColumn(name="that_field_anem", referencedColumnName="id")}
)
This will instruct Doctrine to create a relation the current entity and the target entity.
But that's not your case. For what I can see from your model you need to add some field on the 'middle' entity.
Here what you may want to do:
class Product
{
[...]
/**
* #var ArrayCollection | ProductImage[]
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="product")
*/
private $productImages;
}
class Image
{
[...]
/**
* #var ArrayCollection | ProductImage[]
*
* #ORM\OneToMany(targetEntity="ProductImage", mappedBy="image")
*/
private $productImages;
}
as you can see as defined here either Product and Image have a oneToMany relation with a middle entity which will be named ProductImage**.
The last step will be to implement such entity:
class ProductImage
{
[...]
/**
* #var Image
*
* #ORM\ManyToOne(targetEntity="Image", mappedBy="image")
* #ORM\JoinColumn(name="image_id", referencedColumnName="id")
*/
private $image;
/**
* #var Product
*
* #ORM\ManyToOne(targetEntity="Product", mappedBy="product")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
private $product;
/**
* #ORM\Column(type="string", length=1024)
* #var string
*/
private $position;
}
The owning side of the relation both for Product and Image is still ProductImage.
As a side note in your entity is common practice to implement an add method in this fashion:
public function __contructor(){
$this->productImages = new ArrayCollection();
}
/**
* Add ProductImage
*
* #param ProductImage $productImage
* #return $this
*/
public function addDocument(ProductImage $productImage)
{
$productImage->addProductImage($productImage);
$this->documents->add($document);
return $this;
}
and then you can use such method with the following approach:
$product = new Product();
$image = new Image();
$productImage = new ProductImage($product,$image);
$product->addProductImage($productImage);
Don't forget to provide the usual setter method as Doctrine need them to initialize the entity.
Hope it helps, Regards.

Data is not inserted to 3rd table in many to many relation in doctrine 2.4 and CodeIgniter 2.2

This question is asked many times on stackoverflow, but none of them helped me.
I have 3 tables:
student
subject
student_subject
Problem: When I try to insert the data, rows are inserted into student and subject tables, but NOT into student_subject table.
Detailes on environment:
CodeIginter 2.2
Doctrine 2.4
Xampp
PHP 5.5.15
Apache 2.4.4
mysql 5.0.11
Windows 8.1 x64 pro
Detailes on database schema: My table structures are:
student_subject table:
mysql> desc student_subject;
+------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| student_id | int(11) | YES | MUL | NULL | |
| subject_id | int(11) | YES | MUL | NULL | |
+------------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
subject table:
mysql> desc student;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| class | char(1) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
subject table:
mysql> desc subject;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| author | varchar(255) | YES | | NULL | |
+--------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
Detailes on PHP (CodeIgniter) code:
C:\xampp\htdocs\test_orm\application\libraries\doctrine.php:
<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\DBAL\Logging\EchoSQLLogger,
Doctrine\ORM\Mapping\Driver\DatabaseDriver,
Doctrine\ORM\Tools\DisconnectedClassMetadataFactory,
Doctrine\ORM\Tools\EntityGenerator;
/**
* CodeIgniter Smarty Class
*
* initializes basic doctrine settings and act as doctrine object
*
* #final Doctrine
* #category Libraries
*/
class Doctrine {
/**
* #var EntityManager $em
*/
public $em = null;
/**
* constructor
*/
public function __construct()
{
// load database configuration from CodeIgniter
require APPPATH.'config/database.php';
// Set up class loading. You could use different autoloaders, provided by your favorite framework,
// if you want to.
require_once APPPATH.'third_party/Doctrine/Common/ClassLoader.php';
$doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'third_party');
$doctrineClassLoader->register();
$entitiesClassLoader = new ClassLoader('models', rtrim(APPPATH, "/" ));
$entitiesClassLoader->register();
$proxiesClassLoader = new ClassLoader('proxies', APPPATH.'models');
$proxiesClassLoader->register();
// Set up caches
$config = new Configuration;
$cache = new ArrayCache;
$config->setMetadataCacheImpl($cache);
$driverImpl = $config->newDefaultAnnotationDriver(array(APPPATH.'models/Entities'));
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl($cache);
// Proxy configuration
$config->setProxyDir(APPPATH.'models/proxies');
$config->setProxyNamespace('Proxies');
// Set up logger
//$logger = new EchoSQLLogger;
//$config->setSQLLogger($logger);
$config->setAutoGenerateProxyClasses( TRUE );
// Database connection information
$connectionOptions = array(
'driver' => 'pdo_mysql',
'user' => $db['default']['username'],
'password' => $db['default']['password'],
'host' => $db['default']['hostname'],
'dbname' => $db['default']['database']
);
// Create EntityManager
$this->em = EntityManager::create($connectionOptions, $config);
$this->em->getConfiguration()
->setMetadataDriverImpl(
new DatabaseDriver(
$this->em->getConnection()->getSchemaManager()
)
);
//$this->generate_classes();
}
/**
* generate entity objects automatically from mysql db tables
* #return none
*/
function generate_classes(){
$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");
}
}
C:\xampp\htdocs\test_orm\application\models\Entities\Subject.php
<?php
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Subject
*
* #ORM\Table(name="subject")
* #ORM\Entity
*/
class Subject
{
public function __construct() {
$this->students = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="author", type="string", length=255, nullable=true)
*/
private $author;
/**
* #ORM\ManyToMany(targetEntity="Student" mappedBy="subjects")
*/
protected $students;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Subject
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set author
*
* #param string $author
* #return Subject
*/
public function setAuthor($author)
{
$this->author = $author;
return $this;
}
/**
* Get author
*
* #return string
*/
public function getAuthor()
{
return $this->author;
}
/**
* Add the Student to Subject
*
* #param Student $student
* #return void
*/
public function addStudent(Student $student){
$student->addSubject($this);
$this->students[] =$student;
}
public function getStudents () {
return $this->students;
}
}
C:\xampp\htdocs\test_orm\application\models\Entities\Student.php
<?php
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Student
*
* #ORM\Table(name="student")
* #ORM\Entity
*/
class Student
{
public function __construct() {
$this->subjects = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="class", type="string", length=1, nullable=true)
*/
private $class;
/**
* #ORM\ManyToMany(targetEntity="Subject", inversedBy="students")
* #ORM\JoinTable(name="student_subject")
*/
protected $subjects;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Student
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set class
*
* #param string $class
* #return Student
*/
public function setClass($class)
{
$this->class = $class;
return $this;
}
/**
* Get class
*
* #return string
*/
public function getClass()
{
return $this->class;
}
/**
* Add the Subject to Student
*
* #param Subject $subject
* #return void
*/
public function addSubject(Subject $subject){
//$subject->addStudent($this);
$this->subjects[] = $subject;
}
public function getSubjects () {
return $this->subjects;
}
}
C:\xampp\htdocs\test_orm\application\models\StudentModel.php
<?php
require_once(APPPATH."models/Entities/Student.php");
require_once(APPPATH."models/Entities/Subject.php");
//use Doctrine\ORM\EntityManager;
use \Student;
use \Subject;
class StudentModel extends CI_Model {
/**
* #var \Doctrine\ORM\EntityManager $em
*/
var $em;
public function __construct() {
parent::__construct();
$this->em = $this->doctrine->em;
}
/**
* Add contact messages to database
* #param array $contact_form
* #return bool
*/
public function addSubject()
{
/**
* #var Student $student
*/
$student = new Student();
$student->setName("Musa Haidari");
$student->setClass("BCS");
$subject = new Subject();
$subject->setName("JAVA");
$subject->setAuthor("XXX");
$this->em->persist($subject);
$subject = new Subject();
$subject->setName("PHP");
$subject->setAuthor("YYY");
$this->em->persist($subject);
$student->addSubject($subject);
$this->em->persist($student);
try {
//save to database
$this->em->flush();
}
catch(Exception $err){
die($err->getMessage());
}
return true;
}
}
C:\xampp\htdocs\test_orm\application\controllers\Landing.php
class Landing extends CI_Controller {
public function index()
{
$this->load->view('welcome_message');
}
public function addStudentSubjectLog () {
$this->load->model('StudentModel');
$this->StudentModel->addSubject();
echo "<br /><br />Done!<br /><br />";
}
}
To insert the data, I enter this URL in the browser:
http://localhost/test_orm/Landing/addStudentSubjectLog
I believe that you should uncomment the line //$subject->addStudent($this); from the addSubject function at your Student entity.
Also, remove the line $student->addSubject($this); from the addStudent function at you Subject entity.
I think you should also persist the $student object before adding the $subject to it. Basically switching these two lines:
$student->addSubject($subject);
$this->em->persist($student);
Hope this helps.

How to set 0 value in table at doctrine 2 to column? It's saving like null

Hi I'm created application with table which is one of column is can't be null.
When I'm persisting value with 0 value. The doctrine is saving it to database as null value.
I'm trying to save column sort_id value in my code.
How to save 0 value as 0 integer value?
Here is my code
namespace cms\models\Entities;
use \cms\Doctrine\ORM\Mapping as ORM;
use \cms\Doctrine;
use \cms\models\Entities;
/**
* #Entity
* #Table(name="vkladki")
*/
class Vkladki{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", length=255)
*/
protected $title;
/**
* #Column(type="integer")
*/
protected $cat_id;
/**
* #var integer
* #Column(type="integer", nullable=false)
*/
protected $sort_id;
public function setSortId( $sort_id){
$this->sort_id = $sort_id;
}

Two one-to-many relationship with reference table (Doctrine 2, ZF2)

I've a problem with my many-to-many relation. I want to have access to the reference table for a querybuilder query. With a many-to-many relation I don't have access to my reference table, so I've set up two one-to-many relationships. My structure look likes:
User ---> UserUserCategory <--- UserCategory
The above structure has two one-to-many relationships and are working fine with the database. When I have a user with the following data in the database (in UserUserCategory):
Table User
ID | Name
1 | Bart
2 | Gerard
Table Category
ID | Name
1 | Officer
2 | Medic
Table UserUserCategory
User | Category
1 | 1
2 | 2
So Bart is an Officer and Gerard is a Medic. But when I want to retrieve the data, it said that Bart is the Medic, and Gerard has a "null" value in the category.
My User-entity:
/**
* Entity Class representing a post of our User module.
*
* #ORM\Entity
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="User\Repository\UserRepository")
*
*/
class User extends zfcUser implements UserInterface
{
/**
* Categories from user
*
* #ORM\OneToMany(targetEntity="User\Entity\UserUserCategory", mappedBy="user_id", cascade={"remove", "persist"})
* #var UserUserCategory
* #access protected
*/
protected $user_usercategories;
//name & user_id comes here
/**
* Constructor to make a new ArrayCollection for addresses
*
*
*/
public function __construct()
{
$this->user_usercategories = new ArrayCollection();
}
/**
* #param Collection $categories
*/
public function addUserUserCategories(Collection $user_usercategories)
{
foreach ($user_usercategories as $user_usercategorie) {
$user_usercategorie->setUser($this);
$this->user_usercategories->add($user_usercategorie);
}
}
/**
* #param Collection $categories
*/
public function removeUserUserCategories(Collection $user_usercategories)
{
foreach ($user_usercategories as $user_usercategorie) {
$user_usercategorie->setUser(null);
$this->user_usercategories->removeElement($user_usercategorie);
}
}
/**
* #return Collection
*/
public function getUserUserCategories()
{
return $this->categories;
}
}
My UserCategory-entity:
/**
* A User category entity.
* #ORM\Entity
* #ORM\Table(uniqueConstraints={#ORM\UniqueConstraint(name="unique_name_parentId", columns={"name", "parent_id"})})
* #ORM\HasLifecycleCallbacks
*/
class UserCategory extends Category
{
/**
* User_usercategories
*
* #ORM\OneToMany(targetEntity="User\Entity\UserUserCategory", mappedBy="category_id")
* #var UserUserCategory
* #access protected
*/
protected $user_usercategories;
/**
* Constructor
*/
public function __construct()
{
$this->user_usercategories = new ArrayCollection();
}
/**
* #param Collection $categories
*/
public function addUserUserCategories(Collection $user_usercategories)
{
foreach ($user_usercategories as $user_usercategorie) {
$user_usercategorie->setCategory($this);
$this->user_usercategories->add($user_usercategorie);
}
}
/**
* #param Collection $categories
*/
public function removeUserUserCategories(Collection $user_usercategories)
{
foreach ($user_usercategories as $user_usercategorie) {
$user_usercategorie->setCategory(null);
$this->user_usercategories->removeElement($user_usercategorie);
}
}
/**
* #return Collection
*/
public function getUserUserCategories()
{
return $this->categories;
}
}
My UserUserCategory-entity:
/**
* Entity Class representing a post of our User_UserCategory entity.
*
* #ORM\Entity
* #ORM\Table(name="user_usercategory")
*
*/
class UserUserCategory
{
/**
* User with a category
*
* #ORM\ManyToOne(targetEntity="User\Entity\User", inversedBy="user_usercategories")
* #ORM\JoinColumn(name="user_id", referencedColumnName="user_id", nullable=false, onDelete="CASCADE")
* #ORM\Id
*
* #var User
* #access protected
*/
protected $user_id;
/**
* Category from user
*
* #ORM\ManyToOne(targetEntity="User\Entity\UserCategory", inversedBy="user_usercategories")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
* #ORM\Id
*
* #var Category
* #access protected
*/
protected $category_id;
public function getUser()
{
return $this->user;
}
/**
* Set User
*
* #param User $user
* #return User
*/
public function setUser(User $user = null)
{
//die('setUser');
$this->user = $user;
return $this;
}
public function getCategory()
{
return $this->category;
}
/**
* Set Category
*
* #param Category $category
* #return Category
*/
public function setCategory(Category $category = null)
{
$this->category = $category;
return $this;
}
}
When I execute the following line, it gives back the wrong result. The wrong category pops up:
\Doctrine\Common\Util\Debug::dump($this->getEntityManager()->find('User\Entity\User', '49')->user_usercategories);
die;
Result:
array(1) {
[0]=>
object(stdClass)#452 (3) {
["__CLASS__"]=>
string(28) "User\Entity\UserUserCategory"
["user_id"]=>
string(16) "User\Entity\User"
["category_id"]=>
string(24) "User\Entity\UserCategory"
}
}
In the category_id is the medic printed, I expect the officer to get back.
In my other user, (id=60) the category_id field is "null". So it look likes Doctrine skips the first input in my UserUserCategory, starts with the second and can't get the last category anymore.
No offence, but I find your code very hard to read. I would suggest you to do few corrections and that might even help you in solving the problem.
1: Naming: Instead of UserCategory, rename it to Category. If your Category will have different types, create new column "type" with values from constansts like
class Category
{
const TYPE_USER = 1 ;
....
2: Instead of addCategories(Collection $array), do singular version like
public function addCategory(Category $category)
{
$reference = new UserCategory() ;
$reference->setUser($this) ;
$reference->setCategory($category) ;
$this->user_categories->add($reference) ;
}
public function removeCategory(Category $category)
{
foreach($this->user_categories as $reference) {
if ( $reference->getCategory() === $category )
$this->user_categories->removeElement($reference) ;
}
}
Symfony2 automaticaly recognizes methods like this. Even if your relation is plural (like categories), s2 will find singularified addCategory and removeCategory methods.
To get array of categories, use this:
public function getCategories()
{
$categories = new ArrayCollection() ;
foreach($this->user_categories as $reference) {
$categories->add( $reference->getCategory() ) ;
}
return $categories ;
}
If you do it like this, you will probably solve the problem you have.