Fetching Related Objects exception when work with mutil database - symfony

when i use mutil database with doctrine to related objects ,it can't find the table in the right way.
ta is table name ,in the acc database.
tb is table name too,in the trade database.
ta record:
id name
1 ta名称
tb record:
id name
1 tb名称
$em=$this->getDoctrine()->getRepository(ta::class,'customer');
$ta=$em->find(2);//now ,it can fetch the data,and the data is right
$tb=$ta->getTbTable();
$szName=$tb->getName(); //i want to get the tb record,it will throw an exception :
...................................
'acc.tb' doesn't exist"
actully,tb is in the trade database.
how to fix these problem
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Table(name="ta")
* #ORM\Entity(repositoryClass = "AppBundle\Entity\taRepository")
* #ORM\HasLifecycleCallbacks()
* #package AppBundle\Entity
*/
class ta {
/**
* #ORM\Column(type="integer",unique=true)
* #Assert\NotBlank(message="账号ID不能为空")
* #ORM\Id
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\EntityTrade\tb")
* #ORM\JoinColumn(name="id",referencedColumnName="id")
*/
private $tb_table;
/**
* Set id.
*
* #param int $id
*
* #return ta
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name.
*
* #param string $name
*
* #return ta
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name.
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set tbTable.
*
* #param \AppBundle\EntityTrade\tb|null $tbTable
*
* #return ta
*/
public function setTbTable(\AppBundle\EntityTrade\tb $tbTable = null)
{
$this->tb_table = $tbTable;
return $this;
}
/**
* Get tbTable.
*
* #return \AppBundle\EntityTrade\tb|null
*/
public function getTbTable()
{
return $this->tb_table;
}
}
<?php
namespace AppBundle\EntityTrade;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Table(name="tb")
* #ORM\Entity(repositoryClass = "AppBundle\EntityTrade\tbRepository")
* #ORM\HasLifecycleCallbacks()
* #package AppBundle\EntityTrade
*/
class tb {
/**
* #ORM\Column(type="integer",unique=true)
* #Assert\NotBlank(message="账号ID不能为空")
* #ORM\Id
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* Set id.
*
* #param int $id
*
* #return tb
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name.
*
* #param string $name
*
* #return tb
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name.
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
class defaultController{
public function indexAction(){
$em=$this->getDoctrine()->getRepository(ta::class,'customer');
$ta=$em->find(2);
$tb=$ta->getTbTable();
$szName=$tb->getName();
}
}

It will not work in this way. Doctrine's EntityManager only support management of entities within single database, so your cross-database relation between ta and tb will not be established. Please refer this issue in Doctrine bug tracker for more information.
However your goal can be accomplished into slightly different way. You can't establish cross-database relations between entities, but you can, of course, store ids that refers entities into different databases. Hence you can move all cross-database relations logic into repositories. For example let's assume that you have 2 EntityManager for each database: $accEm for acc database and $tradeEm for trade database. Taking in mind that you're using Symfony - they can be configured into DoctrineBundle configuration and then injected into services.
You will need to create some changes into your code:
ta.php, I've omitted most of code to express changes that needs to be made.
namespace AppBundle\Entity;
class ta
{
/**
* #ORM\Column(type="integer", nullable=true)
* #var int
*/
private $tb_table; // Notice that it is not a reference anymore, but simple integer
/**
* Set tbTable.
*
* #param \AppBundle\EntityTrade\tb|null $tbTable
*
* #return ta
*/
public function setTbTable(\AppBundle\EntityTrade\tb $tbTable = null)
{
// You can also consider updating this method to accept plain integers aswel
$this->tb_table = $tbTable instanceof \AppBundle\EntityTrade\tb ? $tbTable->getId() : null;
return $this;
}
/**
* Get tbTable.
*
* #return int|null
*/
public function getTbTable()
{
// Also notice that plain integer is returned, you may want to rename column and method names to reflect this change of column meaning
return $this->tb_table;
}
}
taRepository.php, I've also omitted most of code that can be there
namespace AppBundle\Entity;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
class taRepository extends EntityRepository {
/**
* #var EntityManager
*/
private $tradeEm;
/**
* #param EntityManager $tradeEm
*/
public function setTradeEntityManader(EntityManager $tradeEm)
{
// It is required to pass instance of EntityManager for "trade" database here. It should be done via Symfony services configuration, please refer Symfony documentation on this topic if needed
$this->tradeEm = $tradeEm;
}
/**
* #param ta $ta
* #return \AppBundle\EntityTrade\tb|null
*/
public function getTbTable(ta $ta) {
// This method should be used instead of $ta::getTbTable()
$tbId = $ta->getTbTable();
if ($tbId === null) {
return null;
}
return $this->tradeEm->find(\AppBundle\EntityTrade\tb::class, $tbId);
}
}
defaultController.php
namespace AppBundle\Controller;
use Doctrine\ORM\EntityManager;
class defaultController
{
/**
* #var EntityManager
*/
private $tradeEm;
/**
* #param EntityManager $tradeEm
*/
public function __construct(EntityManager $tradeEm)
{
// Same as before, this should be instance of EntityManager for "trade" database
$this->tradeEm = $tradeEm;
}
public function indexAction()
{
$em = $this->getDoctrine()->getRepository(ta::class, 'customer');
$ta = $em->find(2);
// Notice that we're not receiving "trade" database entity directly, but using corresponding EntityManager instead
$tb = $this->tradeEm->getTbTable($ta);
if ($tb !== null) {
$szName = $tb->getName();
}
}
}

