I want to use the query_builder in a Symfony2 FormType, I tried to make a simple request in my Postgresql shema using Doctrine DQL. It return me an error and i don't really understand how fix it :
PDOException: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "" AS id0 FROM ""
LINE 1: SELECT "0_."id" AS id0 FROM "DATA_WAREHOUSE"."WindFarm" "0_
This is the Windfarm class :
<?php
namespace Base\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* WindFarm
*
* #ORM\Table(name="""DATA_WAREHOUSE"".""WindFarm""")
* #ORM\Entity(repositoryClass="Base\CoreBundle\Repository\WindFarmRepository")
*/
class WindFarm
{
/**
* #ORM\OneToMany(targetEntity="Base\CoreBundle\Entity\Turbine", mappedBy="windFarm")
*/
private $turbines;
/**
* #var string $id
*
* #ORM\Column(name="""id""", type="string", length=32)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\SequenceGenerator(sequenceName="""DATA_WAREHOUSE"".""WindFarm_id_seq""", allocationSize=1, initialValue=1)
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="""name""", type="text", nullable=true)
*/
private $name;
/**
* #var string $alias
*
* #ORM\Column(name="""alias""", type="string", length=32, nullable=true)
*/
private $alias;
/**
* #var string $location
*
* #ORM\Column(name="""location""", type="text", nullable=true)
*/
private $location;
/**
* #var string $sncNbr
*
* #ORM\Column(name="""sncNbr""", type="string", length=8, nullable=true)
*/
private $sncNbr;
}
The DQL request in the WindFarmRepository:
public function getWindFarmsAndTurbines(){
$qb = $this->createQueryBuilder()
->select('wft')
->from('BaseCoreBundle:WindFarm', 'wft')
->leftJoin('wft.turbines', 't')
->addSelect('t')
->orderBy('t.alias');
return $qb;
}
The FormType :
<?php
namespace Base\CoreBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Base\CoreBundle\Repository\WindFarmRepository;
class TurbineStatusCodeType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('exportBegin', 'date', array('input' => 'datetime',
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',))
->add('exportEnd', 'date', array('input' => 'datetime',
'widget' => 'single_text',
'format' => 'yyyy-MM-dd',))
->add('arrayId', 'textarea')
->add('turbines', 'entity', array('class' => 'BaseCoreBundle:WindFarm',
'property' => 'name',
'multiple' => true,
'expanded' => true,
'query_builder' => function(WindFarmRepository $repo){
return $repo->getWindFarmsAndTurbines();
}))
->add('save', 'submit');
}
/**
* #return string
*/
public function getName()
{
return 'base_corebundle_turbineStatusCodeType';
}
}
apparently, the problem is situated in the quote, I tried many solutions, but nothing work.
All of your Doctrine annotations are incorrect and have extra double-quotes.
#ORM\Column(name="""id""", type="string", length=32)
should be
#ORM\Column(name="id", type="string", length=32)
and so on
Related
My form is returning the following error:
An exception occurred while executing 'UPDATE user_info SET
country_of_residence = ?, want_children = ?, salary = ? WHERE id = ?'
with params [{}, "a", "0", 22]:
Catchable Fatal Error: Object of class AppBundle\Entity\Country could
not be converted to string
My UserInfoType:
<?php
// src/AppBundle/Form/UserInfoType.php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class UserInfoType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('first_name', TextType::class, array('label' => 'Prénom'))
->add('surname', TextType::class, array('label' => 'Nom'))
->add('nationality', TextType::class, array('label' => 'Nationalité'))
->add('country_of_residence', EntityType::class, array(
'class' => 'AppBundle:Country',
'choice_label' => 'name',
))
->add('maritial_status', TextType::class, array('label' => 'Votre statut maritial'))
->add('ethnique_origin', TextType::class, array('label' => 'Origine ethinique'))
->add('spoken_language', TextType::class, array('label' => 'Langues parlés'))
->add('children', TextType::class, array('label' => 'Possèdez vous des enfants'))
->add('want_children', TextType::class, array('label' => 'Désirez vous des enfants'))
->add('astrological_sign', TextType::class, array('label' => 'Votre signe astrologique'))
->add('education', TextType::class, array('label' => 'Votre niveau d\'étude'))
->add('profession', TextType::class, array('label' => 'Votre profession'))
->add('salary', TextType::class, array('label' => 'Votre salaire'))
->add('save', SubmitType::class, array('label' => 'Suivant'))
;
}
My country entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Country
*
* #ORM\Table(name="country")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CountryRepository")
*/
class Country
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="code", type="string", length=255)
*/
private $code;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="language", type="string", length=255)
*/
private $language;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set code
*
* #param string $code
*
* #return Country
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
/**
* Set name
*
* #param string $name
*
* #return Country
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set language
*
* #param string $language
*
* #return Country
*/
public function setLanguage($language)
{
$this->language = $language;
return $this;
}
/**
* Get language
*
* #return string
*/
public function getLanguage()
{
return $this->language;
}
}
My profil controller:
/**
* #Route("/survey/{slug}", name = "survey_render" )
*/
public function renderSurvey($slug, Request $request)
{
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$user_info = $em->getRepository('ProfileBundle:UserInfo')->findOneBy(array('userId' => $user->getId()));
if (!$user_info) {
$user_info = new UserInfo();
$user_info->setuserId($user->getId());
}
$user_pref = $em->getRepository('ProfileBundle:UserPreference')->findOneBy(array('userId' => $user->getId()));
if (!$user_pref) {
$user_pref = new UserPreference();
$user_pref->setuserId($user->getId());
}
//$user_info = new UserInfo();
switch ($slug) {
case 'vos_infos':
$form = $this->createForm(UserInfoType::class, $user_info );
break;
case 'votre_apparance':
$form = $this->createForm(UserAppearanceType::class, $user_info);
break;
case 'votre_style_vie':
$form = $this->createForm(UserLifeStyleType::class, $user_info);
break;
case 'ses_infos':
$form = $this->createForm(UserPrefInfoType::class, $user_pref);
break;
case 'son_apparence':
$form = $this->createForm(UserPrefAppearanceType::class, $user_pref);
break;
case 'son_style_vie':
$form = $this->createForm(UserPrefLifeStyleType::class, $user_pref);
break;
case 'votre_quiz':
$form = $this->createForm(UserLifeStyleType::class, $user_pref);
break;
default;
echo 'Lien incorrect';
break;
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$form_data = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($form_data);
$em->flush();
It seems that its trying to pass the whole entity to the form and not just the choice results.
Does anyone have an idea of what im doing wrong here?
Thx
Ok i found the error I had in UserInfo.
I did not prepend #ORM and did not have the correct path to the Country entity ( it is not in the same namespace)
Before:
/**
* One Product has One Shipping.
* #OneToOne(targetEntity="Country")
* #JoinColumn(name="countryOfResidence", referencedColumnName="id")
*/
private $countryOfResidence;
After:
/**
* One Product has One Shipping.
* #ORM\OneToOne(targetEntity="AppBundle\Entity\Country")
* #ORM\JoinColumn(name="countryOfResidence", referencedColumnName="id")
*/
private $countryOfResidence;
Thanks for pointing me in the right direction.
If user_info is an entity do you have set the field country_of_residence as a onetoone relation on country entity ?
I got the same type of error. In my case it was an erroneous annotation in the 'owning' entity.
Befor (causes error):
/**
* #ORM\OneToOne(targetEntity="RfpMatchBundle\Entity\Address", cascade={"persist"})
* #ORM\Column(nullable=true, unique=false)
*/
private $address;
After(fixed):
/**
* #ORM\OneToOne(targetEntity="RfpMatchBundle\Entity\Address", cascade={"persist"})
*/
private $address;`
I created a form in Symfony with this setup:
#\src\AppBundle\Entity\Order.php
class Order
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $orderID
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
*/
protected $orderID;
/**
* #var string $email
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
* #Assert\Email()
*/
protected $email;
...
In my form type:
# \src\AppBundle\Form\OrderType.php
class OrderType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('order_id', TextType::class, [
'label' => 'index.order_id',
'attr' => array(
'placeholder' => 'index.order_id.placeholder'
)
])
->add('email', EmailType::class, [
'label' => 'index.email',
'attr' => array(
'placeholder' => 'index.email.placeholder'
)
]);
}
...
So if I submit the form with empty fields, Symfony detects both errors but the order ID error is assigned to the Class instead of the actual field.
Any ideas?
Update
I renamed protected $orderID; to protected $orderid; and the problem is fixed! So why this happened? Is there any reserved names when it comes to the use of ID in the property name?
I think you should have this because that's what you specified in buildForm:
/**
* #var string $order_id
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
*/
protected $order_id;
Can you try it?
I need help with Symfony2 (2.8)
Created two entities Category and CategoryLang. It will be a categories.
<?php
namespace CreLabs\Bundle\SettingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Entity;
/**
* #ORM\Entity(repositoryClass="CreLabs\Bundle\SettingBundle\Entity\CategoryRepository")
* #ORM\Table(name="category")
*/
class Category
{
const STATUS_ENABLED = 1;
const STATUS_DISABLED = 0;
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="boolean", nullable=true, options={"default": 1})
*/
protected $status;
/**
* #ORM\OneToMany(targetEntity="CategoryLang", mappedBy="category", cascade={"persist", "remove"})
*/
protected $locales;
/**
* #ORM\Column(type="datetime", nullable=false)
*/
protected $created_at;
/**
* #ORM\Column(type="datetime", nullable=true)
*/
/**
* #ORM\Column(type="datetime", nullable=true)
*/
protected $updated_at;
CategoryLang. It will be a translation of my categories.
<?php
namespace CreLabs\Bundle\SettingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Entity;
/**
* #Entity
* #ORM\Table(name="category_lang")
*/
class CategoryLang
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
protected $name;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $description;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="locales", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
/**
* #ORM\Column(type="string", length=2)
*/
protected $locale;
Now i trying add createFormBuilder Category Entity + CategoryLang Entities fields, but can not see normally form. Only can use array('mapped' => false and forward data from fields.
$form = $this->createFormBuilder($category);
$form = $form
->add('locale', HiddenType::class, array('mapped' => false, 'data' => $locale))
->add('name', TextType::class, array('mapped' => false, 'data' => $name))
->add('description', TextareaType::class, array('mapped' => false, 'required' => false, 'data' => $description))
->add($label, SubmitType::class, array('label' => $label));
$form = $form->getForm();
By the way have CategoryRepository with custom query
public function getCategory($category_id, $locale)
{
$repository = $this->getEntityManager()->getRepository('SettingBundle:Category');
$fields = array('p.id', 'category_info.name', 'category_info.description', 'p.status, category_info.locale');
$query = $repository->createQueryBuilder('p')
->select($fields)
->innerJoin('SettingBundle:CategoryLang', 'category_info', 'WITH', 'category_info.category = p.id')
->where('p.id = :category_id AND category_info.locale = :locale')
->setParameter('category_id', $category_id)
->setParameter('locale', $locale)
->getQuery();
$result = $query->getOneOrNullResult() != NULL ? new ArrayCollection($query->getSingleResult()) : false;
return $result;
}
Problems:
1. getCategory() -> return not object, but array or ArrayCollection. Can not be reused then need update fields in database.
/* #var $category Category */
$category = $this->getCategory($category_id, $form['locale']);
if ($category) {
// $category->setUpdatedAt(new ArrayCollection());
$locale = new CategoryLang();
$locale->setName($form['name']);
$locale->setDescription($form['description']);
$category->addLocale($locale);
$entityManager = $this->getEntityManager();
$entityManager->persist($category);
$entityManager->flush($category);
}
2. Can not get in create form builder information from child table.
Where is my problem? Can anybody help me understand my mistakes?
I have implemented the 'collection' form type in my app, and it works great, including removing related records that are removed from the submitted data, however in order to save any newly added link record I have to manually loop through the links entities & set the owner as the entity being edited. I'm sure it should do this automatically, so what have I missed?
You'll see a...
/*****************************************************************
* This is the bit I've had to add to persist the new entries!!! *
*****************************************************************
... where I've had to manually link the entities in the AppController file.
The files
App Entity
<?php
namespace ...\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* App
*
* #ORM\Table()
* #ORM\Entity()
*/
class App
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
/**
* #var AppAppStoreData[]|ArrayCollection
*
* We use orphan removal here to remove the link data when deleting an app
* #ORM\OneToMany(targetEntity="AppAppStoreData", mappedBy="app", cascade={"all"}, orphanRemoval=TRUE)
*/
private $appAppStoreData;
// ...
/**
* #return ArrayCollection|AppAppStoreData[]
*/
public function getAppAppStoreData()
{
return $this->appAppStoreData;
}
/**
* #param ArrayCollection|AppAppStoreData[] $appAppStoreData
*
* #return $this
*/
public function setAppAppStoreData( $appAppStoreData )
{
$this->appAppStoreData = $appAppStoreData;
return $this;
}
}
AppStore Entity
<?php
namespace ...\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* AppStore
*
* #ORM\Table()
* #ORM\Entity()
*/
class AppStore
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
/**
* #var AppAppStoreData[]|ArrayCollection
*
* We use orphan removal here to remove the link data when deleting an app
* #ORM\OneToMany(targetEntity="AppAppStoreData", mappedBy="appStore", cascade={"all"}, orphanRemoval=TRUE)
*/
private $appAppStoreData;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
// ...
/**
* #return AppAppStoreData[]|ArrayCollection
*/
public function getAppAppStoreData()
{
return $this->appAppStoreData;
}
/**
* #param AppAppStoreData[]|ArrayCollection $appAppStoreData
*
* #return $this
*/
public function setAppAppStoreData( $appAppStoreData )
{
$this->appAppStoreData = $appAppStoreData;
return $this;
}
}
AppAppStoreData Entity
<?php
namespace ...\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* AppAppStoreData
*
* #ORM\Table()
* #ORM\Entity()
*/
class AppAppStoreData
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var App
*
* #ORM\ManyToOne(targetEntity="App", inversedBy="appAppStoreData")
* #ORM\JoinColumn(name="app_id", referencedColumnName="id")
*/
private $app;
/**
* #var AppStore
*
* #ORM\ManyToOne(targetEntity="AppStore", inversedBy="appAppStoreData")
* #ORM\JoinColumn(name="app_store_id", referencedColumnName="id")
*/
private $appStore;
/**
* #var string
*
* #ORM\Column(name="app_store_uri", type="string", length=1083)
*/
private $appUri;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set app
*
* #param App $app
*
* #return AppAppStoreData
*/
public function setApp(App $app)
{
$this->app = $app;
return $this;
}
/**
* Get app
*
* #return App
*/
public function getApp()
{
return $this->app;
}
/**
* Set appStore
*
* #param AppStore $appStore
*
* #return AppAppStoreData
*/
public function setAppStore(AppStore $appStore)
{
$this->appStore = $appStore;
return $this;
}
/**
* Get appStore
*
* #return AppStore
*/
public function getAppStore()
{
return $this->appStore;
}
/**
* Set appStoreLink
*
* #param string $appUri
*
* #return AppAppStoreData
*/
public function setAppUri( $appUri)
{
$this->appUri = $appUri;
return $this;
}
/**
* Get appStoreLink
*
* #return string
*/
public function getAppUri()
{
return $this->appUri;
}
}
AppType Form
<?php
namespace ...\Form\Type;
use ...\Entity\App;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class AppType extends AbstractType
{
/**
* Builds the App admin edit form
*
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder
// ...
->add( 'appAppStoreData', 'collection', [
'type' => new ,
'label' => 'App Store Links',
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'widget_add_btn' => array( 'label' => "Add App Store Details" ),
'widget_remove_btn' => array( 'label' => "Remove App Store Details" ),
'show_legend' => false, // dont show another legend of subform
'options' => array( // options for collection fields
'label_render' => false,
'widget_addon_prepend' => array(
'text' => '#',
),
'horizontal_input_wrapper_class' => "col-lg-8",
),
] );
}
/**
* Sets the Entity data class
*
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions( OptionsResolverInterface $resolver )
{
$resolver->setDefaults(
array(
'data_class' => '...\Entity\App',
)
);
}
/**
* Returns the name of this type.
*
* #return string The name of this type
*/
public function getName()
{
return 'app';
}
}
AppAppStoreDataFieldsType
<?php
namespace ...\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class AppAppStoreDataFieldsType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm( FormBuilderInterface $builder, array $options )
{
$builder
->add( 'appStore', 'entity', [
'class' => '...Bundle:AppStore',
'property' => 'name',
'label' => 'App Store'
] )
->add( 'appUri', 'url', [
'label' => 'App URI'
] );
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions( OptionsResolverInterface $resolver )
{
$resolver->setDefaults( array(
'data_class' => '...\Entity\AppAppStoreData'
) );
}
/**
* #return string
*/
public function getName()
{
return 'app_store_data_fields';
}
}
App Controller
<?php
namespace ...\Controller;
use ...\Entity\UploadableInterface;
use ...\Exception\RecordNotFoundException;
use ...\Exception\RedirectException;
use ...\Entity\App;
use ...\Entity\AppRepository;
use ...\Entity\ClientRepository;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class AppController extends ClientAssetController
{
/**
* #param Request $request
* #param null $id
*
* #return Response
*/
public function editAction( Request $request, $id = null )
{
$app = #$this->getAppRepository()->find( $id );
// ...
$form = $this->createForm( 'app', $app )
->add( 'save', 'submit', [ 'label' => 'Save' ] );
$form->handleRequest( $request );
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist( $app );
/*****************************************************************
* This is the bit I've had to add to persist the new entries!!! *
*****************************************************************
/
foreach ($app->getAppAppStoreData() as $appAppStoreDatum) {
$appAppStoreDatum->setApp( $app );
}
$em->flush();
// ... Redirect
}
// ... Render
}
// ...
}
initialize the collection of appAppStoreData:
...
public function __construct()
{
$this->appAppStoreData = new ArrayCollection();
}
I'm trying to create a form which dinamically load all "sites" related to a "project", It seems like this would be of use, so I tried it:
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class EngineeringType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('project','entity',array(
'class' => 'tBundle:Project',
'label' => 'Project'
;
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
$sites = $data->getProject()->getSites();
$form->add('site', 'entity', array('choices' => $sites));
}
);
}
My problem comes when I try to access the form, I get:
FatalErrorException: Error: Call to a member function getSites() on a non-object in ... tBundle\Form\EngineeringType.php line 41
Here are my entities:
namespace tBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Engineering
*
* #ORM\Table(name="engineerings")
* #ORM\Entity
*/
class Engineering
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="tBundle\Entity\Project")
* #ORM\JoinColumn(name="project_id", referencedColumnName="id",nullable=false)
*/
private $project;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set project
*
* #param string $project
* #return Engineering
*/
public function setProject(\tBundle\Entity\Project $project)
{
$this->project = $project;
return $this;
}
/**
* Get project
*
* #return string
*/
public function getProject()
{
return $this->project;
}
Project:
namespace tBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Project
*
* #ORM\Table(name="projects")
* #ORM\Entity
*/
class Project
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #ORM\ManyToMany(targetEntity="tBundle\Entity\Site")
* #ORM\JoinTable(name="project_sites",
* joinColumns={#ORM\JoinColumn(name="site_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="project_id", referencedColumnName="id")}
* )
*/
private $sites;
public function __construct()
{
$this->sites = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Project
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Get Sites
*
* #return array
*/
public function getSites()
{
return $this->sites;
}
/* Returns Project's Name */
public function __toString()
{
return $this->name;
}
What am I doing wrong?
EDIT
Controller:
/**
* Creates a form to create a Engineering entity.
*
* #param Engineering $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Engineering $entity)
{
$form = $this->createForm(new EngineeringType(), $entity, array(
'action' => $this->generateUrl('engineering_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
/**
* Creates a form to edit a Engineering entity.
*
* #param Engineering $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Engineering $entity)
{
$form = $this->createForm(new EngineeringType(), $entity, array(
'action' => $this->generateUrl('engineering_update', array('id' => $entity->getId())),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Update'));
return $form;
}
The PRE_SET_DATA event is actually fired twice. The first time will not have any data. There used to be a blurb in the manual explaining why but I could not find it again.
So just:
function(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if ($data)
{
$sites = $data->getProject()->getSites();
$form->add('site', 'entity', array('choices' => $sites));
}
}
=======================================================
Updated answer to show how to handle non-existent $project:
if ($data)
{
$project = $data->getProject();
$sites = $project ? $project->getSites() : array();
$form->add('site', 'entity', array('choices' => $sites));
}
There is an easy solution, why don't you use the "property" property on the form builder?
$builder
->add('project','entity',array(
'class' => 'tBundle:Project',
'label' => 'Project',
'property' => 'sites');
Or even you can use a query builder if this is not enough:
$builder->add('users', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.username', 'ASC');
},
));
You can find here more description, if this is not enough:
Symfony documentation
EDIT:
So your problem that with the first solution, that it's going to be an array, so use my second option, and in the query builder, specify what will reflect your needs.
Or use it like the class is not Project but Sites.