If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
Open GenusFormType
and find the configureOptions()
method. Add $resolver->setDefaults()
.
Pass that an array with a single key called data_class
set to AppBundle\Entity\Genus
:
... lines 1 - 8 | |
class GenusFormType extends AbstractType | |
{ | |
... lines 11 - 19 | |
public function configureOptions(OptionsResolver $resolver) | |
{ | |
$resolver->setDefaults([ | |
'data_class' => 'AppBundle\Entity\Genus' | |
]); | |
} | |
} |
Do nothing else: refresh to re-submit the form.
Tip
You can also use a newer syntax in PHP for this:
'data_class' => Genus::class
Most editors will auto-complete this for you!
Boom! Now we have a brand-new Genus
object that's just waiting to be saved. Thanks
to the data_class
option, the form creates a new Genus
object behind the scenes.
And then it sets the data on it.
Earlier, when we got back an associative array, these field names - name
, speciesCount
and funFact
– could have been anything:
... lines 1 - 8 | |
class GenusFormType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder | |
->add('name') | |
->add('speciesCount') | |
->add('funFact') | |
; | |
} | |
... lines 19 - 25 | |
} |
But as soon as you bind your form to a class, name
, speciesCount
and funFact
need
to match property names inside of your class:
... lines 1 - 11 | |
class Genus | |
{ | |
... lines 14 - 23 | |
private $name; | |
... lines 25 - 34 | |
private $speciesCount; | |
... lines 36 - 39 | |
private $funFact; | |
... lines 41 - 132 | |
} |
Actually, that's kind of a lie. These properties are private, so the form component
can't set them directly. In reality, it guesses a setter function for each field and
call that: setName()
, setSpeciesCount()
and setFunFact()
:
... lines 1 - 11 | |
class Genus | |
{ | |
... lines 14 - 67 | |
public function setName($name) | |
{ | |
$this->name = $name; | |
} | |
... lines 72 - 90 | |
public function setSpeciesCount($speciesCount) | |
{ | |
$this->speciesCount = $speciesCount; | |
} | |
... lines 95 - 100 | |
public function setFunFact($funFact) | |
{ | |
$this->funFact = $funFact; | |
} | |
... lines 105 - 132 | |
} |
Technically, you could add a form field call outOnAMagicalJourney
as long as you had
a public method in your class called setOutOnAMagicalJourney()
.
Head back to your browser, highlight the URL and hit enter. This just made a GET request, which skipped form processing and just rendered the template.
Let's add a few more field we need: like subFamily
:
... lines 1 - 8 | |
class GenusFormType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder | |
->add('name') | |
->add('subFamily') | |
->add('speciesCount') | |
->add('funFact') | |
... lines 18 - 19 | |
; | |
} | |
... lines 22 - 28 | |
} |
Hey, we're even getting auto-complete now: PhpStorm knows Genus
has a subFamily
property!
Also add isPublished
- that should eventually be a checkbox - and firstDiscoveredAt
-
that will need to be some sort of date field:
... lines 1 - 8 | |
class GenusFormType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder | |
->add('name') | |
->add('subFamily') | |
->add('speciesCount') | |
->add('funFact') | |
->add('isPublished') | |
->add('firstDiscoveredAt') | |
; | |
} | |
... lines 22 - 28 | |
} |
Cool, try it out!
Huge error!
Catchable Fatal Error: Object of class
SubFamily
could not be converted to string
Okay: that's weird. What's going on?
Until now, it looked like Symfony renders every field as an input text field by default. But that's not true! There's a lot more coolness going on behind the scenes!
In reality, the form system looks at each field and tries to guess what type of
field it should be. For example, for subFamily
, it sees that this is a ManyToOne
relationship to SubFamily
:
... lines 1 - 11 | |
class Genus | |
{ | |
... lines 14 - 25 | |
/** | |
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\SubFamily") | |
* @ORM\JoinColumn(nullable=false) | |
*/ | |
private $subFamily; | |
... lines 31 - 132 | |
} |
So, it tries to render this as a select drop-down of sub families. That's amazing, because it's exactly what we want.
But, it needs to be able to turn a SubFamily
object into a string so it can render
the text for each option in the select. That's the source of the error.
To help it, add a public function __toString()
to the SubFamily
class:
... lines 1 - 10 | |
class SubFamily | |
{ | |
... lines 13 - 39 | |
public function __toString() | |
{ | |
return $this->getName(); | |
} | |
} |
Refresh again!
Look at this! A free drop-down with almost no work. It also noticed that isPublished
should be a checkbox because that's a boolean
field in Doctrine:
... lines 1 - 11 | |
class Genus | |
{ | |
... lines 14 - 41 | |
/** | |
* @ORM\Column(type="boolean") | |
*/ | |
private $isPublished = true; | |
/** | |
* @ORM\Column(type="date") | |
*/ | |
private $firstDiscoveredAt; | |
... lines 51 - 132 | |
} |
And since firstDiscoveredAt
is a date, it rendered it with year-month-day drop-down
boxes. Now, those three boxes are totally ugly and we'll fix it later, but isn't it
cool that it's guessing the right field types?
Fill out the form again with super-realistic data and submit. Woh! One more error:
Neither the property
isPublished
nor one of the methodsgetIsPublished()
exist and have public access in classGenus
Remember how every form field needs a setter function on your class? Like name
and
setName()
? Every field also needs a getter function - like getIsPublished()
or one of these other variations.
This was my bad: when I set this up, I added an isPublished
property, a setIsPublished()
method, but no getter! I'll use the "Code"->"Generate" menu - or command
+N
- to generate
that getter:
... lines 1 - 11 | |
class Genus | |
{ | |
... lines 14 - 115 | |
public function getIsPublished() | |
{ | |
return $this->isPublished; | |
} | |
... lines 120 - 137 | |
} |
Refresh! It dumps the Genus
object of course, but check out the subFamily
field!
It's not the SubFamily
ID - the form field took the submitted ID, queried the
database for the SubFamily
object and set that on the property. That's HUGE.
We're ready to save this!
Hey Jelle S.!
Ah, super glad you're happy! Well, happy except for this error :). And it is a strange error! What does the code look like for your ChoiceType::class
field? Are you possibly passing it a choices
option explicitly? And if so, is it possible that some of the objects you're passing haven't been saved to the database yet?
Let me know - I'm sure we can debug it!
Cheers!
Thanks, but I`ve found the solution in the controller I tried pass extra data about the object which was not needed and caused the error
How can I create form fields relation entity?
I have relation invoice entity and detail entity, I would create a form type with fields of invoice and detail, please can you help me?
Thanks
Hey Gianluca M.
You can embed forms. If you create a DetailEntity form, then you would be able to embed it into the InvoiceEntity form. You can see an example here: https://symfony.com/doc/cur...
Another approach is to use a DTO to map all the fields you want to have in your form. Here is an example of how to do it: https://symfonycasts.com/sc...
Cheers!
Hey Maksym,
That's a good tool and definitely in some cases you can prefer to use it instead, but it *always* generates both setters and getters. However, for example, some entities could not have setters, or probably in some cases you don't need both setters /getters. So, in some cases, better to add them manually instead of remove unnecessary methods after this tool.
IMO, in PhpStorm I can add setters/getters quicker, i.e. I don't need to switch to the console and back to the IDE :p
Cheers!
HI! This is an amazing course!
I have a question, what about form binding against an object with oneToMany relationship?
I have an Organization Entity that haves a telephone column. The column is related to a table of phones with area code, country code and FK of the organization.
When i print the entire form just for a test, i have an error saying that the columns of the Phones table doesnt exist. Should i create a new Object Phone before the createForm function, and then pass it as an argument? I dont know if in that case the phone will be related to the Organization.
Thank you!
Hey Fran!
When your entity has a relationship to other entity, in your FormType, you have to add that field as an EntityType, so you will see a menu with a list of phones. You can read more about EntityType's here: http://symfony.com/doc/curr...
Have a nice day!
Hey, thank you for the reply. But if I have to just print 3 number field types that belongs to other tables I have to use the EntityType too? What I need to do is that the fields phone - area code and country code get saved in the Phone number's column, with the FK of the organization (I'm not the owner of the database so unfortunately I can´t change that)
Oh, so you are not using Doctrine's ORM ?
In that case you would have to do it manually, add 3 "not mapped" fields to you Form, and create a new Phone instance, setting up those values manually.
You may find these links helpful:
Form mapped option: http://symfony.com/doc/curr...
Form without data class: https://symfony.com/doc/cur...
Cheers!
Sorry, im not explaining it well.
I'm using Doctrine´s ORM but i don´t need to fill a select box with number's from another Entity, i just need to display 3 input´s (Area Code - Country code - Phone Number) that will save data in another table (Phone's table) The Organization has a relation oneToMany with the Phone's Entity (with Doctrine Annotation)
These 3 fields are the only that not belong to my class related to the form, so i don't know how to show them properly.
Thank you so much for your replies and your time!
Yo Fran!
Ah, now I think I understand :). There are sort of 2 answers:
1) I don't love the way your relationship is setup, but you may have a good reason :). With this relation, it means that one Organization can have many Phone numbers. Is that correct? It's even a bit more confusing because it seems like you want to create a form where the user is entering just one Phone number, not many. But, sometimes this is exactly what you want :).
2) If this is exactly what you want, then here is what you should do:
A) Add these 2 new methods to your Organization entity:
public function getMainPhone()
{
return $this->phones->first();
}
public function setMainPhone(Phone $phone)
{
if ($this->phones->contains($phone)) {
return;
}
$this->phones[] = $phone;
// make sure to set the owning side of the relation
$phone->setOrganization($this);
}
B) Create a PhoneFormType class with the fields you need on it: areaCode, countryCode, phoneNumber (make sure to set the data_class to the Phone entity)
C) In OrganizationFormType (or however you call it), add a new mainPhone field:
$builder
// ...
->add('mainPhone', PhoneFormType::class)
That should be it! You've now tricked the form system into thinking that your Organization has one Phone (mainPhone). When you fill out the 3 fields, it will create a new Phone and call setMainPhone(). It will even work if you edit an organization.
Let us know if this helps!
Cheers!
Yes, thank you! I know is a little bit weird, im trying to convince my boss that we can change that about the Phone's list.
I have one last question! What about validation inside PhoneFormType? When i try to apply the Validate() annotation for embedded forms, y have an error saying:
"Expected argument of type "AppBundle\Entity\Phone", "array" given
I think that's because the 3 fields (area code, country code and phone) are passing as an array? Im mapping the PhoneFormType just like the other forms, with the data_class
Thank you so much for your help!
Yo Fran!
Hmmm. Do you mean the @Valid annotation? Can you post a screenshot of the full stacktrace... I'm not sure exactly where that error is coming from. And also post your 2 form classes if you can. And you do absolutely have data_class => Phone::class
inside PhoneFormType, right? I'm sure it's some small details we've missed!
Cheers!
Fortunately I was able to change the structure of the phone table, but I have the same problem with another embedded form, it's exactly the same error. Sorry if the explanation is very long, but I have not been able to solve it for many hours! Thank you so much for your help anyway!
I have a user form related to an entity:
Https://puu.sh/xbFKZ/e24d7b...
The entity: https://puu.sh/xbGhL/5049e4...
The user is related to the Organization:
Https://puu.sh/xbGlN/1f57a6...
Reverse relation: https://puu.sh/xbGmO/e0cb8c...
In this way an organization has a contact user.
In the new organization view/controller I have a form:
Https://puu.sh/xbGJh/854eb7... (and is linked with data_class
The form is nested to the UserOrganizationContact form, so that an organization can be registered along with the contact user:
Https://puu.sh/xbGR0/efd928...
I get this form and send it to twig, which shows it correctly. The only problem is when I want to validate it, otherwise I correctly create the contact entity!
Https://puu.sh/xbH9m/da3173...
Finally, when I apply the Valid () annotation in Entity / Organization, on the contact relation column, the following error occurs, only in the submit form:
Https://puu.sh/xbHpR/fd0399...
If I delete the Valid annotation, it works correctly and creates the Organizationcontact entity:
Https://puu.sh/xbHsd/dc399d...
Thank you for your time, this courses are helping me a lot!
Hmmm, it's very weird. The error is actually coming from the UniqueEntity validator that the PUGMultiUserBundle provides. And it's quite confusing. Above your entity, you have @UniqueEntity(fields={"email"}...)
. But, looking at the validator, for some reason, it looks like it expects fields to be a string only. Look, it's clearly concatenating your "fields" like a string: https://github.com/PUGX/PUGXMultiUserBundle/blob/226a5adf3f23f9820cbe038f351e59fe2e268d7b/Validator/Constraints/UniqueEntityValidator.php#L34. I don't know this bundle, but this looks like a possible bug to me!
Try this: just do @UniqueEntity(fields="email"...)
. So, just make fields be a string. I think this is allowed, and it may fix the issue.
Cheers!
Amazing tutorial!
For some reason subFamily field does not render as select type, instead it is normal text field. Am I missing something?
Hey Mohammad,
Thanks! Hm, that's weird. Did you specify any type as the second argument for subFamily field ? Or, do you have only:
$builder
->add('subFamily')
// other fields...
And how does your Genus::$subFamily ORM definition looks like?
Cheers!
Hi Victor,
No, I have only $builder->add('name')
->add('subFamily')
->add('speciesCount')
...
and the ORM looks like this:
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\SubFamily")
* @ORM\Column(nullable=false)
*/
private $subFamily;
Thanks
Hey Mohammad Althayabeh
Did you bind your Form to an entity class? Something like this:
// YourFormType class
...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Genus'
]);
}
If you did, could you show me the code of you Form, please? So, I can help you debugging
Cheers!
Yes I did. Below the class code of the formType
class GenusFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name')
->add('subFamily')
->add('speciesCount')
->add('funFact')
->add('isPublished')
->add('firstDiscoveredAt');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class'=>'AppBundle\Entity\Genus'
]);
}
public function getBlockPrefix()
{
return 'app_bundle_genus_form_type';
}
}
This is weird indeed, makes me wonder a few fundamental things
Did you update the DataBase schema ? $ php bin/console doctrine:schema:update --force
Did you change anything about how Doctrine reads Entity metadata?
What happen if you define the second argument as EntityType?
$builder->add('name')
->add('subFamily', EntityType::class)
I did remove the the whole database and recreated it. I have not changed anything about Doctrine settings. I wonder if this is related to the version of Symfony, since I am using the 3.3
if I add`
$builder->add('name')
->add('subFamily', EntityType::class)```
then I get error The required option "class" is missing.
on the mentioned line of the following method
public function newAction(Request $resquest)
{
$form = $this->createForm(GenusFormType::class); <--
...
}
Oh, that error is my fault, you need to specify which class is related to.
$builder->add('subFamily', EntityType::class, array(
'class' => SubFamily::class,
...
));
There are other useful options you can define, if you want to know more, you can read this section of the documentation http://symfony.com/doc/current/reference/forms/types/entity.html
Cheers!
Thanks MolloKhan
The following actually solved the issue, But I wonder why would I need to do that and it worked without specifying the class in the video.
$builder->add('subFamily', EntityType::class, array(
'class' => SubFamily::class,
...
));
Yeah, it's strange, maybe the cache is messing up something? or, I'm not sure about this but you may need to have a setter for that field "setSubFamily()"
He Ryan,
BEcause of this clip I got a bit further with the fixtures load. However I now get the following error:
[Doctrine\DBAL\Exception\InvalidFieldNameException]
An exception occurred while executing 'INSERT INTO genus (name, species_count, fun_fact, is_published, first_dis
covered_at, sub_family_id) VALUES (?, ?, ?, ?, ?, ?)' with params ["Eumetopias", 807, "Recusandae asperiores acc
usamus nihil repellat vero omnis voluptates.", 1, "1854-01-29", 37]:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sub_family_id' in 'field list'
Do you know why this happens?
Yo Daan!
My answer on your other comment will address this too, fortunately :). When you copy the relationship code for the subFamily into your Genus entity, your migrations will suddenly want to generate a sub_family_id column. Sorry for sneaking that in!
Cheers!
He Ryan,
Thanks for your assistance. It helped alot. I think it had something to do with adding Assert\NotBlank().
the -vvv tip helped alot too!
Hey Boban,
Yes, nice tip! This is a new feature for PHP 5.5 and it's a very nice to have an autocomplete for FQCN.
Cheers!
Hello there, i just cant configure symfony to use moneytype with BRL and grouping... It knows its R$ (BRL) but needs to format inputed number as 000,000,000.00 but the correct is 000.000.000,00
how can i solve this? Thanks!!!
Hey Raphael!
Hmm, that's very interesting. The MoneyType is supposed to look up the number format by looking at the currency that you pass as an option. It's possible that the issue is because you don't have the "intl" PHP extension installed. Can you see if you see "intl" in the list, when you run this command?
php -m
This command displays the modules installed in your PHP :).
Cheers!
Hello Weaverryan!!! Thanks... i do not have it installed... i`ll provide and test... will post here when finishe...
I am binding my form to an entity that will return more than one row. When I look at the debug tool my entity query has a 'LIMIT 1' clause. How do I remove this?
Hey Moises Cano!
Can you post some of your code? I don't fully understand what you mean by "binding my form to an entity that will return more than one row"? If you want to edit a product, for example, you are editing just one product at a time. Are you trying to somehow edit more than one object on the same form?
Cheers!
I'm going to ask it a different way. Here is my FormType code.
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ExceptionFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('usrid')
->add('trcode')
->add('cola', NumberType::class,
['scale' => 2])
->add('colb', NumberType::class,
['scale' => 2]
)
->add('colc', NumberType::class,
['scale' => 2])
->add('cold')
->add('fringe', ChoiceType::class,
array(
'choices' => array(
'No' => 0,
'Yes' => 1
)
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Exception'
]);
}
public function getBlockPrefix()
{
return 'app_bundle_exception_form_type';
}
I want to fetch more than one row. When I look at the debug tool i see this sql.
SELECT
t0.usrid AS usrid_1,
t0.trcode AS trcode_2,
t0.cola AS cola_3,
t0.colb AS colb_4,
t0.colc AS colc_5,
t0.cold AS cold_6,
t0.dept AS dept_7,
t0.fringe AS fringe_8,
t0.seq AS seq_9,
t0.id AS id_10
FROM
exception t0
WHERE
t0.usrid = ?
LIMIT
1
How do i remove 'LIMIT 1' ?
Hey Moises,
Hm, I wonder how your exceptions() method looks like. Does it really return an array of entities instead of a single entity? Could you show its code? Btw, entity type has "multiple" option, probably you want to set it to "true":
$builder
->add('trcode', EntityType::class, [
'class' => ExceptionCode::class,
'multiple' => true,
'query_builder' => function (ExceptionRepository $repo) {
return $repo->exceptions();
}
])
Cheers!
Sorry about that. I should have taken that part out. I have it commented out because i'm not using it right now.
Super tutorials! Great thank you!
And I have a question...
I have a 2-3 Entities (tables in Database) and those entities are related one-to-many. I need 1 form (for ../admin/new) for populating data to database. I need 2-3 entities in one form. How can I do this? What is the best way?
I used this code it's works:
$product->setPrice($form->get('price')->getData());
$product->setModel($form->get('model')->getData());
$product->setDateCreated($form->get('dateCreated')->getData());
$description->setSmallDesc($form->get('smallDesc')->getData());
$description->setBigDesc($form->get('bigDesc')->getData());
But in $form = $this->createForm(DescriptionFormType::class, $product); i need more objects...for next work of code.
but it's not allowing to do like this:
$description = new Description;
$image = new Image;
$form = $this->createForm(DescriptionFormType::class, $product, $description, $image);
And I need to do this without any bundles.
Plese tell me what I need to do? Thank you. Sorry for bad English.
Hey Vasili,
I think I got what you mean, since your entities are related to each other like one-to-many, it's easy to do with sub-forms. You need to create a form for each entity you want to see in your final form. For example, you have 3 entities: Product, Description, and Image. So as I understand, Description and Image relate to Product like many-to-one, i.e. Product can have many Description and Image objects. Then you need to create forms for those entities, i.e. ProductForm, DescriptionForm, and ImageForm. So if your ProductForm is your final form, you need to include those 2 sub-forms to it, but using Collection type:
$productFormBuilder
->add('descriptions', CollectionType::class, [
'entry_type' => DescriptionType::class,
])
->add('images', CollectionType::class, [
'entry_type' => ImageType::class,
])
// ... other fields you need to see in ProductForm
;
Then you'll be able to do just:
$form = $this->createForm(ProductForm::class, $product);
And all the sub-forms also will be populated with data. Anyway, I hope you got the idea, CollectionType is something you need, see https://symfony.com/doc/current/reference/forms/types/collection.html
Also, see our screencast about it for an example: https://knpuniversity.com/screencast/collections/embedded-form-collection . And in general, this course has a lot of interesting information about working with collections: https://knpuniversity.com/screencast/collections
Cheers!
Thank for response! I saw links as you give...
Yes, in Entity: Description and Image are related to Product with many-to-one. I need 1 form with clear fields for filling this with my data from ...admin/new. This is 3 entities with many fields (producr->name, product->price, description->smallDescription, image->linkBigImage...and others) in one form. And I need populating this form manually.
$this
->add('descriptions', CollectionType::class, ['entry_type' =>DescriptionFormType::class]
where DescriptionFormType have...
$builder
->add('smallDesc', TextType::class, ['data_class' => Description::class])
->add('bigDesc', TextareaType::class ,['data_class' => Description::class])
doesn't work with next error:
<blockquote>
-Neither the property "descriptions" nor one of the methods "getDescriptions()", "descriptions()", "isDescriptions()", "hasDescriptions()", "__get()" exist and have public access in class "RevprodBundle\Entity\Description".
</blockquote>
But all getters and setters is in Entity...
Hey Vasili,
From the error I see Symfony can't find proper methods. Please, make sure you do "$this->add('descriptions', ...)" in ProductForm, and this form's data_class is set to "Product::class", not "Description::class". Because from error I see that Symfony trying to find those methods in "RevprodBundle\Entity\Description" entity which is incorrect if I understand you right. And the error makes sense because Description entity does not have getDescriptions() method, right? :)
Cheers!
Я вижу, вы русский знаете. Уже кучу времени потратил, но никак не могу решить эту задачу. У меня есть 3 эти сущности: Продукт, Картинки, Описание. И мне нужна одна форма, чтобы заполнить все это, просто форма с несколькими полями и кнопкой для загрузки картинок, это для страницы /new. Встраивание форм попробовал, что-то выдает только название (Products и image) без самих форм. Уже не знаю, что делать. Вроде простая задача, часто используется, а реализации нормальной нет( Может есть какой нормальный вариант?
->add('products', CollectionType::class, ['entry_type' => ProductFormType::class])
->add('image', CollectionType::class, ['entry_type' => ImageFormType::class])
Да и что делать, если в $this->createForm(ProductForm::class, $product) нужно передать несколько аргументов? Спасибо за помощь!
Добрый день,
Из нашей команды русский понимаю только я, поэтому для вопросов на английском у вас есть шанс получить ответ быстрее :)
Теперь вы меня запутали окончательно с этим примером, так как речь вроде шла о том что у вас Product относится к Image и Description как один-ко-многим, но из вашего примера я вижу что вы пытаетесь создать возможность редактировать сразу несколько Product а Image к ним вообще не относится. Или вы поменяли требования? Давайте пойдем по другому пути, можете показать вашу сущность Product с теми свойствами которые вы хотите видеть в форме но у вас не получается отобразить? И опишите как вы себе видите конечную форму, а я попробую помочь.
Что вы имеете ввиду что нужно передать несколько аргументов в $this->createForm(ProductForm::class, $product)? Симфони формы могут привязываются только на одну сущность, которая является главной. Все дочерние сущности должны привязываться автоматически если у вас правильно написанный form type, т.е. если у вас есть Product который связан как один-ко-многим к Image, то в createForm() вы просто передаете объект Product. Но прежде чем создать форму и передать в нее Product, вы можете модифицировать его, например, добавить в него несколько картинок, но все это зависит от ваших целей. Вот очень упрощенный пример:
$product->addImage(new Image());
$product->addImage(new Image());
$product->addImage(new Image());
$this->createForm(ProductForm::class, $product);
Т/е/ вы передаете объект Product сразу с 3-мя картинками, и если у вас есть коллекция картинок в форме - то вы должны будете увидеть отображение этих трех картинок в форме. Как видите, мне не нужно передавать в форму еще отдельно картинки так как они являются дочерними по отношению к Product.
Также, эта статья может быть полезна для вас: http://symfony.com/doc/curr... - там как раз идет речь о том как встраивать коллекции в формы. Кстати, для правильной реализации добавления / удаления нужно будет поработать с JavaScript: http://symfony.com/doc/curr... . Поэтому я рекомендую вам сначала сделать возможность редактирования уже существующей информации в БД, так будет проще начать и будет понятнее.
Удачи!
Спасибо за ответ!
На данном этапе я хочу создать форму для добавления новой записи, а не для редактирования. В форме много полей, поля группами принадлежат разным объектам. Допустим, заполняем продукт, его название, стоимость, дата производства, большое и малое описание и картинка к нему или несколько картинок. Т.е. форма относится к разным классам-сущностям. Отношения уже потом. Сейчас нужно всего лишь создать форму, чтобы потом в БД она разошлась по разным таблицам. Не нашел подробной инструкции как это сделать. Слышал про композитный класс, но не знаю как это сделать, да и кажется, что это лишнее... Спасибо Вам за помощь!
Добрый день,
Начинать с формы добавления будет немного сложнее чем с формы редактирования. Композитный класс скорее всего не нужен если есть главная сущность, а все остальные сущности являются дочерними, т/е/ связаны с главной сущностью по схеме один к одному, многие к одному или многие ко многим. Если же это ваш случай - супер, осталось определить главную сущность и создать дня нее форм тайп. В форм тайпе сначала пропустите поля которые являются отдельными сущностями, т/е/ создайте форму которая будет содержать только простые поля типа "input type=text" или "textarea", например где вы заполняете описание, стоимость, дату, и т/д/. После того как эта простая форма будет готова - добейтесь того чтобы ее отрендерить на странице, а после этого чтобы когда вы отправляете форму - обработайте ее так чтобы информация писалась в БД. Если все работает, дайте мне знать и после этого можно будет переходить на второй этап.
Кстати о формах, думаю будет полезным этот курс: https://knpuniversity.com/s... . Также есть https://knpuniversity.com/s... - где мы строим более сложные формы, по сути именно такие как вам надо. Думаю он должен автоматически ответить на большинство ваших вопросов, но рекомендую его только после "Symfony Forms: Build, Render & Conquer!".
Удачи!
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*", // v3.1.4
"doctrine/orm": "^2.5", // v2.7.2
"doctrine/doctrine-bundle": "^1.6", // 1.6.4
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
"symfony/swiftmailer-bundle": "^2.3", // v2.3.11
"symfony/monolog-bundle": "^2.8", // 2.11.1
"symfony/polyfill-apcu": "^1.0", // v1.2.0
"sensio/distribution-bundle": "^5.0", // v5.0.22
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.4", // 1.4.2
"doctrine/doctrine-migrations-bundle": "^1.1" // 1.1.1
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.0.7
"symfony/phpunit-bridge": "^3.0", // v3.1.3
"nelmio/alice": "^2.1", // 2.1.4
"doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
}
}
Awesome tutorials, well worth the subscription!
What can I do against this error?
"Entities passed to the choice field must be managed. Maybe persist them in the entity manager?"