Related

How do I load related entities on a sub class with Doctrine inheritance mapping?

Doctrine has a couple of great options to provide your application with abstraction and performance features.
Pre-fetching related objects (by joining them)
Inheritance mapping in your entity model
Combining the two seems to be a bit problematic. I'm not even sure if Doctrine is able to handle complexity of this magnitude.
This will be the third area of discussion where my question really lies.
1. Pre-fetching related objects:
If I simply want to fetch all Supplier entities that are related to a RegularProduct, I'd do something like this in my Repository
App\Repository\RegularProductRepository.php:
namespace App\Repository;
use Doctrine\ORM\EntityRepository;
class RegularProductRepository extends EntityRepository
{
/**
* #return array The result
*/
public function findWithSupplier() : array
{
$alias = "rp";
$qb = $this->createQueryBuilder($alias);
$qb->addSelect("s"); // hydrates Supplier entity
$qb->leftJoin($alias . ".supplier", "s");
return $qb->getQuery()->getResult();
}
}
This results in a single query on the database. Whenever I read the suppliers properties in a template it doesn't need to query the database again because the supplier entity is already stored in the ReguralProduct entity.
2. Inheritance mapping in your entity model:
In this example I show you the concept which I have implemented in my project.
App\Entity\AbstractProductBase.php:
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass = "App\Repository\ProductBaseRepository")
* #ORM\Table(name = "s4_product")
* #ORM\MappedSuperclass
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name = "product_type", type = "string")
* #ORM\DiscriminatorMap({"RegularProduct" = "RegularProduct", "AliasedProduct" = "AliasedProduct"})
*/
abstract class AbstractProductBase
{
/**
* ID
*
* #var integer
*
* #ORM\Id
* #ORM\Column(name = "product_id", type = "integer")
* #ORM\GeneratedValue(strategy = "AUTO")
*/
protected $id;
/**
* Name
*
* #var string
*
* #ORM\Column(name = "product_name", type = "string", length = 128)
*/
protected $name;
/**
* Created At
*
* #var \DateTime
*
* #ORM\Column(name = "created_at_date", type = "datetime")
*/
protected $createdAt;
/**
* Constructor
*/
public function __construct()
{
$this->createdAt = new \DateTime();
}
/* ... getters & setters ... */
}
App\Entity\RegularProduct.php:
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\AliasedProduct;
use App\Entity\ProductDevice;
use App\Entity\Supplier;
/**
* #ORM\Entity(repositoryClass = "App\Repository\RegularProductRepository")
*/
class RegularProduct extends AbstractProductBase
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->aliasedProducts = new ArrayCollection();
$this->devices = new ArrayCollection();
}
/**
* Supplier
*
* Many Products have one Supplier
*
* #var Supplier
*
* #ORM\ManyToOne(targetEntity = "Supplier", inversedBy = "products")
* #ORM\JoinColumn(name = "supplier_id", referencedColumnName = "supplier_id")
*/
protected $supplier;
/**
* Aliased Products
*
* One RegularProduct has Many AliasedProducts
*
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity = "AliasedProduct", mappedBy = "regularProduct")
*/
protected $aliasedProducts;
/**
* Devices
*
* Many Products have many Devices (with association class ProductDevice)
*
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity = "ProductDevice", mappedBy = "product", cascade = { "persist", "remove" })
*/
protected $devices;
/**
* Set supplier
*
* #param \App\Entity\Supplier $supplier
* #return RegularProduct
*/
public function setSupplier(Supplier $supplier = null)
{
$this->supplier = $supplier;
return $this;
}
/**
* Get supplier
*
* #return \App\Entity\Supplier
*/
public function getSupplier()
{
return $this->supplier;
}
/**
* Add aliasedProduct
*
* #param \App\Entity\AliasedProduct $aliasedProduct
* #return RegularProduct
*/
public function addAliasedProduct(AliasedProduct $aliasedProduct)
{
$aliasedProduct->setRegularProduct($this);
$this->aliasedProducts[] = $aliasedProduct;
return $this;
}
/**
* Remove aliasedProduct
*
* #param \App\Entity\AliasedProduct $aliasedProduct
*/
public function removeCopy(AliasedProduct $aliasedProduct)
{
$this->aliasedProducts->removeElement($aliasedProduct);
}
/**
* Get aliasedProducts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getAliasedProducts()
{
return $this->aliasedProducts;
}
/**
* Add device
*
* #param \App\Entity\ProductDevice $device
*
* #return Product
*/
public function addDevice(ProductDevice $device)
{
$device->setProduct($this);
$this->devices[] = $device;
return $this;
}
/**
* Remove device
*
* #param \App\Entity\ProductDevice $device
*/
public function removeDevice(ProductDevice $device)
{
$this->devices->removeElement($device);
}
/**
* Get devices
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getDevices()
{
return $this->devices;
}
}
App\Entity\AliasedProduct.php:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\AbstractProductBase;
use App\Entity\RegularProduct;
/**
* Aliased Product Entity
*
* #ORM\Entity()
*/
class AliasedProduct extends AbstractProductBase
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
}
/**
* Regular Product
*
* Many AliasedProducts have one RegularProduct
*
* #var \App\Entity\RegularProduct
*
* #ORM\ManyToOne(targetEntity = "RegularProduct", inversedBy = "aliasedProducts", fetch = "EXTRA_LAZY")
* #ORM\JoinColumn(name = "original_product_id", referencedColumnName = "product_id")
*/
protected $regularProduct;
/**
* Set regularProduct
*
* #var \App\Entity\RegularProduct
*
* #return AliasedProduct
*/
public function setRegularProduct(RegularProduct $regularProduct = null)
{
$this->regularProduct = $regularProduct;
return $this;
}
/**
*
* #return \App\Entity\RegularProduct
*/
public function getRegularProduct()
{
return $this->regularProduct;
}
/**
* Get supplier
*
* #return Supplier
*/
public function getSupplier()
{
return $this->regularProduct->getSupplier();
}
}
3. Hydrating related entities on inherited classes
When I want to achieve this on a class with inheritance mapping it seems that I also need to join the Sub entity RegularProduct
In my result set will be both RegularProduct and AliasedProduct entities.
Executing the query in the Repository below results in a HydrationException with the message: The parent object of entity result with alias 'd' was not found. The parent alias is 'rp'.
App\Repository\ProductBaseRepository.php:
namespace App\Repository;
use Doctrine\ORM\EntityRepository;
use App\Entity\RegularProduct;
abstract class ProductBaseRepository
{
/**
* #return array
*/
public function getAllWithDevices() : array
{
$alias = "pb"; // AbstractProductBase
$qb->leftJoin(
RegularProduct::class,
"rp",
"WITH",
$qb->expr()->eq($alias,"p")
);
$qb->addSelect("d"); // hydrates ProductDevice entity
$qb->leftJoin(
"rp.devices",
"d",
"WITH",
$qb->expr()->eq("rp", "d.product")
);
return $qb->getQuery()->getResult();
}
}
I have tried to alter the query by adding $qb->addSelect("rp"). This solves getting the exception but poses a new problem; the results are not clean.
At this point the resulting array contain all RegularProducts twice, AliasedProducts once, and for each AliasedProduct there is a null variable.
Is it by any means possible to perform a query which only hydrates Devices on RegularProducts without added the $qb->addSelect("rp") line in my code?

