Doctrine 2 - ORM ZF2 - orm

I have entity and proper mapping with them. PFB
/**
* User
*
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User{
/**
* #ORM\OneToOne(targetEntity="Language", mappedBy="languageCode2")
**/
private $languageObj;
function __construct(){
$this->languageObj = new ArrayCollection();
}
}
/**
* Language
*
* #ORM\Entity
* #ORM\Table(name="language")
*/
class Language
{
/**
* #ORM\OneToOne(targetEntity="User", inversedBy="languageObj")
* #ORM\JoinColumn(name="language_id", referencedColumnName="language_id")
*/
private $languageCode2;
public function __construct()
{
$this->languageCode2 = new ArrayCollection();
}
}
when I print it It gives below
[languageObj:User:private] => Common\User\Entity\Language Object
(
[languageId:Language:private] => 1
[languageCode:Language:private] => en
[languageName:Language:private] => English
[languageCode2:Language:private] => User Object
what issue I am facing is, i am not able to fetch languageCode from Language object
To do that I have written below in __construct() of User class
$this->lc = $this->languageObj->first();
AND
$this->lc = $this->languageObj->getCode();
getCode() is method in Language class, which return $this->languageCode variable

Related

Symfony 2.8 Entity when access displayAction Route SQLSTATE[42P01]: Undefined table: 7 ERROR: missing FROM-clause entry for table "t10"

hi im trying added customer section when customer can do something like see address list and add/update/delete address. a
so im trying my first step make customer entity like this
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Customer
*
* #ORM\Table(name="customer")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CustomerRepository")
*/
class Customer
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="text")
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="address", type="text")
*/
private $address;
/**
* #ORM\OneToOne(targetEntity="User", inversedBy="customer")
*/
private $user;
/**
* #ORM\OneToOne(targetEntity="Cart", mappedBy="user", cascade={"persist"})
*/
protected $cart;
// public function __construct()
// {
// parent::__construct();
// // your own logic
// }
// other properties and methods
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Customer
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set address
*
* #param string $address
*
* #return Customer
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Set cart
*
* #param \AppBundle\Entity\Cart $cart
* #return User
*/
public function setCart(\AppBundle\Entity\Cart $cart = null)
{
$this->cart = $cart;
return $this;
}
/**
* Get cart
*
* #return \AppBundle\Entity\Cart
*/
public function getCart()
{
return $this->cart;
}
// public function __construct()
// {
// parent::__construct();
// $this->addRole("ROLE_CUSTOMER");
// }
}
and when i access localhost/customer i got error message like this
An exception occurred while executing 'SELECT t0.id AS id_1, t0.name
AS name_2, t0.address AS address_3, t0.user_id AS user_id_4, t5.id AS
id_6, t5.total_price AS total_price_7, t5.quantity AS quantity_8,
t5.user_id AS user_id_9 FROM customer t0 LEFT JOIN cart t5 ON
t5.user_id = t10.id':
SQLSTATE[42P01]: Undefined table: 7 ERROR: missing FROM-clause entry
for table "t10" LINE 1: ..._9 FROM customer t0 LEFT JOIN cart t5 ON
t5.user_id = t10.id ^
ive done open some thread in stackoverflow but many of them still confusing me to get the clear answer how to fix this issue,the topic mostly discuss about postgres not the entity.
and this is my customer controller
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use AppBundle\Entity\User;
use AppBundle\Entity\Customer;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class CustomerController extends Controller
{
/**
* #Route("customer/new", name="new_address")
*/
public function newAction(Request $request)
{
$user = new Customer();
$form = $this->createFormBuilder($user)
->add('name', TextType::class)
->add('address', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$doct = $this->getDoctrine()->getManager();
$doct->persist($user);
$doct->flush();
return $this->redirectToRoute('address_list');
} else {
return $this->render('customer/new.html.twig', array(
'form' => $form->createView(),
));
}
}
/**
* #Route("/customer", name="address_list")
*/
public function displayAction()
{
$user = $this->getDoctrine()
->getRepository('AppBundle:Customer')
->findAll();
return $this->render('customer/display.html.twig', array('data' => $user));
}
/**
* #Route("/customer/update/{id}", name="address_update")
*/
public function updateAction($id, Request $request)
{
$doct = $this->getDoctrine()->getManager();
$user = $doct->getRepository('AppBundle:Customer')->find($id);
if (!$user) {
throw $this->createNotFoundException(
'No customer found for id '.$id
);
}
$form = $this->createFormBuilder($user)
->add('address', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$doct = $this->getDoctrine()->getManager();
$doct->persist($user);
$doct->flush();
return $this->redirectToRoute('address_display');
}
return $this->render('customer/new.html.twig', array(
'form' => $form->createView(),
));
}
/**
* #Route("customer/delete/{id}", name="customer_delete")
*/
public function deleteAction($id) {
$doct = $this->getDoctrine()->getManager();
$user = $doct->getRepository('AppBundle:Customer')->find($id);
if (!$user) {
throw $this->createNotfoundException('No customer found for id ',$id);
}
$doct->remove($user);
$doct->flush();
return $this->redirectToRoute('address_display');
}
}
i expect the output i can access the customer display action router again and show the list all data from customer controller.
i dunno why this can solve this issue,so i try to uncomment this line
public function __construct()
{
parent::__construct();
$this->addRole("ROLE_CUSTOMER");
}
its solved the issue i can open and access the localhost/customer

