I'm beginner in Symfony 2.
I'm trying to display a form with a "select" where is the "options" from a query.
I put the following code in my form :
use Doctrine\ORM\EntityRepository;
use Bloc\MainBundle\Entity\Table;
use Bloc\MainBundle\Entity\Table2;
public function addAction(Request $request)
{
$table = new Table();
$form = $this->createFormBuilder($table , array('attr' => array('role' => 'form')))
->add('num', 'integer', array('label' => 'Numéro', 'attr' => array('class' => 'form-control')))
->add('nom_emetteur', 'text', array('label' => 'Emetteur', 'attr' => array('class' => 'form-control')))
->add('numero', 'entity', array('class' => 'BlocMainBundle:Table2', 'property' => 'numero'))
...
}
And I have the following error:
Neither the property "numero" nor one of the methods "getNumero()", "isNumero()", "hasNumero()", "__get()" or "__call()" exist and have public access in class "Bloc\MainBundle\Entity\Table".
I understand that the error tells me that "numero" is not in the entity Table but I question the entity Table2.
I must miss something, but I do not know where ...
My entity definition looks like this :
Table 1:
<?php...
class Table
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="num", type="integer")
*/
private $num;
//Getter and setter...
}
Table 2
<?php
namespace Bloc\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Fournisseur
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Bloc\MainBundle\Entity\Table2Repository")
*/
class Table2
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="numero", type="integer")
*/
private $numero;
/**
* Set numero
*
* #param integer $numero
* #return Fournisseur
*/
public function setNumero($numero)
{
$this->numero = $numero;
return $this;
}
/**
* Get numero
*
* #return integer
*/
public function getNumero()
{
return $this->numero;
}
...
}
Can you help me please ?
If you do not have the relationship set then you need to tell the FormBuilder to not map it to a field.
->add('numero', 'entity', array(
'mapped' => false,
'class' => 'BlocMainBundle:Table2',
'property' => 'numero',
));
To accomplish the options the way that you want (using multiple fields for the option text) you need to use a choice type and build your options list like this:
->add('numero', 'choice', array(
'mapped' => false,
'choices' => $this->buildChoices()
));
protected function buildChoices() {
$choices = [];
$table2Repository = $this->getDoctrine()->getRepository('BlocMainBundle:Table2');
$table2Objects = $table2Repository->findAll();
foreach ($table2Objects as $table2Obj) {
$choices[$table2Obj->getId()] = $table2Obj->getNumero() . ' - ' . $table2Obj->getName();
}
return $choices;
}
you can use this solution. Its a simply and from documentation of symfony2. I m use this
->add('numero', 'entity', array(
'class' => 'BlocMainBundle:Table2',
'choice_label' => 'numero' // MAGIC read next paragraph, it is a private variable
))
Like is in documentation writed:
If the entity object does not have a __toString() method the choice_label option is needed.
Use this solution because its native symfony solution for this situations :)
I hope i will help you or the other people
If you need information's table, you could create a constructor in your Form class
in your controller :
$emForm = $this->getDoctrine()->getRepository('RelacionesDoctrineBundle:Adolecente');
$asignatura = new AsignaturasType($emForm);// your form class
in your form class
class AsignaturasType extends AbstractType {
protected $repository;
function __construct($repository)
{
$this->repository = $repository;
}
}
and done! you use it:
$findAdolecente = $this->repository->findAll();
Related
I develop with symfony a form for create tickets but when i try i got this error:
my function buildform from the file tickettype.php:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('Titre', TextType::class)
->add('Message', TextType::class)
->add('Date', DateTimeType::class, ['data' => new \DateTime()] )
->add('Demandeur', EntityType::class, [
'class' => Client::class,
'choice_label' => 'Nom',
])
->add('Agent', EntityType::class, [
'class' => Dealer::class,
'choice_label' => 'Nom',
])
->add('Etat_Ticket', EntityType::class, [
'class' => Etat::class,
'choice_label' => 'Statut',
]);
}
and in the controller :
/**
* #Route("/add/", name="add_ticket")
*
* #param Request $request
* #return \Symfony\Component\HttpFoundation\Response
*/
public function addTicketAction(Request $request)
{
$ticket = new Ticket();
$form = $this->createForm(TicketType::class, $ticket);
$form->add('send', SubmitType::class, ['label' => 'créé un nouveau ticket']);
$form->handleRequest($request);
if($form->isSubmitted()){
$ticket->setDate(new \DateTime());
$em = $this->getDoctrine()->getManager();
$em->persist($ticket);
$em->flush();
return $this->redirectToRoute('List_ticket');
}
return $this->render("add.html.twig", array('form' => $form->createView()));
}
and my entity Ticket have this property:
/**
* #ORM\ManyToOne(targetEntity=Etat::class, inversedBy="Etat_Ticket")
* #ORM\JoinColumn(nullable=false)
*/
private $Etat_Ticket;
link to the entity Etat which look like this :
/**
* Etat
*
* #ORM\Table(name="etat")
* #ORM\Entity
*/
class Etat
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="statut", type="string", length=255, nullable=false)
*/
private $statut;
public function getId(): ?int
{
return $this->id;
}
public function getStatut(): ?string
{
return $this->statut;
}
public function setStatut(string $statut): self
{
$this->statut = $statut;
return $this;
}
}
You don't have a getter for Etat_Ticket property, so symfony (and that's a PHP common rule, when the property is not public) can't read its value from outside class scope. Symfony Form component, here, is trying by default to use the getter or access the property directly if it were public, and as neither getter nor public property are found, it symply doesn't know how to retrieve the value.
You can feed the form by yourself (docs) or use property_path.
Remember also that binding entities (or in general the domain model) directly to a form is good for RAD (rapid application development) but not so good in the long term. I would suggest to use a sort of DTO in order to read and write from and to the model (take a look here in order to get an idea about this concept)
I am trying to create a Form with a Category selector for a Page entity - Pages can have many categories in multiple Registries.
The relationship from Page --> Category is a OneToMany/ManyToOne with an intermediate PagesCategoryEntity that has a discriminator property (categoryRegistryId).
I have successfully figured out how to use the 'entity' Type in the FormBuilder to create ONE multiple select box. But in the end, I will need to have multiple select-boxes (for each registry) with a discriminator value in the html somewhere.
So, I need to know how to get the additional properties of PagesCategoryEntity into the Form and then how I can access them in the getters/setters of the PageEntity.
Surely, I cannot be the only person to have values in the intermediate entity that need to be accessible in the form and persistence layer?
I appreciate you taking the time to look at this!
craig
truncated Entity and Form classes for Brevity.
class CategoryEntity
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
// other properties, getters, setters, etc...
}
class PageEntity
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="PagesCategoryEntity",
* mappedBy="page", cascade={"all"},
* orphanRemoval=true, indexBy="categoryRegistryId")
*/
private $categories;
// other properties, getters, setters, etc...
}
class PagesCategoryEntity
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $categoryRegistryId;
/**
* #ORM\ManyToOne(targetEntity="CategoryEntity")
* #ORM\JoinColumn(name="categoryId", referencedColumnName="id")
*/
private $category;
/**
* #ORM\ManyToOne(targetEntity="PageEntity", inversedBy="categories")
* #ORM\JoinColumn(name="entityId", referencedColumnName="pageid")
*/
private $page;
}
class PageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('categories', 'entity', array(
'class' => 'MyCoolBundle:CategoryEntity',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.parent = :parent')
->setParameter('parent', 19)
->orderBy('c.name', 'ASC');
},
'property' => "name",
'multiple' => true,
'required' => false,
'empty_data' => null,
));
}
}
Try this then:
->add('categories',
'entity',
array(
'class'=>'Acme\MycoolBundle\Entity\Category',
'property'=>'name',
'query_builder' => function (\Acme\MycoolBundle\Entity\CategoryRepository $repository)
{
return $repository->createQueryBuilder('c')
->where('c.parent = :parent')
->setParameter('parent', 19)
->add('c.name', 'ASC');
}
)
);
try to create a category Repository if u don't have and adapt the scripts for ur needs it works for me!
Try to use Collection instead of using Entity!
Collection is used in one to many/ many to one
you can try the tutorial of symfony cookbook for collection forms
http://symfony.com/doc/current/cookbook/form/form_collections.html
i hope it helps ;)
I have two OneToMany relationship between two entities : Serie ---> Episode and Episode ---> Musique which follow :
class Serie{
........
/**
* #ORM\OneToMany(targetEntity="Episode", mappedBy="serieId")
* #ORM\OrderBy({"numeroE" = "ASC"})
*/
private $episodes;
........
}
class Episode{
........
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="Serie", inversedBy="episodes")
* #ORM\JoinColumn(name="serie_id", referencedColumnName="id")
*/
private $serieId;
/**
* #ORM\OneToMany(targetEntity="Musique", mappedBy="episodeId")
* #ORM\OrderBy({"min" = "ASC", "sec" = "ASC"})
*/
private $musiques;
}
class Musique{
........
/**
* #ORM\ManyToOne(targetEntity="Episode", inversedBy="musiques")
* #ORM\JoinColumn(name="episode_id", referencedColumnName="id")
*/
private $episodeId;
........
}
In my My\ContentBundle\Form\Type\MusiqueType, which represents a Musique Entity Form, I have :
class MusiqueType extends AbstractType{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('episodeId', 'entity', array(
'class' => 'MyContentBundle:Episode' ,
)
->add('serieId', 'entity', array(
'class' => 'MyContentBundle:Serie' ,
'mapped' => false
)
;
}
}
In my view, i'd need to display the 'episodeId' field. However, as there are around one thousand Episodes in my database, i'd like to display in this field only the episodes that belong to the Serie selected.
I was going to use some ajax actions to do this, but i was wondering : is there was a simpler way to do it?
Thank you !
You can be more specific in the generation of your form by adding a custom query to it :
use Doctrine\ORM\EntityRepository;
// ...
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')->orderBy('u.username', 'ASC');
},
));
Refer to the entity Field Type page of SF2 doc for more details.
I have this form with manyTomany relation working perfectly like this:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('manifestations', 'entity', array(
'class' => 'PrifProtocoleBundle:Manifestation',
'multiple' => true,
'expanded' => false,
'property' => 'libelle',
'empty_value' => 'Choississez',
'required' => false,));
}
but i want to set the'multiple' parameter to 'false', this way, i just have a select box with the option 'Choississez', so when i click on it, it displays all the other values. Unfortunately i get an error message: nor of the methods _set()" or "_call()" exist and have public access in class. i've been searching for some solutions on the web and tried this one:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('manifestations', 'collection', array(
'type' => 'entity',
'options' => array(
'class' => 'AcmeProtoBundle:Manifestation',
'multiple' => false,
'expanded' => false,
'property' => 'libelle',
'empty_value' => 'Choisissez',
'required' => false,)));
}
i have no error message! but the select form doesn't display even when i set the 'multiple' to 'true, i only have the submit button, when clicked shows me the results, so i think i miss something in the parameters to display the form!
can anyone help? Thanks
Manifestation.php
/**
* #ORM\Entity
* #ORM\Entity(repositoryClass="ManifestationRepository")
*/
class Manifestation {
public function __construct() {
$this->dateCreation = new \DateTime;
$this->dateModif = new \DateTime;
}
public function __toString() {
return $this->getLibelle();
}
/**
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Id
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="integer")
* #Assert\GreaterThan(
* value = 0,
* message = "La valeur doit être positive"
* )
*/
private $numOrdre;
/**
* #ORM\Column(type="string",length=50)
* #Assert\Length(
* min = "5",
* minMessage = "Le libellé doit faire au moins {{ limit }} caractères"
* )
*/
private $libelle;
/**
* #ORM\Column(type="datetime")
*/
private $dateCreation;
/**
* #ORM\Column(type="datetime")
*/
private $dateModif;
/**
* #ORM\Column(type="boolean")
* #Assert\NotBlank( message=" ")
*/
private $etat;
//getters and setters
invite.php
/**
* #ORM\Entity
* #ORM\Entity(repositoryClass="InviteRepository")
*
*/
class Invite {
/**
* #var boolean
*
* #ORM\ManyToMany(targetEntity="Acme\ProtoBundle\Entity\Manifestation", cascade={"persist"})
* #Assert\NotBlank(message=" ")
*/
private $manifestations;
Can you show your manifestation.php file (your entity)?
Multiple doesn't have the behaviour you are looking for : Multiple is used to allow a user to check multiple checkboxes (true) or only one (false) of a given form (symfony doc : multiple).
In your case a common solution is to use javascript on a parent field that would disable/enable the children fields. Make sure to add server-side validation on these fields if you go for this.
This is the solution working for me now with 'multiple' => false':
i've added this function in the other entity in relation with Manifestation, to consider manifestations as an array
public function setManifestations($manifestations){
if(!is_array($manifestations)){
$manifestations = array($manifestations);
}
$this->manifestations = $manifestations;
}
I am trying to rebuild it in Symfony2 on a many-to-many relationship between users and accounts with query builder but I am failing. this is the DQL
return $er->createQueryBuilder('a')
->leftJoin('\FEB\UserBundle\Entity\Userr', 'u')
->where('a.id = :id')
->setParameter('id', $options['pepe']);
This is the entities:
user.php
namespace FEB\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="feb_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
// tu propia lógica
}
}
Account.php
namespace FEB\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Account
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="FEB\UserBundle\Entity\AccountRepository")
*/
class Account
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Many-To-Many, Unidirectional
*
* #var ArrayCollection $idusr
*
* #ORM\ManyToMany(targetEntity="\FEB\UserBundle\Entity\User")
* #ORM\JoinTable(name="accounts_users",
* joinColumns={#ORM\JoinColumn(name="account_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="usr_id", referencedColumnName="id")}
* )
*/
private $idusr;
public function __construct() {
$this->idusr = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Set idusr
*
* #param string $idusr
* #return Account
*/
public function setIdusr($idusr)
{
$this->idusr = $idusr;
return $this;
}
/**
* Get idusr
*
* #return integer
*/
public function getIdusr()
{
return $this->idusr;
}
When I execute the DQL I got all the records of "account" table and not the join:
The SQL statement I want to run would be this:
SELECT *
FROM Account a
LEFT JOIN accounts_users au ON ( au.usr_id = a.id )
WHERE au.usr_id = 1
How can I fix it?
Edit 1:
The idea is retrieve the result to populate a drop-down in account form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('titulo')
->add('tweet', 'textarea')
->add('photo', 'file', array('required' => false))
->add('tags', 'entity', array(
'class' => 'FEBTagsBundle:tag',
'property' => 'tag',
'empty_value' => 'Selecciona tags',
'multiple' => true))
->add('idaccount', 'entity', array(
'class' => 'FEBUserBundle:Account',
'property' => 'username',
'query_builder' => function(EntityRepository $er ) use ($options) {
return $er->createQueryBuilder('a')
->leftJoin('\FEB\UserBundle\Entity\User', 'u')
->where('a.id = :id')
->setParameter('id', $options['pepe']);
//->andWhere('w.visible = 1')
//->andWhere('w.booked = 0');
;},
'empty_value' => 'Selecciona account',
'multiple' => false))
;
}
EDIT2: More info.
The goal is:
From the id of the "feb_user" table, I get the username of the "Account" table. The table feb_user and Account tables are related through the "accounts_users" table.
Correct me if I'm wrong, but you can just query the user like:
$Account = $er->find(<<some_id>>);
Now you can fetch the account and can access the User entity:
$User = $Account->getIduser();
I finally found the solution!
My mistake was in the way I created the DQL. In the leftjoin sentence I referred to the entity, andthe correct way is making reference to the variable that linked the two entities. Would be as follows:
->add('idaccount', 'entity', array(
'class' => 'FEBUserBundle:Account',
'property' => 'username',
'query_builder' => function(EntityRepository $er ) use ($options) {
return $er->createQueryBuilder('a')
->leftJoin('a.idusr', 'u')
->where('u.id = :id')
->setParameter('id', $options['pepe']);
},
'empty_value' => 'Selecciona account',
'multiple' => false));
Thanks to all!!!!