Symfony Doctrine return empty values

I use Symfony doctrine to set and get data from my MySQL database. I can push new data without any problem but when I try to get them with a findAll for exemple, I get an array with the good length but nothing in.
Here's my controller:
namespace KGN\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityManagerInterface;
use KGN\CoreBundle\Entity\Appointment;
use KGN\CoreBundle\Entity\Testy;
class AdminController extends Controller
{
public function indexAction()
{
return $this->render('KGNCoreBundle:Admin:index.html.twig');
}
public function aptAction()
{
$rep = $this->getDoctrine()
->getRepository('KGNCoreBundle:Testy');
$testy = $rep->findAll();
// return new Response('This is for show : '. count($testy) );
return new JsonResponse($testy);
}
public function createAction()
{
$em = $this->getDoctrine()->getManager();
$testy = new Testy();
$testy->setTitre('Magnifique');
$testy->setName('Helicoptere');
$em->persist($testy);
$em->flush();
return new Response('This is for create');
}
}
and what I get on my view page
[{},{}]
And it's true that there is 2 elements in my SQL table.
( I have create my entity with php bin/console doctrine:generate:entity without edition stuff in the "Testy" class or rep )
Entity/Testy
namespace KGN\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Testy
*
* #ORM\Table(name="testy")
* #ORM\Entity(repositoryClass="KGN\CoreBundle\Repository\TestyRepository")
*/
class Testy
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titre", type="string", length=255)
*/
private $titre;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set titre
*
* #param string $titre
*
* #return Testy
*/
public function setTitre($titre)
{
$this->titre = $titre;
return $this;
}
/**
* Get titre
*
* #return string
*/
public function getTitre()
{
return $this->titre;
}
/**
* Set name
*
* #param string $name
*
* #return Testy
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
associed rep
namespace KGN\CoreBundle\Repository;
/**
* TestyRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class TestyRepository extends \Doctrine\ORM\EntityRepository
{
}
Hi The Function findAll Return the correct answer but its return as array of Objects
And JsonResponse can't desplay Object.
to fixe that you have to create a custom function in your repository that return An array exemple
public function getAll() {
$qb = $this->createQueryBuilder('u');
return $qb->getQuery()->getArrayResult();
}
$em = $this->getDoctrine()->getManager();
$records = $em->getRepository("KGNCoreBundle:Testy")->findAll();
Hope its help you

Doctrine 2 - ManyToMany relationship - empty collection

I have many to many relationship between user and groups, but when I want to access all groups for user I get empty collection.
namespace LoginBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="User")
*/
class User
{
/**
* #ORM\Column(type="integer", name="id")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $_iId;
/**
* #ORM\Column(type="string", name="login", length=45)
*/
private $_sLogin;
/**
* #ORM\ManyToMany(targetEntity="GroupBundle\Entity\Group", inversedBy="_aUser")
* #ORM\JoinTable(name="Group_x_User",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
private $_aGroup;
public function __construct() {
$this->_aGroup = new ArrayCollection();
}
/**
* Get iId
*
* #return integer
*/
public function getId()
{
return $this->_iId;
}
/**
* Set sLogin
*
* #param string $sLogin
*
* #return User
*/
public function setLogin($sLogin)
{
$this->_sLogin = $sLogin;
return $this;
}
/**
* Get sLogin
*
* #return string
*/
public function getLogin()
{
return $this->_sLogin;
}
public function getGroups()
{
return $this->_aGroup;
}
User and Group use Group_x_User table to store their relationships.
namespace GroupBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="Group")
*/
class Group
{
/**
* #ORM\Column(type="integer", name="id")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $_iId;
/**
* #ORM\Column(type="string", name="name", length=45)
*/
private $_sName;
/**
* #ORM\ManyToMany(targetEntity="LoginBundle\Entity\User", mappedBy="_aGroup")
*/
private $_aUser;
public function __construct() {
$this->_aUser = new ArrayCollection();
}
/**
* Get iId
*
* #return integer
*/
public function getId()
{
return $this->_iId;
}
/**
* Set sName
*
* #param string $sName
*
* #return Group
*/
public function setName($sName)
{
$this->_sName = $sName;
return $this;
}
/**
* Get sName
*
* #return string
*/
public function getName()
{
return $this->_sName;
}
public function getUsers()
{
return $this->_aUser;
}
}
For restoring data from database I use code:
$oUser = $this->getDoctrine()
->getRepository('LoginBundle:User')
->find(2);
$aGroup = $oUser->getGroups();
Unfortunatelly $aGroup collection contains array of 0 elements while in database are records which are matching. What am I missing in my mapping?
There is something missing from your User class. You only declare _aGroup with ArrayCollection. This is not enough. You have to store the data into ArrayCollection.
Add this into User class.
public class addGroups(\GroupBundle\Entity\Group $group)
{
$group->addUsers($this);
$this->_aGroup->add($group);
}
This is for Group class.
public class addUsers(\LoginBundle\Entity\User $user)
{
if (!$this->_aUser->contains($user)) {
$this->_aUser->add($user);
}
}
For more information, you can visit this link.
#ORM\JoinTable() annotation syntax on User::$_aGroup definition is intended to be used for self-referencing relations Doctrine documentation.
Try using simplified syntax :
#JoinTable(name="Group_x_User")
If you use common conventions ('id' as column name for identifiers, and so on) Doctrine and Symfony will do the rest for you.