ApiPlatform: How to update instead of create a child entity that is not a #ApiResource nor a #ApiSubresource

I have a ThirdPartyEntity from a third party bundle that, using a ThirdPartyEntityTrait, I link to MyEntity in my project.
Now, as the ThirdPartyEntity is not set a ApiResource nor as an ApiSubresource and as I don't have any serializaton group set on MyEntity, when I get MyEntity from ApiPlatform, it returns me something like this:
{
"#id":"/api/my_entities/17",
"#type":"MyEntity",
"id":17,
"third_party_entity": {
"id":22,
"a_property":"some value"
}
}
BUT IF I PUT a changed value for a_property with this body:
{
"#id":"/api/my_entities/17",
"#type":"MyEntity",
"id":17,
"third_party_entity": {
"id":22,
"a_property":"some NEW value to update"
}
}
I get a new third_party_entity to be created and get this response:
{
"#id":"/api/my_entities/17",
"#type":"MyEntity",
"id":17,
"third_party_entity": {
"id":23,
"a_property":"some NEW value to update"
}
}
SO, HOW CAN I UPDATE third_party_entity instead of creating it each time?
HERE THERE ARE THE INVOLVED CLASSES AND TRAITS
/**
* #ORM\Table(name="app_my_entities")
* #ORM\Entity()
* #ApiResource()
*/
class MyEntity
{
// !!!!!!!!!!!!!!!!!!
// This is the trait I use to link MyEntity
// with the entity from the third-party bundle
// !!!!!!!!!!!!!!!!!!
use ThirdPartyEntityTrait;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
...
}
And this is the ThirdPartyEntityTrait:
trait ThirdPartyEntityTrait
{
/**
* #ORM\OneToOne(targetEntity="Namespace\To\Bundle\Entity\ThirdPartyEntity", cascade={"all"})
* #ORM\JoinColumn(name="thirdPartyEntity", referencedColumnName="id")
*/
private $thirdPartyEntity;
/**
* #param thirdPartyEntity $thirdPartyEntity
*
* #return ThirdPartyEntity
*/
public function setThirdPartyEntity(thirdPartyEntity $thirdPartyEntity): ThirdPartyEntity
{
$this->thirdPartyEntity = $thirdPartyEntity;
/** #var ThirdPartyEntity $this */
return $this;
}
/**
* #return thirdPartyEntity
*/
public function getThirdPartyEntity(): ?thirdPartyEntity
{
return $this->thirdPartyEntity;
}
/**
* #return thirdPartyEntity
*/
public function removeThirdPartyEntity(): ?thirdPartyEntity
{
$thirdPartyEntity = $this->getThirdPartyEntity();
$this->thirdPartyEntity = null;
return $thirdPartyEntity;
}
}
As you can see, nothing more a property to save the relation and some accessors methods.
This is, instead, the linked Entity:
/**
* #ORM\Entity()
* #ORM\Table(name="third_party_entities")
*/
class ThirdPartyEntity
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\Column(name="aProperty", type="string", nullable=true)
*/
private $aProperty;
public function getId()
{
return $this->id;
}
public function getAProperty()
{
return $this->aProperty;
}
public function setAProperty($aProperty)
{
$this->aProperty = $aProperty;
return $this;
}
}
This question is cross-posted also on GitHub.
The solution was pretty simple: use another config method!
Practically, it is possible to mix configuration types and so, it is possible to use the annotations along with the yaml configuration.
Given this, it is sufficient to create a new config file in config/api_platform/third_party_entity.yaml.
In it put the configuration required to map the entity from the third party bundle:
resources:
App\Entity\MyEntity:
properties:
remote:
subresource:
resourceClass: 'Third\Party\Bundle\TheBundle\Entity\ThirdPartyEntity'
Third\Party\Bundle\TheBundle\Entity\ThirdPartyEntity:
This way it is possible to configure as subresource the entity from the third party bundle to which we don't have access with annotations.

Sylius - Extend Product fixtures from CoreBundle

