Chapters
28 Chapters
|
2:24:59
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
23.
Adding to a Collection: Cascade Persist
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
This course is built on Symfony 3, but most of the concepts apply just fine to newer versions of Symfony.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"symfony/symfony": "3.4.*", // v3.4.49
"doctrine/orm": "^2.5", // 2.7.5
"doctrine/doctrine-bundle": "^1.6", // 1.12.13
"doctrine/doctrine-cache-bundle": "^1.2", // 1.4.0
"symfony/swiftmailer-bundle": "^2.3", // v2.6.7
"symfony/monolog-bundle": "^2.8", // v2.12.1
"symfony/polyfill-apcu": "^1.0", // v1.23.0
"sensio/distribution-bundle": "^5.0", // v5.0.25
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.29
"incenteev/composer-parameter-handler": "^2.0", // v2.1.4
"composer/package-versions-deprecated": "^1.11", // 1.11.99.4
"knplabs/knp-markdown-bundle": "^1.4", // 1.9.0
"doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.2
"stof/doctrine-extensions-bundle": "^1.2" // v1.3.0
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.1.7
"symfony/phpunit-bridge": "^3.0", // v3.4.47
"nelmio/alice": "^2.1", // v2.3.6
"doctrine/doctrine-fixtures-bundle": "^2.3" // v2.4.1
}
}
10 Comments
Hello super person,
So in my project one product can have many pictures with titles and descriptions. And I'm able to get the remover method to work.
BUT it seems that I can't get the adder to work. if I dump $form->getData(); it seems that everything I add gets ignored. While the multiple pictures I manually added in the database doesn't get ignored, and I can edit them in the form. In "inspect element" in the HTML form. I can see that embedded forms gets the necessary [0], [1] etc in the name, but it isn't visible when I post.
Any ideas what I accidentally missed?
Hey Vince,
Hm, if you don't see added elements in POST request on the server - check the name attribute of added HTML elements. Is it exactly the same as manually added one? The difference should be only with the numbers, i.e. [0], [1], etc. You probably just make a misprint in the field name.
Also I suppose you use collection type for it, so please, double check that you have an "allow_add" => true, option.
And the last but not least, I think you use some JS code to add more pictures in the form. Do you use jQuery or other library / JS framework for it? Are you sure that your code writes directly to the DOM (not virtual DOM)?
Cheers!
Hey, I fixed it by placing the form_start at the beginning and form_end at the end of the file
Hello, I'm wondering if I could submit forms inside a collection separately? I have very long form collection with buttons to save each subform (Basically filling and validating the form at once would be difficult). So clicking the button suppose to only submit corresponding subform, but it submits whole collection.
`<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Address;
use AppBundle\Entity\Applicant;
use AppBundle\Entity\Company;
use AppBundle\Entity\Director;
use AppBundle\Entity\User;
use AppBundle\Form\UserType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
/**
*
*/
class UserController extends Controller
{
}`
Hey Marcin,
HTML does not allow you to embed form inside other form, it means that you can't have sub-forms on the HTML layout layer. So, to implement what you want I think you either need a separate form for each collection you want to save separately, or use one big form for all your collections. If you don't need an ability to send the whole big form with all collections - I think you can go with the 1st option. Otherwise, choose the 2nd option and take a look at form events: https://symfonycasts.com/sc... .
Cheers!
Hello,
I have a problem with the addGenusScientist and removeGenusScientist methods. In my application, I use checkboxes to set or remove entries to or from the mapping table (I call it genusScientist table here for better understanding). When adding, the idea is, that I call addGenusScientist in genus, pass it a genusScientist object where only the user is set. In my opinion, this doesn't work correctly with the current implementation:
I have 3 problems with that:
the setGenus line should be the first action in the method, otherwise contains will never return true, even if the combination of genus and user already exists.
contains apparently only then finds the entry in the collection, when ALL fields in $genusScientist are set exactly set as in the matching object in $this->genusScientists, i.e. not only user and genus have to be set, but also id and yearsStudies. If not, contains will not find them and I will have duplicate entries in my genusScientist table.
the same problem with contains happens in the removeGenusScientist method. Unless I fetched the genusScientist object from the database (i.e. all fields are set) before passing to the removeGenusScientist, contains will never find it. Even worse, the removeElement will then not work.
In my code, I implemented my own contains method, which only searches for the keys (genus and user) in this "mapping table with additional fields". But this feels strange, since the way it is implemented here can also be found on other examples on the internet.
Did I misunderstand the goal of the if-statements in add-/removeGenusScientists or is there really a bug in this code?
Hey Luc,
As for me, I agree with you, I think setGenus() method should be called first, before any if statement in addGenusScientist() / removeGenusScientist() and it makes perfect sense for me. This will fix some potential problems like this workflow:
1. $this->addGenusScientists()->add($genusScientist); // somewhere in the code we add an object to the collection manually but don't set owning side! And then further...
2. ->addGenusScientist($genusScientist); // So the object is already in the collection, BUT if we call this method - we'll ignore setting the owning side because contains() return true now.
Yes, it looks like a developer mistake, but we can cover it with calling setGenus() in the first place in both addGenusScientist() / removeGenusScientist().
What about contains() - we're operating objects, and since this method uses === in http://www.doctrine-project... - we don't have extra checks to validate that each field is matched. If we have another object - this check will fail, if we have the same object - no matter whether its fields are different or no, because we have exactly the same object, and if some fields were changed, Doctrine will do everything to store those fields in the DB on the next flush().
Cheers!
Hey there
My guts are telling me that you may forgotten to setup the inverse side of the relationship. Can you double check that?
Cheers!
Hmm, interesting. My second thought is that you didn't add the `cascade={"persist"}` to the property, but if you did then I would have to check your code so I can tell what's wrong. Maybe you could upload it to Github?
Or just take some screenshots to your entities and controller's action
Hmm, your relationships looks good to me, probably the error comes from processing the form submit. Try dumping your objects throughout the process so you can gather more information of how your objects are being built. You would have to call persist directly to "Bestelorder" and "Artikel"
"Houston: no signs of life"
Start the conversation!