Chapters
19 Chapters
|
2:14:20
|
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!
02.
Adding the ManyToOne Relation
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!
The course is built on Symfony 4, but the principles still apply perfectly to Symfony 5 - not a lot has changed in the world of relations!
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/doctrine-bundle": "^1.6.10", // 1.10.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
"knplabs/knp-paginator-bundle": "^2.7", // v2.7.2
"knplabs/knp-time-bundle": "^1.8", // 1.8.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"sensio/framework-extra-bundle": "^5.1", // v5.1.4
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.0.4
"symfony/console": "^4.0", // v4.0.14
"symfony/flex": "^1.0", // v1.21.6
"symfony/framework-bundle": "^4.0", // v4.0.14
"symfony/lts": "^4@dev", // dev-master
"symfony/twig-bundle": "^4.0", // v4.0.4
"symfony/web-server-bundle": "^4.0", // v4.0.4
"symfony/yaml": "^4.0", // v4.0.14
"twig/extensions": "^1.5" // v1.5.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
"easycorp/easy-log-handler": "^1.0.2", // v1.0.4
"fzaninotto/faker": "^1.7", // v1.7.1
"symfony/debug-bundle": "^3.3|^4.0", // v4.0.4
"symfony/dotenv": "^4.0", // v4.0.14
"symfony/maker-bundle": "^1.0", // v1.4.0
"symfony/monolog-bundle": "^3.0", // v3.1.2
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.0.4
"symfony/stopwatch": "^3.3|^4.0", // v4.0.4
"symfony/var-dumper": "^3.3|^4.0", // v4.0.4
"symfony/web-profiler-bundle": "^3.3|^4.0" // v4.0.4
}
}
42 Comments
Hi SymfonyCasts,
I would like to learn more about "orphanRemoval" topic such as automatically remove orphaned records. If you can please point me to documentation or tutorial.
Thank you!
Dung.
Hey Dung,
Did you try our cool search on SymfonyCasts? :) It might help a lot with searching some info about this and other things, e.g. see https://symfonycasts.com/se... - we mention "orphanRemoval" feature in a few screencasts.
I hope this helps! If no, please, we would like to hear your feedback what's not covered on your opinion and we will try to cover missing pieces in the future screencasts.
Cheers!
Thanks Victor as usual, just tried it and like it :), used google search for SymfonyCasts before knowing this availability. Cheers!
Hey Dung,
Thank you for your feedback about our search feature! Great you like it :) And recently we allow searching in specific course only when you're on a course page - this helps to make search results more relevant and specific.
Cheers!
"orphanRemoval" tutorial of this search result https://disq.us/url?url=htt... you gave is what I was looking for. I have no suggestion, it's already good :). Thanks!
Hey Dung,
Perfect! And thank you for your feedback about that topic! We're really happy to know it's clearly described for you there :)
Cheers!
I have no column article_id
when i localhost/phpmyadmin there is no column commentId help plz any wrong entity class
Hey @Himanshu,
That makes sense, because you don't have the $article project in your entity, do you? See this code block: https://symfonycasts.com/screencast/symfony4-doctrine-relations/many-to-one-relation#codeblock-42c3eba0fb - please, rewatch this video to understand how to add it.
Cheers!
Hi !!!, I have the following doubt, when I have several ManytoOne entities (each one calls another) is there a way to know in the controller of the child who is the actualy parent? Maybe I'm confuse, but y must send the parent entity in all functions of the controller (CRUD) for not missing it and is so anoing!
for example:
Hey Battle,
Fairly speaking, I'm not completely understand your example and what you're trying to do, but I think I can give you some hints on it. First of all, there's no way to know the parent entity unless you have getParent() method in your entities and so you can know the parent entity by calling it:
$entity->getParent(). If you're talking about nested objects, like Category entity and each main category may have sub-categories, that in turn may have sub-categories and so on... you can call that $category->getParent() in a while loop, something like:
Or, depends on your needs, but you can also write a custom method in an entity repository that will join some tables (or whatever crazy business login you need) and will try to find the parent for you. With this, you will only need to call a single method in the controller passing the entity parent of what you want to find.
Also, you can take a look at StofDoctrineExtensionsBundle or KnpLabsDoctrineBehaviors bundle that have so called "Tree" behaviour with some useful functions.
I hope this helps!
Cheers!
Yeaaa...I think tree is the solution. There is a course who talk about it?
Thanks!!!
Hey Battle,
Great! I'm happy it was useful for you :) Unfortunately, no course about Tree behaviour yet, only Sluggable/Timestampable were covered from that bundles on SymfonyCasts IIRC, you can search for it if needed. And yeah, it's kind of complex task... but bundle's docs should cover how to start using it, so check them first. Also, I bet you can find some examples on the internet as well.
Cheers!
How does one update a OneToOne relation when existing relations exists ? ex ( User && UserInfo )
Hey Cybernet2u,
Here's the explanation how it works: https://symfonycasts.com/sc...
I hope this helps.
Cheers!
maybe someone will have the time to help me out :D
Symfony - Updating OneToOne doctrine relation
Hey Ad F. !
I see your question! Can you post a bit more of the code? Specifically: what does the form (or forms) look like? It appears like you may have set the
companyCoverPhotofield on your form to aFileTypein your form. That causes a mismatch: the submitted value will be an UploadedFile object, but thecompanyCoverPhotoproperty on User should aCoverPhotoobject. You'll either want to (A) create a separateCoverPhotoFormTypethat you use as the "type" for yourcompanyCoverPhotofield on the main form or (B) mark thecompanyCoverPhotofield asmapped => falseand then use that value in your controller (much like you are already) to (if necessary) create theCoverPhotoobject and set it onUserand then update whatever filename field you need to on it.Let me know if that helps!
Cheers!
thanks, i know what it is, can't figure out how to make doctrine is trying to update a row , not create a new one
Hey Cybernet2u,
Could you explain a bit more? :) Do you have an issue with OneToOne relation? What's the issue exactly?
Cheers!
I have an embedded form and I followed this tutorial on saving related entities, i have a typical OneToOne relationship 1 user <-> 1 profile, the page says treat like a oneToMany relationship, however, when persisting, I have the message "Argument must be of type array", object given, does it mean that despite OneToOne relationship, my getter for the profile property in User class must return an ArrayCollection? The exception is in the file UnitOfWork.php of Doctrine.
Hey Benoit L.
Can you double-check that your relationship is indeed a OneToOne? Probably clearing the cache and updating the Database schema may help
It's a good idea to treat a OneToOne as if it were a OneToMany but of course there are implementation details (like this one) where you have to know that you are working with a OneToOne relationship
Cheers!
Hello, the problem was in the getter which was returning an int, I changed it to return an object instead. That solved the problem.
Hi to everybody!
Just wonder:
like
@ORM\....
(like:
`manyToOne:
)
Why you use the 1st way?) What are the advantages of one way over another?
PS. Some time the way with .orm.yml - files seems easy to store all configuration on one place.
Thanks in advance!
Hey Igor P.
Good questions :)
It's a common practice to use annotations to handle your metadata in Symfony but of course it depends. If you are developing a third party bundle, then, it's better to use an xml file for it, because it's easier to override and it doesn't depend of any external libraries in order to parse it. An advantage of using annotations is that you have all in one place (code & metadata)
Cheers!
So, I downloaded the course code and when I
composer installI get this:[ErrorException]
Declaration of Symfony\Flex\ParallelDownloader::getRemoteContents($originUrl, $fileUrl, $context) should be compatible with Composer\Util\RemoteFilesystem::getRemoteContents($originUrl, $fileUrl, $context, ?array &$responseHeaders = NULL)
Hey odds!
Hmm, sorry about that! This is caused by an out-of-date Flex version... but if you download the course code, we've already included an up-to-date Flex version inside (I just double-checked again). Are you downloading the course code for this (the Doctrine Relations) tutorial? What version of Composer do you see if you run
composer --version?Cheers!
Regarding migrations, I've noticed that at some point my migration files started to contain the actual change that I intended to make along with the queries from previous migrations. I am using the S4 generator and the following commands: make:entity -> make:migration -> doctrine:migrations:migrate. Am I doing something wrong?
Hey radone!
Really good question :). Yes, there is something wrong... but it's actually a little bit tricky. In order for this migration "workflow" to work correctly, before you make any entity changes, your database needs to be 100% in sync with your entities. If that's true, then, after you make changes to your entity, make:migration will only ever contain the new changes. So, in theory, as long as you are using the make:entity -> make:migration -> doctrine:migrations:migrate flow, you're good! Later, when you make more changes to your entity, when you run make:migration, the only difference between the database & your entity should be the new changes. And so, the migration should only contain the new changes.
However, things can get a little bit messy when you start working on a real project with branching. You may change to one branch, make some entity change, make the migration, then migrate. Then, when you move back to your main branch (assuming you haven't merged that branch yet), when you make changes to your entity and run make:entity, your migration will contain extra changes. Specifically, it will see the changes from the other branch and try to undo them. I don't know if this is the cause of what you're seeing, but it's an important thing to think about.
So, the key thing is this: before making entity changes & running make:migration, make sure that your database is in sync with your entities. Any easy way to check is to run this command:
Run this before making changes to your entity. If this dumps some SQL, then your database is out of date. You can fix that by re-running your migrations from scratc:
I hope this helps! Cheers!
weaverryan I think found the cause for this issue. It seems that all entity members containing the ORM annotation
nullable=truewill remain stuck and will appear over and over again when attempting to generate migrations. An example generated with make:entity is below:Hi, thanks for your reply!
Yes it helps. So in theory after running
php bin/console doctrine:migrations:migrate, if I executephp bin/console doctrine:schema:update --dump-sqlthis should return no other changes, correct? Unfortunately for me it returned the same queries I had, before runningphp bin/console doctrine:migrations:migratethe first time.I have also executed the
php bin/console doctrine:schema:drop --full-databasefollowed byphp bin/console doctrine:migrations:migrateand then executedphp bin/console doctrine:schema:update --dump-sqland I still get the changes (see below).The initial migration created the fields in the ALTER TABLE statements above just the same way (identical). It seems that those changes remained stuck somehow and they constantly appear as new for doctrine.
Am I doing something wrong?
Hey radone!
Hmm, ok - let's see if we can debug this! Two things
1) What database engine are you using - is it MySQL or something else? And what version?
2) Try running this:
What I'm doing here is fully dropping the database, then asking Doctrine to execute ALL of the queries needed to setup the database, and THEN asking it to dump any queries that are STILL needed. Now, in theory, that 3rd command makes no sense: I've just asked Doctrine to execute all the necessary queries, so there should always be ZERO queries returned by the 3rd command. But, I want to see if that is true in your case or not. This is slightly different than what you did because it's possible that there's a problem with your migrations (i.e. they are missing something - like they were missing the
DEFAULT NULLpart for some reason) and so then Doctrine is correct to try to "fix" the problem when you run--dump-sql. Anyways, tell me what you find!Cheers!
Hey weaverryan , sorry for the late response,
I am using a mariadb 10 docker image. I found a couple of articles regarding a few cases where Doctrine and the DB may look out of sync when in fact they are not.
https://github.com/doctrine...
https://github.com/doctrine...
and a potential fix which I haven't tried yet
https://marenkay.com/2018/0...
At this point I have reverted all nullable=true fields so I don't get a migartion diff all the time.
Hey radone!
Indeed - looks like a bug with Doctrine and Mariadb - thanks for sharing. I'd be interested if the last link / solution works. It's unfortunate, either way - Doctrine usually does this stuff *really* well.
Cheers!
A bit strange for me:
And then in Article removeComment method:
Hey toporovvv!
There may be a small bug here in the code generated by MakerBundle (I believe we have an issue about this on its repository already). But, I need to think about it. The question is, if you create a Comment with a required article_id... then what should happen when someone calls
$article->removeComment($comment)? Probably, it should explode, because this doesn't make any sense. The best solution in this case, would be to add orphanRemoval=true on the OneToMany annotation (we actually answered "no" to this question during generation, just to avoid talking about it). If you did this, then if a Comment is removed from its Article, that Comment is deleted. That's not always what you want with a ManyToOne/OneToMany relationship, but in this case, it probably is.Cheers!
Hi weaverryan . Thanks for reply.
Sorry, but I still don't understand exactly this situation. If we decided not to set up orphanRemoval for the comments field of the Article entity (it's inverse side of the association) and maker bundle does not check, that article_id is mandatory field - it will lead to sql-error in this case. I suppose, that orphanRemoval should be "yes" by default (in maker session) for a inverse side of this association. Or maker-generated code should remove comment anyway (even if developer didn't set orphanRemoval), because entity fields (and produced DB-scheme) should have a priority over the association code.
But I agree with you: generated entity code could not check all the schema nuances, especially after several controversial changes. And that's why there was a good practice of removing all the autogenerated code in the entity and recreation it by the doctrine command or IDE.
Hey toporovvv!
Hmm. It's just a matter of asking: what *is* the ideally generated code in this situation (without orphanRemoval)? IF MakeBundle is going to generate a removeComment() method, then what do you think this method should do? If it only removes the Comment from the Article, but does not change the Article in any way, then when you save, the Article will *still* be connected to the Comment. That's not what we want. What would you want the generated code to look like? This is totally something can change in MakerBundle - we've spent a lot of time thinking about the most *ideal* generated code. But, we need to find out what that perfect code looks like :).
Cheers!
Ah, it's a same problem of deleting from an inverse side of a relation. We've faced it here in Symfony 3 track:
https://knpuniversity.com/s...
https://knpuniversity.com/s...
https://knpuniversity.com/s...
https://knpuniversity.com/s...
From my point of view generated code could not save us from the error. And Maker Bundle should explicitly set orphanRemoval to true because of a DB-state. In that case remove method from an inverse side will work fine.
I know that this question is out of a course scope, but does anyone one know a reason for existing of owning and inverse side of Doctrine relations? Can we make an equal sides of association (to CRUD entities from both sides without additional actions)?
Hey toporovvv
The thing about owning & inverse side is because Doctrine needs to know which table holds the associated ID, so then it can generate the SQL query correctly.
Let's say that you have "Post" and "Image" entites, now, if you only know the "image_id" and you want to get its associated "Post" record, then, depending on the DB structure is how you will make the query, if the "Image" table holds the "post_id", then you just need a SELECT & WHERE, but if the "Post" table is who holds the "image_id", then you need a INNER JOIN
I hope anything I just said makes any sense to you :D
Cheers!
At around the 5:58 mark, you say we could add a "setComments" method. That implies replacing the ArrayCollection with a new one. The Doctrine docs say you cannot do this - the ArrayCollection is managed by Doctrine and you can't just wholesale replace it. That's why there's a add/remove methods generated, but not a set method.
I will supply a doc reference if you need.
Hey Greg B.!
Oh really? I actually didn't know this - I think I've replaced ArrayCollection objects many times in my projects... it sounds like I may have been getting a bit lucky :). And yes! I would love to see a doc reference.
Cheers!
Search for "Please note interesting things" at https://github.com/doctrine...
Awesome! Thanks for sharing! I've always done the adder/remover for convenience (and because it plays well with the form system). But, I honestly wasn't aware of this requirement :). I'm glad we made the make:entity command work like this out-of-the-box.
Cheers!
"Houston: no signs of life"
Start the conversation!