I've extended the Product model from CoreBundle (v1.0.0-alpha) and I want to change the behavior of the fixtures based on this new model. Keeping in mind that CoreBundle\Fixture\Factory\ProductExampleFactory is final, I am looking for a way to extend the fixtures so I don't have to rewrite the whole class and the whole "default" suite.
AppBundle\Entity\Product
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Sylius\Component\Core\Model\Product as BaseProduct;
/**
* Product
*
* #author leogout
*
* #ORM\Table(name="sylius_product")
* #ORM\Entity
*/
class Product extends BaseProduct
{
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Package", mappedBy="component")
*/
protected $packages;
/**
* #var boolean
*
* #ORM\Column(type="boolean")
*/
protected $exposed;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Customization", mappedBy="product")
* #ORM\JoinColumn(name="customization_id", referencedColumnName="id")
*/
protected $customizations;
/**
* Product constructor.
*/
public function __construct()
{
parent::__construct();
$this->packages = new ArrayCollection();
$this->customizations = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set exposed
*
* #param boolean $exposed
* #return Product
*/
public function setExposed($exposed)
{
$this->exposed = $exposed;
return $this;
}
/**
* Get exposed
*
* #return boolean
*/
public function getExposed()
{
return $this->exposed;
}
/**
* Add packages
*
* #param Package $packages
* #return Product
*/
public function addPackage(Package $packages)
{
$this->packages[] = $packages;
return $this;
}
/**
* Remove packages
*
* #param Package $packages
*/
public function removePackage(Package $packages)
{
$this->packages->removeElement($packages);
}
/**
* Get packages
*
* #return ArrayCollection
*/
public function getPackages()
{
return $this->packages;
}
/**
* Add customizations
*
* #param Customization $customizations
* #return Product
*/
public function addCustomization(Customization $customizations)
{
$this->customizations[] = $customizations;
return $this;
}
/**
* Remove customizations
*
* #param Customization $customizations
*/
public function removeCustomization(Customization $customizations)
{
$this->customizations->removeElement($customizations);
}
/**
* Get customizations
*
* #return ArrayCollection
*/
public function getCustomizations()
{
return $this->customizations;
}
}
Thanks in advance !
EDIT :
After some digging, I saw that I needed to code a whole new fixture with a new ProductFixture, a new ProductExampleFactory and a new MyCustomProductFixture on top of that with their own config files which is not ideal... Do you have a better solution ?

A choice list based on database values in sonata

is it possible to add a choice list in configureformfields with choices values mapped from the database instead of configuring it manually like this :
->add('testfield', 'choice', array('choices' => array(
'1' => 'choice 1',
'2' => 'choice 2',)))
if the entity is correctly mapped then you can just use:
->add('testfield')
and Sonata admin will do the job.
Let's say you have a Product class linked to a Category class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Product
*
* #ORM\Table(name="product")
*
*/
class Product
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
*/
protected $category;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set category
*
* #param Category $category
*
* #return Product
*/
public function setCategory(Category $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return Category
*/
public function getCategory()
{
return $this->category;
}
}
Simply using:
->add('category')
will provide a select form field with all the categories.
You can also use SONATA_TYPE_MODEL if you want something more advanced:
<?php
// src/AppBundle/Admin/ProductAdmin.php
class ProductAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$imageFieldOptions = array(); // see available options below
$formMapper
->add('category', 'sonata_type_model', $imageFieldOptions)
;
}
}
The documentation is on this page: Form Types
Hope this helps!

Symfony2-Doctrine: ManyToMany bi-directionnal relation

I've already search a lot befors asking, even the related topic Symfony2-Doctrine: ManyToMany relation is not saved to database
but still no answer.
I've got this two classes:
class Intervenant extends User
{
/**
* #ManyToMany(targetEntity="iMDEO\DISAASBundle\Entity\Domaine", inversedBy="intervenants", cascade={"persist","merge"})
*/
private $domaines;
/**
* Add domaines
*
* #param Domaine $domaines
*/
public function addDomaine(Domaine $domaines)
{
$this->domaines[] = $domaines;
}
/**
* Get domaines
*
* #return Doctrine\Common\Collections\Collection
*/
public function getDomaines()
{
return $this->domaines;
}
}
class Domaine
{
// ...
/**
* #ORM\ManyToMany(targetEntity="Intervenant", mappedBy="domaines", cascade={"persist","merge"})
*
*/
private $intervenants;
/**
* Add intervenants
*
* #param Intervenant $intervenants
*/
public function addIntervenant(Intervenant $intervenants)
{
$intervenants->addDomaine($this);
$this->intervenants[] = $intervenants;
}
/**
* Get intervenants
*
* #return Doctrine\Common\Collections\Collection
*/
public function getIntervenants()
{
return $this->intervenants;
}
}
When I save an Intervenant, everthing is OK.
But when i save the inverse side Domaine, the changes are not persisted.
Reading Symfony's doc and topics everywhere, I can't find any solution to get a bi-directionnal relation between my two entities.
Here's part of my DomaineController:
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('myBundle:Domaine')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Domaine entity.');
}
$editForm = $this->createForm(new DomaineType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
return $this->indexAction();
}
// ...
My purpose is that when I create/edit an Intervenant, I can choose related Domaine.
And when I create/edit a Domaine, I link every Intervenants in it.
Could you please help me?