__toString return name from another entity

Let say I have 2 tables in my database : lesson and group. Group can have 1 lesson per year.
Then I will have 2 entities, lesson entity :
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Lesson
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* Set id
*
* #param integer $id
* #return DftGrupMapel
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
and group entity :
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Group
{
/**
* #var integer
*/
private $id;
/**
* #var \Sifo\AdminBundle\Entity\MstLesson
*/
private $idLesson;
/**
* #var integer
*/
private $year;
/**
* Set id
*
* #param integer $id
* #return DftGrup
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set idLesson
*
* #param \Sifo\AdminBundle\Entity\MstLesson $idLesson
* #return DftGrup
*/
public function setIdLesson(\Sifo\AdminBundle\Entity\MstLesson $idLesson = null)
{
$this->idLesson = $idLesson;
return $this;
}
/**
* Get idGrup
*
* #return \Sifo\AdminBundle\Entity\MstGrup
*/
public function getIdLesson()
{
return $this->idLesson;
}
/**
* Set year
*
* #param integer $year
* #return DftGrup
*/
public function setYear($year)
{
$this->year = $year;
return $this;
}
/**
* Get year
*
* #return integer
*/
public function getYear()
{
return $this->year;
}
The problem is, in group entity I don't have available string to show for __toString(). I fell not good for making new name field in group entity and save lesson name there.
lesson.id and group.idLesson is foreign key.
How I can get name field in lesson entity to show in __toString() group without create new field?
This is an ORM. Your Group class shouldn't really care about what it's associated Lesson's id is... it should just have a reference to the Lesson object itself:
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class Group
{
private $id; // An integer
private $lesson; // A Lesson object
private $year; // An integer, probably
Once $lesson is a Lesson object, you can refer to it in your Group::__toString():
private function __toString() {
return $this->lesson->getName();
}
Here's the documentation on association mapping, which should be helpful in mapping the relationship between Group and Lesson:
http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html
public function setIdLesson(\Sifo\AdminBundle\Entity\MstLesson $idLesson = null)
{
$this->idLesson = $idLesson;
return $this;
}
Here,you don't need the return statement.

Symfony 2 - Retrieve Entity with Json, return another Entity

I have a problem while json_encodeing a Entity.
public function jsonvoteAction($id) {
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('KorumAGBundle:AGVote')->findOneById($id);
$response = new Response(json_encode($entity, 200));
$response->headers->set('Content-Type',' application/json');
return $response;
}
This code returns me a the users entity
{"users":{"__isInitialized__":false,"id":null,"nickname":null,"pwd":null,"email":null,"firstname":null,"lastname":null,"poste":null,"addr1":null,"addr2":null,"pc":null,"country":null,"phone":null,"province":null,"acess":null,"site":null,"crew":null,"utilisateur":null}}
And when I var dymp my $entity, it returns both my AGVote and USers entity.
Here is my AGVote Entity
<?php
namespace Korum\AGBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Korum\AGBundle\Entity\AGVote
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class AGVote
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* #ORM\Column(type="text")
*/
private $question;
/**
* #ORM\Column(type="smallint")
*/
private $actif;
/**
* #ORM\ManyToOne(targetEntity="\Korum\KBundle\Entity\Users", cascade={"all"})
*/
public $users;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set question
* Nb : Only AG admin can set a question
* #param text $question
*/
public function setQuestion($question)
{
$this->question = $question;
}
/**
* Get question
*
* #return text
*/
public function getquestion()
{
return $this->question;
}
/**
* Set actif
*
* #param smallint $actif
*/
public function setActif($actif)
{
$this->actif = $actif;
}
/**
* Get actif
*
* #return smallint
*/
public function getActif()
{
return $this->actif;
}
/**
* Set Users
*
* #param Korum\KBundle\Entity\Province $Users
*/
public function setUsers(\Korum\KBundle\Entity\Users $users)
{
$this->users = $users;
}
/**
* Get Users
*
* #return Korum\KBundle\Entity\Users
*/
public function getUsers()
{
return $this->users;
}
}
Does anyone have an idea of what happened ?
I tried to install the JSMSerializerBundle but event with Metadata library at version 1.1.
When I want to clear my cache, it failed with error :
See :
JMSSerializerBundle Installation : Catchable Fatal Error: Argument 1 passed to JMSSerializerBundle\Twig\SerializerExtension::__construct()
By default, json_encode only uses public properties.
So it serialized the only public property of AGVote: $users. The content of $users was an instance of User; which public fields were serialized.
You could work around these by adding a toArray() method to your entities, and then doing json_encode($entity->toArray()), but i highly recommend you to have a look and use the JMSSerializedBundle.

Resources