I have a view on nomencladores schema called obtenerPaisesPorFabricanteProductoSolicitud. This is the content for the view:
SELECT
ps.id AS psid,
ps.nombre,
fps.id AS fpsid
FROM
(
(
nomencladores.pais ps
JOIN nomencladores.pais_fabricante_producto_solicitud pfps ON ((pfps.pais_id = ps.id))
)
JOIN negocio.fabricante_producto_solicitud fps ON (
(
pfps.fabricante_producto_solicitud_id = fps.id
)
)
);
I'm trying to map the view as follow:
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="nomencladores.obtenerPaisesPorFabricanteProductoSolicitud", schema="nomencladores")
*/
class ObtenerPaisesPorFabricanteProductoSolicitud
{
/**
* #ORM\Id
* #ORM\Column(name="psid", type="integer", nullable=false, unique=true)
*/
protected $ps;
/**
* #ORM\Column(name="fpsid", type="integer")
*/
protected $fps;
/**
* #ORM\Column(name="nombre", type="string")
*/
protected $nombre;
public function getPs()
{
return $this->ps;
}
public function getFps()
{
return $this->fps;
}
public function getNombre()
{
return $this->nombre;
}
}
But any time I run this code on it:
$ent = $em->getRepository("AppBundle:ObtenerPaisesPorFabricanteProductoSolicitud")->findBy(
array(
"fps" => $entF->getId()
)
);
I got this result:
An exception occurred while executing 'SELECT t0.psid AS psid1,
t0.fpsid AS fpsid2, t0.nombre AS nombre3 FROM
nomencladores.obtenerPaisesPorFabricanteProductoSolicitud t0 WHERE
t0.fpsid = ?' with params [22]:
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "nomencladores.obtenerpaisesporfabricanteproductosolicitud" does not
exist LINE 1: ...d1, t0.fpsid AS fpsid2, t0.nombre AS nombre3 FROM
nomenclado...
If I remove the annotations then the error transform on this:
"Class
"AppBundle\Entity\ObtenerPaisesPorFabricanteProductoSolicitud"
is not a valid entity or mapped super class."
Why Doctrine2 or Symfony tries to execute the query instead go through the view? How I can execute the view from Symfony2/Doctrine2 side?
EDIT
As a side note I'm using PostgreSQL as DB and it haves several squemas, in this case I wrote the view at nomencladores schemas but I tried putting also in public schema and none works, apparently Doctrine doesn't find the view on the schema
Related
Why are Proxy classes created instead of entity objects?
DoctrineORMModule\Proxy\__CG__\App\Entity\FormType vs \App\Entity\FormType
Setup: Laminas, Doctrine ORM
Class Project{}
Class ProjectForm
{
/**
* #ORM\Id
* #ORM\Column(name="id")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\OneToOne(targetEntity="FormType")
* #ORM\JoinColumn(name="form_type_id", referencedColumnName="id")
*/
protected $formType;
/**
* #ORM\OneToOne(targetEntity="Project")
* #ORM\JoinColumn(name="project_id", referencedColumnName="id")
*/
protected $project;
/**
* #ORM\Column(name="label")
*/
protected $label;
/**
* #ORM\Column(name="status")
*/
protected $status;
/**
* #ORM\Column(name="order_nr")
*/
protected $order;
}
Class FormType
{/**
* #ORM\Id
* #ORM\Column(name="id")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(name="code")
*/
protected $code;
/**
* #ORM\Column(name="label_txt")
*/
protected $label;
:
:
}
Then, using a custom extended Repository use the query builder to get data from storage
$qb->select('pc','ft')
->from(\App\Entity\ProjectForm::class,'pc')
->join(\App\Entity\FormType::class,'ft')
->where($qb->expr()->eq('pc.project',$projectId))
->andWhere('pc.formType=ft.id');
SQL Generated is/seems correct (when passing project ID 1) and returns the correct number of rows
SELECT p0_.id AS id_0, p0_.label AS label_1, p0_.status AS status_2, p0_.order_nr AS order_nr_3, f1_.id AS id_4, f1_.code AS code_5, f1_.label_txt AS label_txt_6, p0_.form_type_id AS form_type_id_7, p0_.project_id AS project_id_8 FROM project_forms p0_ INNER JOIN form_types f1_ WHERE p0_.project_id = 1 AND p0_.form_type_id = f1_.id
The same resultset is visible via
$this->getEntityManager()->getRepository(\Eho\Core\Entity\ProjectForm::class)->findBy(['project'=>$projectId],[]);
With $result[0]->getProject()->getTitle() returning the correct string but $result[0]->getFormType()->getName() throwing and error due to class \DoctrineORMModule\Proxy\__CG__\Entity\FormType being returned from getFormType()...???
Project::getTite() -> string
ProjectForm->getName() -> string
EDIT: Also tried different join for giggles
$joinOn = \Doctrine\ORM\Query\Expr\Join::ON;
$joinWith = \Doctrine\ORM\Query\Expr\Join::WITH;
$qb->select('pf','ft')
->from(\App\Entity\ProjectForm::class,'pf')
->innerJoin(\App\Entity\FormType::class,'ft',$joinWith, 'pf.formType=ft.id')
->where($qb->expr()->eq('pf.project',$projectId));
With SQL generated:
SELECT ...fields... FROM project_forms p0_ INNER JOIN form_types f1_ ON (p0_.form_type_id = f1_.id) WHERE p0_.project_id = 1
But the same resultsets (with Proxy classes are returned)...
Why is ONE entity (project) populated correctly and another (formType) as a proxy...?
I'm using Symfony 3.4 with built-in forms in a Bootstrap modal and I've created an inheritance with an abstract parent entity (USER) and two daughter entities (EMPLOYER and SEASONAL where the ID fields are commented out to use that of USER) that's extends USER with the 3 entities of PROTECTED fields.
On my site, from my twig modalForm view, I manage to register in base my different types of users Employer or Seasonal via my SecurityController.
Once the record is done, I redirect to a userAccount twig view whose URL is receiving the data sent by the user's creation: MySeason / {role} / {id} / my-account and the UserAccountController which should recover the data sent previously and display them, that's when I come across the error:
An exception occurred while executing 'SELECT t1.id AS id_2, t1.email AS email_3, t1.password AS password_4, t1.registration AS registration_5, t1.company AS company_6, t1.contact AS contact_7, t1.role AS role_8 FROM employer t1 WHERE t0.id = ?' with params ["1"]:
SQLSTATE[42S22]: Column not found: 1054 Field 't0.id' unknown in where clause
I think in the error, symfony confuses t1.id of the daughter entity and the t0.id of the parent entity.
If anyone has a solution to offer me! ;-)
My parent Entity
...
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="P6\GeneralBundle\Repository\UserRepository")
*/
abstract class User
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255)
*/
protected $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
protected $password;
...
My daughter entity
...
/**
* Employer
*
* #ORM\Table(name="employer")
* #ORM\Entity(repositoryClass="P6\GeneralBundle\Repository\EmployerRepository")
*/
class Employer extends User
{
const ROLE_USER = 'EMPLOYER';
// /**
// * #var int
// *
// * #ORM\Column(name="id", type="integer")
// * #ORM\Id
// * #ORM\GeneratedValue(strategy="AUTO")
// */
// protected $id;
/**
* #var string
*
* #ORM\Column(name="company", type="string", length=255)
*/
protected $company;
/**
* #var string
*
* #ORM\Column(name="contact", type="string", length=255)
*/
protected $contact;
...
My SecurityController
<?php
namespace P6\GeneralBundle\Controller;
use P6\GeneralBundle\Entity\Seasonal;
use P6\GeneralBundle\Form\SeasonalType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use P6\GeneralBundle\Entity\Employer;
use P6\GeneralBundle\Form\EmployerType;
class SecurityController extends Controller
{
public function userRegistrationAction (Request $request)
{
// Employer Form
$employer = new Employer();
if ($formEmployer = $this->createForm(EmployerType::class, $employer, array('action' => $this->generateUrl('registerUser')
))) {
$formEmployer->handleRequest($request);
if ($formEmployer->isSubmitted() && $formEmployer->isValid()) {
/** #var Employer $employer */
$employer = $formEmployer->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($employer);
$em->flush();
$this->addFlash('registration', 'Votre profil a bien été enregistré !');
return $this->redirectToRoute('user_account', [
'role' => $employer->getRole(),
'id' => $employer->getId(),
]);
}
}
// Seasonal Form
$seasonal = new Seasonal();
if ($formSeasonal = $this->createForm(SeasonalType::class, $seasonal, array('action' => $this->generateUrl('registerUser')
))) {
$formSeasonal->handleRequest($request);
if ($formSeasonal->isSubmitted() && $formSeasonal->isValid()) {
/** #var Seasonal $seasonal */
$seasonal = $formSeasonal->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($seasonal);
$em->flush();
$this->addFlash('registration', 'Votre profil a bien été enregistré !');
return $this->redirectToRoute('user_account', [
'role' => $seasonal->getRole(),
'id' => $seasonal->getId(),
]);
}
}
// Renvoi de vue si les formulaires ne sont pas valides
return $this->render('#General/Default/modalForm.html.twig', [
'formEmployer' => $formEmployer->createView(),
'formSeasonal' => $formSeasonal->createView(),
]);
}
}
My UserAccountController
<?php
namespace P6\GeneralBundle\Controller;
use P6\GeneralBundle\Entity\Employer;
use P6\GeneralBundle\Entity\Seasonal;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UserAccountController extends Controller
{
public function userAccountAction(Employer $employer, Seasonal $seasonal)
{
$repository = $this->getDoctrine()->getRepository('GeneralBundle:Employer');
$employer = $repository->findBy(['employer' => $employer->getId()]);
// if ($repository = $this->getDoctrine()->getRepository('GeneralBundle:Seasonal')) {
// $seasonal = $repository->findBy(['seasonal' => $seasonal->getId()]);
// }
return $this->render('#General/Default/userAccount.html.twig', [
'employer' => $employer,
//'seasonal' => $seasonal,
]);
}
}
I already tried 3 ways to extends a class(Mapped superclass, single table and class table) but that does not solve my problem.
I expect to be able to recover the data saved in the database and display it in a twig view.
I found a solution through this link (Symfony2-Doctrine2 inheritance persist not working properly), I can finally recover the data sent during registration from the User to the next view, the User's account!
In fact, I had to add this piece of code in the parameters of my mother class:
* #ORM \ InheritanceType ("JOINED")
* #ORM \ DiscriminatorColumn (name = "discr", type = "string")
* #ORM \ DiscriminatorMap ({"employer" = "Employer", "seasonal" = "Seasonal"})
But also modify the getters Id of my daughter entities by replacing:
public function getId (){return $ this-> id;}
by:
public function getId (){return parent :: getId ();}
And finally, I replaced in my UserAccountController:
$ repository = $ this-> getDoctrine () -> getRepository ('GeneralBundle: Employer');
$ employer = $ repository-> findBy (['employer' => $ employer-> getId ()]);
by:
$ repository = $ this-> getDoctrine () -> getRepository ('GeneralBundle: Employer');
$ employer = $ repository-> findOneBy (['id' => $ employer-> getId ()]);
Hoping that this solution does not block me for the rest;)
Many users can have many items. But I want to get a list of specific items owned by specifics users.
I have two entities :
User Entity :
class User
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* Many Users have many items
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Item", fetch="EAGER")
* #ORM\JoinTable(name="users_items",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="item_id", referencedColumnName="id")}
* )
*/
private $items;
}
Item Entity :
class Item
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=10)
*/
private $name;
}
Doctrine then created three tables :
items
users
users_items
I want to get all the items named "Pencil" owned by userId 11.
How can I achieve that ?
Thank you.
I hope that you realize that you are using an UNIdirectional many-to-many relation between User and Item. User 'knows' what items belong to him but Item does not know which users use this item. Therefore you can retrieve a single User from the database (by user-id) with a collection of items that are filtered by name. If the user-id does not exist or the user has no items that match the filter, then $user will be NULL. instead of the exception in the controller in my example you could use a if-else statement in twig to verify if user is null or not.
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
/**
* #Route("/someroute", name="some_route")
*/
public function someAction()
{
$em = $this->getDoctrine()->getManager();
// for this example two hardcoded parameters. $user might be NULL !
$user = $em->getRepository('AppBundle:User')->getItemsWithNameForUser(1, 'Pencil');
if(null === $user)
{
throw $this->createNotFoundException('This user does not have the selected items or the user does not exist');
}
return $this->render('default/index.html.twig', [
'user' => $user
]);
}
}
and the UserRepository:
namespace AppBundle\Repository;
class UserRepository extends \Doctrine\ORM\EntityRepository
{
public function getItemsWithNameForUser($userId, $itemName)
{
return $this->getEntityManager()->createQuery(
'SELECT u,i FROM AppBundle:User u JOIN u.items i WHERE u.id=:id AND i.name=:name'
) ->setParameter('id', $userId)
->setParameter('name', $itemName)
->getOneOrNullResult();
}
}
I think it should be something like:
$items= $em->getDoctrine->createQueryBuilder()
->select('[items]')
->from(User::class, 'users')
->join('users.items', 'items')
->where('users.id = :userId')
->setParameter('userId', $theId)
->getQuery()
->getResult();
I am not sure this works (syntax is maybe not perfect), but theoretically it should, the problem in your case is that the owning side only knows about the relation and you want to query from the other side.
I have 2 tables called Advert and User. The User Id gets written into the Advert Table. I have now created a third table called Bookmark. The table got 2 columns, advert_id and user_id. When I see an Advert I like, I can add a Bookmark to be able to find it easier in my Private Section. When I am in my Private Section to see my Bookmarks, I want to see the Advert Details straight away, so in my Repository I want to create a Join to read the information from the Advert Table. I thought this will be a OneToOne Relationship. I also have to make sure that if the Advert gets deleted, then all the Bookmarks need to be deleted, so I thought its a Bi-directional relationship. So I have below:
Entity/Bookmark.php
/**
* Bookmark
*
* #ORM\Table(name="bookmark")
* #ORM\Entity(repositoryClass="Advert\Repository\BookmarkRepository")
*/
class Bookmark
{
/**
* #var integer
* #ORM\Id
* #ORM\Column(name="advert_id", type="integer", nullable=false)
* #ORM\OneToOne(targetEntity="Advert", mappedBy="bookmark")
* #ORM\JoinColumn(name="advert_id", referencedColumnName="id")
*/
private $advertId;
/**
* #var integer
* #ORM\Id
* #ORM\Column(name="user_id", type="integer", nullable=false)
* #ORM\OneToOne(targetEntity="User")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $userId;
public function setAdvertId($advertId)
{
$this->advertId = $advertId;
return $this;
}
public function getAdvertId()
{
return $this->advertId;
}
public function setUserId($userId)
{
$this->userId = $userId;
return $this;
}
public function getUserId()
{
return $this->userId;
}
Entity\Advert.php
/** Advert
*
* #ORM\Table(name="advert")
* #ORM\Entity(repositoryClass="Advert\Repository\AdvertRepository")
*/
class Advert
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Bookmark", inversedBy="advert")
* #ORM\JoinColumn(name="id", referencedColumnName="advert_id")
**/
private $bookmark;
public function setBookmark($bookmark)
{
$this->bookmark = $bookmark;
return $this;
}
public function getBookmark()
{
return $this->bookmark;
}
public function addBookmark($bookmark)
{
$this->bookmark->add($bookmark);
}
public function removeBookmark($bookmark)
{
$this->bookmark->removeElement($bookmark);
}
Advert\Repository\Advert\Repository.php
class BookmarkRepository extends EntityRepository
{
public function getBookmarksByUserIds($userId)
{
$query =$this->_em->getRepository($this->getEntityName())->createQueryBuilder('b')
->join('b.advertId', 'a')
->andWhere('a.userId=:userid')
->setParameter('userid',$userId)
;
return $query->getQuery()->getResult();
}
What do I do wrong or where is my missunderstanding? I get the Error Message:
Advert\Entity\Bookmark has no association named advertId
As I said, the table Bookmark gets only filled, when I click on "Add Advert to Bookmarks". I need a Join to be able to display the Advert Details when I click on "Show my Bookmarks" and if an Advert or a User gets deleted, all Bookmarks need to be removed from the Bookmark table. Is this a OneToOne Bi-directional relationship and what is wrong?
UPDATE 1 BELOW NOT WORKING
I have updated the 2 Files below, but I do not get any Bookmarks shown. Instead I should see a list of Bookmarked adverts plus the advert details. I have not even tried yet to get my Service to "Bookmark Advert" or the method to check if an Advert is bookmarked working again. I got it working before, but I guess I am just really confused now.
AdvertController.php
public function watchlistAction()
{
$user_id = $this->zfcUserAuthentication()->getIdentity()->getId();
$adverts = $this->getEntityManager()->getRepository('Advert\Entity\User')->findBookmarksByUserId($user_id);
return new ViewModel(array(
'adverts' => $adverts,
));
}
Repository\UserRepository.php
class UserRepository extends EntityRepository
{
public function findBookmarksByUserId($userId)
{
$query =$this->_em->getRepository($this->getEntityName())->createQueryBuilder('b')
->join('b.bookmarks', 'a')
->join('b.adverts', 'c')
->andWhere('a.user=:userid')
->setParameter('userid',$userId)
;
return $query->getQuery()->getResult();
}
UPDATE 2 BELOW WORKING
You were right, I don't need the UserRepository Query see the List of Bookmarked Adverts. I just had to change the
AdvertController.php
public function watchlistAction()
{
$user_id = $this->zfcUserAuthentication()->getIdentity()->getId();
// get User by reference (no queries executed)
$user = $this->getEntityManager()->getReference('Advert\Entity\User' , $user_id);
$adverts = $user->getBookmarks();
return new ViewModel(array(
'adverts' => $adverts,
));
}
Good news also, in the moment I delete an Advert, the Bookmark gets automatically removed in the Bookmark Database table. Now I only have to find out how to add the Bookmark, so I will have to change my Service. As soon I get this working I will update this post for others to see.
UPDATE 3 BELOW NOT WORKING
Unfortunately I do not get the below 3 Methods in my Service working. I obviously have to now pick 1 record, to either check the Status (Bookmarked already or not), remove the Bookmark (defined by advertId) or add a Bookmark (defined by advertId)
public function checkAdvertBookmarkStatus($advertId)
{
$userId = $this->getUserEntity()->getId();
// get User by reference (no queries executed)
$user = $this->getEntityManager()->getReference('Advert\Entity\User' , $userId);
$bookmarkStatus = $this->getEntityManager()->getRepository('Advert\Entity\User')
->findOneBy(array('advert' => $advertId, 'userId' => $userId));
return $bookmarkStatus;
}
public function saveAdvertBookmark($advertId)
{
$bookmark = new UserEntity();
$userId = $this->getUserEntity()->getId();
// $bookmark->addBookmark($advertId);
$bookmark->setAdvertId($advertId);
$bookmark->setUserId($userId);
# write new bookmmark to database tbl bookmark
$this->getEntityManager()->persist($bookmark);
$this->getEntityManager()->flush();
}
public function removeAdvertBookmark($advertId)
{
$bookmark = new UserEntity();
$userId = $this->getUserEntity()->getId();
$bookmark = $this->getEntityManager()->getRepository('Advert\Entity\Bookmark')
->findOneBy(array('advertId' => $advertId, 'userId' => $userId));
# remove bookmmark from tbl bookmark
$this->getEntityManager()->remove($bookmark);
$this->getEntityManager()->flush();
}
I suppose the answer is in the Tutorial, which I keep reading, but I do not understand it fully. I was able to add Bookmarks before, when I was using the BookmarkEntity, but I have no idea how to do it via the UserEntity
A OneToOne relationship would be the wrong choice here, this would mean that a user can bookmark only one advert and that an advert can only be bookmarked by one user. Because a user should be able to bookmark many adverts and an advert should be bookmarked by many users, you need a ManyToMany relationship.
You idea to create a mapping table bookmarks is not wrong if you work with a database. However, you don't need to create it as an entity in Doctrine. You can simply add Adverts in an association called bookmarks in User to display the bookmarked Adverts and vice versa:
User Entity:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Application\Entity\Advert", inversedBy="bookmarks", cascade={"persist"})
* #ORM\JoinTable(name="bookmarks",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="advert_id", referencedColumnName="id")}
* )
*/
private $bookmarks;
Advert Entity
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Application\Entity\User", mappedBy="bookmarks", cascade={"persist"})
* #ORM\JoinTable(name="bookmarks",
* joinColumns={#ORM\JoinColumn(name="advert_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
private $bookmarks;
You might want to read this article, too:
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html
Edit: How to add and remove bookmarks
Associations in Doctrine are something entirely different from fields, although both are properties in your Entity. To handle bookmarks you add or remove the Advert Entity in your User Entity directly. For example:
$bookmarks = $user->getBookmarks();
$bookmarks[] = $advert;
This would add a bookmark to the user and will be stored as soon as you persist and flush. To make this even easier, you can define remover and adder:
Use statements:
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
and the code:
/**
* #param Collection $bookmarks
*/
public function addBookmarks(Collection $bookmarks)
{
foreach ($bookmarks as $bookmark) {
$this->bookmarks->add($bookmark);
}
}
/**
* #param Collection $bookmarks
*/
public function removeBookmarks(Collection $bookmarks)
{
foreach ($bookmarks as $bookmark) {
$this->bookmarks->removeElement($bookmark);
}
}
You can now remove and add adverts given in collection like this:
$user->addBookmarks(new ArrayCollection(array($advert)));
It is always recommended to define adder and remover in toMany relationships, because many Doctrine components will need them, for example the very useful DoctrineObject, a hydrator used by DoctrineModule for Zend 2
I'm working on a form with 3 entities :
order (idorder)
support reference table (idsupport)
link table (idorder, idsupport)
And when i try to select one or more support i got this error:
Catchable Fatal Error: Argument 1 passed to Myapp\MyBundle\Entity\PcastCmdsupports::setIdsupports() must be an instance of Myapp\MyBundle\Entity\PcastSupports, instance of Doctrine\Common\Collections\ArrayCollection given,
called in C:\wamp\www\php\Symfony\vendor\symfony\src\Symfony\Component\Form\Util\PropertyPath.php on line 347 and defined in C:\wamp\www\php\Symfony\src\Myapp\MyBundle\Entity\PcastCmdsupports.php line 62
Since i already created my link table i saw on the web that i can simply create 2 Many-To-One relation in my link table :
/**
* #var PcastSupports
*
* #ORM\ManyToOne(targetEntity="PcastSupports")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="IDSUPPORTS", referencedColumnName="IDSUPPORTS")
* })
*/
private $idsupports;
/**
* #var PcastOrder
*
* #ORM\ManyToOne(targetEntity="PcastOrder")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="IDORDER", referencedColumnName="IDORDER")
* })
*/
private $idorder;
and my setters and getters :
/**
* Set idsupports
*
*/
public function setIdsupports(\Myapp\MyBundle\Entity\PcastSupports $idsupports)
{
$this->idsupports = $idsupports;
}
/**
* Get idsupports
*
*/
public function getIdsupports()
{
return $this->idsupports;
}
/**
* Set idorder
*
*/
public function setIdcommande(\Myapp\MyBundle\Entity\PcastOrder $idorder)
{
$this->idorder = $idorder;
}
/**
* Get idorder
*
*/
public function getIdorder()
{
return $this->idorder;
}
In my order form i can choose one or many supports so i created my form like this:
$form_clips = $this->createFormBuilder($cmdclips)
->add('idorder', new CmdsupportsType)
->getForm();
And finally my supportsType form:
$builder
->add('idsupports', 'entity', array(
'class' => 'MyappMyBundle:PcastSupports',
'property' => 'name',
'expanded' => true,
'multiple' => true,
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('pts')
->orderBy('pts.idsupports','ASC');
},
));
I'm not using any arraycollection so i don't understand the issue. And the issue happened during this action:
$form_clips->bindRequest($request);
Thank a lot for your help !
I tried to make it work with the many-to-many relation in a simple case (user, company and a user_company entities) but i got a problem when i try to add a company to a user:
Warning: oci_bind_by_name() [<a href='function.oci-bind-by-name'>function.oci-bind-by-name</a>]: Invalid variable used for bind in C:\wamp\www\php\Promocast\Symfony\vendor\doctrine-dbal\lib\Doctrine\DBAL\Driver\OCI8\OCI8Statement.php line 113
I googling a lot but i didn't find anything on this error... According to stack trace the error is when doctrine try to add the company object :
array('column' => ':param10', 'variable' => object(PcastCompany), 'type' => '1')
My user entity (societe = company):
/**
* #ORM\ManyToMany(targetEntity="PcastSociete", inversedBy="users")
* #ORM\JoinTable(name="PcastLienusersociete",
* joinColumns={#ORM\JoinColumn(name="ImUser_iduser", referencedColumnName="iduser")},
* inverseJoinColumns={#ORM\JoinColumn(name="PcastLienusersociete_idsociete", referencedColumnName="idsociete")}
* )
*/
private $societes;
public function getSocietes()
{
return $this->societes;
}
public function addSociete(\Myapp\MyBundle\Entity\PcastSociete $societe)
{
$this->societes[] = $societe;
}
My company entity:
/**
* #ORM\ManyToMany(targetEntity="ImUser", mappedBy="societes")
*/
private $users;
public function __construct() {
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
}
If anybody have any idea...
Thanks
You should not have an entity representing the link table. If you annotate both your entities correctly, Doctrine will handle the creation of the link table by itself.
Moreover, you do not need any link table to do a Many-to-One relationship in the first place, what you want to do is use the Many-to-Many annotations in both entities.
http://readthedocs.org/docs/doctrine-orm/en/latest/reference/association-mapping.html?highlight=many%20to%20one#many-to-many-bidirectional
Start with the basics. I was curious about something else concerning ManyToMany so I grabbed your entities as a test case. Before diving into forms and such, make sure you can execute a simple test case from the command line such as:
use Zayso\ArbiterBundle\Entity\PcastSociete as Company;
use Zayso\ArbiterBundle\Entity\ImUser as User;
protected function test1()
{
$em = $this->getContainer()->get('doctrine.orm.entity_manager');
$company = new Company();
$em->persist($company);
$user = new User();
$user->addSociete($company);
$em->persist($user);
$em->flush();
}
For entities I used:
namespace Zayso\ArbiterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class ImUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer",name="iduser")
* #ORM\GeneratedValue
*/
protected $id;
public function getId() { return $this->id; }
/**
* #ORM\ManyToMany(targetEntity="PcastSociete", inversedBy="users")
* #ORM\JoinTable(name="PcastLienusersociete",
* joinColumns={#ORM\JoinColumn(name="ImUser_iduser", referencedColumnName="iduser")},
* inverseJoinColumns={#ORM\JoinColumn(name="PcastLienusersociete_idsociete", referencedColumnName="idsociete")}
* )
*/
private $societes;
public function getSocietes()
{
return $this->societes;
}
public function addSociete(PcastSociete $societe)
{
$this->societes[] = $societe;
}
public function __construct()
{
$this->societes = new ArrayCollection();
}
}
namespace Zayso\ArbiterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class PcastSociete
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="idsociete")
* #ORM\GeneratedValue
*/
protected $id;
public function getId() { return $this->id; }
/**
* #ORM\ManyToMany(targetEntity="ImUser", mappedBy="societes")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
}
Get the above working then we can move on to the forms problem.