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!
07.
ManyToMany: The Inverse Side of the Relationship
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
}
}
17 Comments
Hi!
I don't really know what is happening but I am having a problem with the inverse side of the relationship. I have categories and products like below. The problem is that it works when I save products in a category but not the inverse. I tried in my controller to $em->flush() without a parameter but it tells me:
<blockquote>A new entity was found through the relationship 'AppBundle\Entity\Product#categories' that was not configured to cascade persist operations for entity:
AppBundle\Entity\Category@00000000565496d3000000017d6c6077. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'AppBundle\Entity\Category#__toString()' to get a clue".
</blockquote>
and
Let me know if you need more details to help me to solve this problem.
Thanks loads guys!
James
Hey James,
Looks like you need to call persist() on Category entity which you add to collection. Don't forget that Doctrine requires calling persist() on new entities before calling flush().
Cheers!
Thanks for the fast reply! You guys are awesome!
I did as you said so I am updating the products and because I keep both side synced, I am also updating the categories. So I tried to persist products then persist categories then flush but I still get the following error:
A new entity was
found through the relationship 'AppBundle\Entity\Product#categories'
that was not configured to cascade persist operations for entity:
AppBundle\Entity\Category@000000006d8a552300000001007fe7fa. To solve
this issue: Either explicitly call EntityManager#persist() on this
unknown entity or configure cascade persist this association in the
mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot
find out which entity causes the problem implement
'AppBundle\Entity\Category#__toString()' to get a clue.
Here is my code in the controller:
if ($formCategory->isSubmitted() && $formCategory->isValid()) {
// Save category changes
$category->setName($formCategory['name']->getData());
$category->setSub($formCategory['sub']->getData());
$category->setSlug($formCategory['slug']->getData());
$category->setMetaTitle($formCategory['metaTitle']->getData());
$category->setMetaKeywords($formCategory['metaKeywords']->getData());
$category->setMetaDescription($formCategory['metaDescription']->getData());
$category->setDescription($formCategory['description']->getData());
if ($formCategory['image']->getData()){
$imageSaver = new ImageService();
$imageName = $imageSaver->imageSaveAction(
$formCategory['image']->getData(),
$formCategory['name']->getData(),
$this->getParameter('images_directory')
);
$category->setImageName($imageName);
}
foreach ($category->getProducts() as $product) {
$category->removeProduct($product);
}
if (count($formCategory['products']->getData())){
foreach ($formCategory['products']->getData() as $product) {
$category->addProduct($product);
$em->persist($product);
}
}
$em->persist($category);
$em->flush();
$this->addFlash('success', 'Category updated');
return $this->redirectToRoute('categories_view', array('id' => $category->getId()));
}
Hey James Davison
Have you tried configuring "cascade" on persist? or you have a special reason to don't do it?
Another question, why are you removing all products from the category?
Thanks for the tip Diego! Added cascade and it does the trick. If I don't remove all products from category first then if I just delete products from the category it does not work. Maybe do you know of a quick way to identify the products which are not present anymore which need to be deleted; something to check the difference.
That's great!
I need to know a bit more about the relationship between category and product, can you have products without a category?
Hi! Thanks for the quick answer,
it is a many to many and products or categories can be alone.
The entities code is in my first message.
Thanks again!
If you dump `$category->getProducts()` and `$formCategory['products']->getData()`
Are there any differences?
Do you have this code in any public repository? I would like to check it in more detail
Let me add you as a collaborator on Github if this is alright with you.
sure no problem, find me as Larzuk91
I have sent you an invite.
Thanks again
Hey James, I could see your invitation, but for some reason I cannot see your organization into my list =/
What's the name of your org/repo?
I seem to get a problem with my self referenced many to many relation in between products.
I changed the relation to a many to many unidirectional which works on the frontend but do not know how to incorporated to the form to add or delete related products to a product.
The error coming up is:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
https://github.com/connectj...
Just sent you another message on my github, the related products don't seem to work when passing the object to the form. Could you help me please?
Hi,
How would you approach ManyToMany relationship on the same entity. For example, if i am having entity Course and would like to have field represent the prerequisites courses of that Course which are from the same entity? what is the best way to implement this?
Thank you, much appreciated.
Hey Mohammad Althayabeh
I can think in two options, but to know which one is better for you, deppends on how are you planning to work with your objects
1) set a self referenced ManyToMany relationship (is like you said), you can get a better idea of how to achieve it here: http://docs.doctrine-projec... but I don't think you need to make it bidirectional
2) Create a new entity called something like `PrerequisiteCourseGroup` which will hold the Course and a list of (another new entity) `PrerequesiteCourse`, this entity will only have the reference of a Course (the prerequesite course)
So, in this case, given a Course, you can query for a PrerequisiteCourseGroup object and then ask him to give you the list of all prerequisite courses
Second approach is kind of confusing but it's nice if you don't want to alter your current course schema
Cheers!
"Houston: no signs of life"
Start the conversation!