Buy
Buy

Adding the ManyToOne Relation

Hmm. We want each Article to have many Comments... and we want each Comment to belong to one Article. Forget about Doctrine for a minute: let's think about how this should look in the database. Because each Comment should belong to one article, this means that the comment table needs an article_id column.

So far, in order to add a new column to a table, we add a new property to the corresponding entity. And, at first, adding a relationship column is no different: we need a new property on Comment.

Generating the Relationship

And, just like before, when you want to add a new field to your entity, the easiest way is to use the generator. Run:

php bin/console make:entity

Type Comment so we can add the new field to it. But then, wait! This is a very important moment: it asks us for the new property's name. If you think that this should be something like articleId... that makes sense. But, surprise! It's wrong!

Instead, use article. I'll explain why soon. For the field type, we can use a "fake" option here called: relation: that will start a special wizard that will guide us through the relation setup process.

The first question is:

What class should this entity be related to?

Easy: Article. Now, it explains the four different types of relationships that exist in Doctrine: ManyToOne, OneToMany, ManyToMany and OneToOne. If you're not sure which relationship you need, you can read through the descriptions to find the one that fits best.

Check out the ManyToOne description:

Each comment relates to one Article

That sound perfect! And then:

Each Article can have many Comment objects

Brilliant! This is the relationship we need. In fact, it's the "king" of relationships: you'll probably create more ManyToOne relationships than any other.

Answer with: ManyToOne.

Now, it asks us if the article property on Comment is allowed to be null. Basically, it's asking us if it should be legal for a Comment to be saved to the database that is not related to an Article, so, with an article_id set to null. A Comment must have an article, so let's say no.

Generating the Other (Inverse) Side of the Relation

This next question is really important: do we want to add a new property to Article? Here's the deal: you can look at every relationship from two different sides. You could look at a Comment and ask for its one related Article. Or, you could look at an Article, and ask for its many related comments.

No matter what we answer here, we will be able to get or set the Article for a Comment object. But, if we want, the generator can also map the other side of the relationship. This is optional, but it means that we will be able to say $article->getComments() to get all of the Comments for an Article. There's no real downside to doing this, except having extra code if you don't need this convenience. But, this sounds pretty useful. In fact, we can use it to render the comments on the article page!

If this is making your head spin, don't worry! We'll talk more about this later. But most of the time, because it makes life easier, you will want to generate both sides of a relationship. So let's say yes.

Then, for the name of this new property in Article, use the default: comments.

Finally, it asks you about something called orphanRemoval. Say no here. This topic is a bit more advanced, and you probably don't need orphanRemoval unless you're doing something complex with Symfony form collections. Oh, and we can easily update our code later to add this.

And... it's done! Hit enter one more time to exit. We did it!

Looking at the Entities

Because I committed all of my changes before recording, I'll run:

git status

to see what this did. Cool! It updated both Article and Comment. Open the Comment class first:

... lines 1 - 10
class Comment
{
... lines 13 - 31
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Article", inversedBy="comments")
* @ORM\JoinColumn(nullable=false)
*/
private $article;
... lines 37 - 77
}

Awesome! It added a new property called article, but instead of the normal @ORM\Column, it used @ORM\ManyToOne, with some options that point to the Article class. Then, at the bottom, we have getter and setter methods like normal:

... lines 1 - 10
class Comment
{
... lines 13 - 66
public function getArticle(): ?Article
{
return $this->article;
}
public function setArticle(?Article $article): self
{
$this->article = $article;
return $this;
}
}

Now, check out the other side of the relationship, in Article entity. This has a new comments property:

... lines 1 - 13
class Article
{
... lines 16 - 60
/**
* @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="article")
*/
private $comments;
... lines 65 - 200
}

And, near the bottom, three new methods: getComments(), addComment() and removeComment():

... lines 1 - 5
use Doctrine\Common\Collections\Collection;
... lines 7 - 13
class Article
{
... lines 16 - 170
/**
* @return Collection|Comment[]
*/
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setArticle($this);
}
return $this;
}
public function removeComment(Comment $comment): self
{
if ($this->comments->contains($comment)) {
$this->comments->removeElement($comment);
// set the owning side to null (unless already changed)
if ($comment->getArticle() === $this) {
$comment->setArticle(null);
}
}
return $this;
}
}

You could also add a setComments() method: but addComment() and removeComment() are usually more convenient:

The ArrayCollection Object

Oh, and there's one little, annoying detail that I need to point out. Whenever you have a relationship that holds a collection of items - like how an Article will relate to a collection of comments, you need to add a __construct() method and initialize that property to a new ArrayCollection():

... lines 1 - 4
use Doctrine\Common\Collections\ArrayCollection;
... lines 6 - 13
class Article
{
... lines 16 - 65
public function __construct()
{
$this->comments = new ArrayCollection();
}
... lines 70 - 200
}

The generator took care of that for us. And, this looks scarier, or at least, more important than it really is. Even though the comments are set to an ArrayCollection object, I want you to think of that like a normal array. In fact, you can count, loop over, and pretty much treat the $comments property exactly like a normal array. The ArrayCollection is simply needed by Doctrine for internal reasons.

ManyToOne Versus OneToMany

Now, remember, we generated a ManyToOne relationship. We can see it inside Comment: the article property is a ManyToOne to Article. But, if you look at Article, huh. It has a OneToMany relationship back to Comment:

... lines 1 - 13
class Article
{
... lines 16 - 60
/**
* @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="article")
*/
private $comments;
... lines 65 - 200
}

This is a really important thing. In reality, ManyToOne and OneToMany do not represent two different types of relationships! Nope, they describe the same, one relationship, just viewed from different sides.

Generating the Migration

Enough talking! Let's finally generate the migration. Find your terminal and run:

php bin/console make:migration

Go back to your editor and open that new migration file. Woh! Awesome! The end-result is super simple: it adds a new article_id column to the comment table along with a foreign key constraint to the article's id column:

... lines 1 - 2
namespace DoctrineMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20180426185536 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE comment ADD article_id INT NOT NULL');
$this->addSql('ALTER TABLE comment ADD CONSTRAINT FK_9474526C7294869C FOREIGN KEY (article_id) REFERENCES article (id)');
$this->addSql('CREATE INDEX IDX_9474526C7294869C ON comment (article_id)');
}
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE comment DROP FOREIGN KEY FK_9474526C7294869C');
$this->addSql('DROP INDEX IDX_9474526C7294869C ON comment');
$this->addSql('ALTER TABLE comment DROP article_id');
}
}

So even though, in Comment, we called the property article:

... lines 1 - 10
class Comment
{
... lines 13 - 31
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Article", inversedBy="comments")
* @ORM\JoinColumn(nullable=false)
*/
private $article;
... lines 37 - 77
}

In the database, this creates an article_id column! Ultimately, the database looks exactly like we expected in the beginning! But in PHP, guess what? When we set this article property, we will set an entire Article object on it - not the Article's ID. More about that next.

The migration looks prefect. So find your terminal, and run it!

php bin/console doctrine:migrations:migrate

Ok, time to create a Comment object and learn how to relate it to an Article.

Leave a comment!

  • 2018-09-17 weaverryan

    Hey Radu Barbu!

    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:


    php bin/console doctrine:schema:update --dump-sql

    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:


    php bin/console doctrine:schema:drop --full-database
    php bin/console doctrine:migrations:migrate

    I hope this helps! Cheers!

  • 2018-09-17 Radu Barbu

    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?

  • 2018-07-13 Diego Aguiar

    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!

  • 2018-07-12 toporovvv

    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)?

  • 2018-07-12 weaverryan

    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!

  • 2018-07-11 toporovvv

    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.

  • 2018-07-11 weaverryan

    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!

  • 2018-07-11 toporovvv

    A bit strange for me:

     
    ALTER TABLE comment ADD article_id INT NOT NULL


    And then in Article removeComment method:

     
    public function removeComment(Comment $comment): self
    {
    if ($this->comments->contains($comment)) {
    $this->comments->removeElement($comment);
    // set the owning side to null (unless already changed)
    if ($comment->getArticle() === $this) {
    $comment->setArticle(null); //but the article_id is not nullable! EXPLODE HERE!
    }
    }

    return $this;
    }

  • 2018-07-05 weaverryan

    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!

  • 2018-07-03 Greg

    Search for "Please note interesting things" at https://github.com/doctrine...

  • 2018-07-03 weaverryan

    Hey Greg!

    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!

  • 2018-07-03 Greg

    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.

  • 2018-06-14 Victor Bocharsky

    Hey Doccos,

    I think because you wrote them so :) Maker bundle asks you how you would like to name your entity, and if you start it with a lowercase first later - it will create an entity with lowercase first latter.

    Cheers!

  • 2018-06-13 Doccos

    Thanks for the answer it Works, but why are they lowercase ?
    i created it with make:entity

  • 2018-06-13 Victor Bocharsky

    Hey Doccos,

    Looks like letter case in your entity names inconsistent, you have App\Entity\ForumForum entity but link to it with App\Entity\forumForum, i.e. first letter of entity is in lower case. Try to fix it first and then it should work - it should be "App\Entity\ForumForum" since we start entity classes with uppercase letter.

    Cheers!

  • 2018-06-13 Doccos

    Hello,

    i tried to create 2 Entitys with relations and now i get the error "The target-entity App\Entity\forumForum cannot be found in 'App\Entity\ForumTopics#forum'." when i call $entityManager->getRepository(ForumTopics::class)->findAll();

    ForumTopics entity: https://pastebin.com/HJFykhuG

    ForumForum entity: https://pastebin.com/xMceSZ4C

    where is the error ? :)

  • 2018-05-29 weaverryan

    Hey Peter!

    We won't touch on inheritance in this tutorial, unfortunately. It's a great system actually, but still, I don't use it that often (that might just be due to the types of projects I work on - I haven't needed it at all over the past few years.

    But, hopefully I can give you a few points :).

    1) First, ask your question if you actually *need* inheritance. In some cases, all you really need is some common properties. So, you use inheritance as a way to avoid duplication. But, you can also put these annotated properties into traits, and use those traits in all the unrelated entities.

    2) But, if you want to be able to, for example, "query for all vehicles" at the same time, and have this return an array/mixture of Buss, Car, Truck, etc, then you probably do want inheritance (and there are a few other similar reasons to do inheritance). The Doctrine inheritance system is pretty awesome, and always works more-or-less the same way: with a parent class and sub-classes. The decision you'll need to make is what "type" of Doctrine inheritance you want, which mostly just affects how the data is stored in the database. The "join table" is probably the most flexible, but inheritance does add complexity.

    I'll throw this on our tutorial idea list - could be a great, quick tutorial. But, if you have any questions, we're here!

    Cheers!

  • 2018-05-29 Peter

    Any chance we will touch inheritance and how this is solved/mapped into doctrine? Lets say vehicle entity as parent and bus,car,truck,bike as children? Each of these child entities have some uncommon properties? Also I would like to see an example where we have composite relationship/primary keys. I could propably google it but I still would like to see best practises and like your explanation Ryan.

  • 2018-05-09 Diego Aguiar

    Hey Matt Johnson

    Thank you for informing us about that sneaky typo. It is already fixed!

    Have a nice day :)

  • 2018-05-09 Matt Johnson

    Typo on:

    php bin/console make:enitty

    Should be
    php bin/console make:entity

  • 2018-02-13 weaverryan

    Hi @mehdimarchouk!

    Oh boy - it's very complex. I'm really not sure what to recommend :/. Your data structure is *quite* denormalized, and so things are becoming very complex - relational databases just don't do this kind of thing well. You could try to leverage the `json` field type in Doctrine, which would allow you to store whatever data you want inside 1 field. If you do that, make sure you set the server_version config to 5.7 (https://symfony.com/doc/cur... so that Doctrine uses the native JSON feature.

    I'm sorry I can't recommend more - this is really a complex, custom situation. My best advice is to try to keep it as simple as possible!

    Cheers!

  • 2018-02-13 Mehdi Marchouk

    Thank you for this great reply as usual !
    I think if have a lot of subcategories, I will come up with a lot of tables.
    Those are others explanations :
    This the whole structure :
    - Category can be 1=> an Object or 2=> an Animal (Dog, Cat, Other ....).
    - All animals have the same fields for simplicity.
    - Object can be 1.1.Clothes (T-shirt, Pants, Other ...) or 1.2.Jewelry (Ring, Bracelet, Other ....).
    - For objects, since I can have a lot of tables, I will use an easy solution: Omit the specific fields for subcategories and use just the common fields for all objects.
    - Object's fields are different from Animal's.
    This is an example of using that structure :
    - If I choose Animal , a form appears (choosing which animal and filling Animal fields)
    - If I choose Object or if after I select Jewelry , a form appears (choosing which Jewelry and filling Object fields ).
    So there are 3 levels for Object category ?? The implementation also will be changed because fields are in the parent category ?
    I am sorry but I am blocked on this part.
    Thank you !

  • 2018-02-12 weaverryan

    Hey @mehdimarchouk!

    Ah yes. This is not an easy problem so solve: in general, the data structure needed for ECommerce & categories is complex! That's part of the reason why something like Sylius exists: ECommerce built on top of Symfony. It may or may not be a good idea for you (it has a lot of features, which can be good or bad depending on your situation!).

    The Tree implementation is probably not needed, because you only have *2* levels of categories (unless I'm wrong). I mean, you have Category -> SubCategory.... NOT Category -> SubCategory -> SubSubCategory....

    Here's what I would do:

    1) Create a Category entity
    2) Create a SubCategory entity. Give this only the fields that are on all sub categories. So, material & type.
    3) Create a ManyToOne relationship from SubCategory to Category
    4) Use Doctrine's inheritance system (http://docs.doctrine-projec... to create a new entity for each *type* of SubCategory. For example, create RingSubCategory and make it extend SubCategory. Give this the "sex" field. Do the same thing for BraceletSubCategory: give it the field color. For the inheritance type, usually the "joined table" is the best idea.

    This setup will allow you to have a Category that relates to many SubCategory's of different *types*. I think it's what you need :).

    Cheers!

  • 2018-02-09 Mehdi Marchouk

    Hello,
    I have categories and sub categories with different fields for last sub category child. For example Jewelry category have 2 sub categories , a sub category Ring have these fields : material, type, color. a sub category Bracelet have
    these fields: material, type and sex. I want to design this in doctrine. I did a search and I found this bundle StofDoctrineExtensionsBundle
    using the Tree Doctrine Extension but Ii don't know how to handle those different fields since this Doctrine Extension work with the same
    fields for all categories and sub categories ?
    Can you help me? Thank you!

  • 2017-05-04 Victor Bocharsky

    Hey @maxii123 ,

    In this screencast Ryan wants to say that OneToOne relation is actually ManyToOne, i.e. technically it is, they have the same schema in the database. You can see it in examples of Doctrine docs: http://docs.doctrine-projec... . So just Doctrine helps you to control OneToOne relationship which is technically the same as ManyToOne in DB. Does it makes sense for you?

    Cheers!

  • 2017-05-03 maxii123

    I'm not sure the apparent dismissal of onetoone in this video is a good thing. It has certainly caused a few issues on a #irc help channel. Lets say I have an address table with a pointer to a country table. many addresses can point to the same country record. surely this is a one to one? OK I admit it. I'm confused.

  • 2016-11-30 Hakim Ch

    Thank you Victor !

  • 2016-11-30 Victor Bocharsky

    Hey Hakim,

    Yes, there's a Database normalization which has several normal forms. It's the first step on the way of database performance optimization.

    Cheers!

  • 2016-11-29 Hakim Ch

    You got a point about combining the tables!!! and thank for the extra :D
    Another question, there is a track about tables creation strategy to avoid performance issues ?

  • 2016-11-29 weaverryan

    Hey @hakimch!

    Yea, using OneToOne is fine :). I usually avoid it, because technically, you could just combine your Client and ClientInfo tables into one table. By separating them, you're causing yourself more complexity, because now you need to make sure you create a Client and ClientInfo object, and set the Client on the ClientInfo. This can be done well, but it's just easier to have one table (I realize having one big table can have performance drawbacks, so this is a tradeoff of complexity versus performance).

    Also, on a more philosophical level, a OneToOne is nothing more than a ManyToOne, where Doctrine creates a unique index on your foreign key (client_id) to prevent you from having more than one. That's not relevant to your question - just a fun thing to think about (and heck, even ManyToMany is just two ManyToOne relationships automated for you - we talk about that in the new https://knpuniversity.com/s... screencast).

    Thanks for the question!

  • 2016-11-29 Hakim Ch

    Hi Ryan,

    I have 2 tables Client, ClientInfo (wich referenced by client_id). the OneToOne relation, so how i can manage that if it not good to use the OneToOne relation ?

  • 2016-10-08 weaverryan

    Hi Yang!

    This is as good a spot as any :). A few things:

    1) It's subjective, but I'm not a huge fan of these "look-up" tables: tables that exist in your database, aren't really ever going to be dynamically updated, and just contain a very few, specific records. I actually like the setup you have in this situation: a normal string column. I use constants in my Post entity class for each valid "source" to keep a nice list of what is a valid source.

    2) But, let's assume that you *do* want to do this: it's still totally valid. And you *can* train the Doctrine Migrations to do this, it's just not automatic. Here's how I do this:

    A) Add the new entity and relationship (but don't remove the old source field yet). Generate a migration. This will contain *just* the code to add the new relationship/column.

    B) Next, we want to migrate the old data into the new location. There are 2 ways to do this, depending on whether or not you're smart enough (I often am not) to write a query that will move the data for you. If you can, you'll simply manually update the migration file generated in step (A), add a new $this->addSql(), and write your new manual query there. This would need to insert the new source records and then update the foreign key column. That's a pretty tricky query (inserting and updating all at once). I don't think that you can insert with one addSql() line, then query for and reference those new columns in a second addSql(), because it's all done in a transaction and so the new records aren't available yet. That's what makes it tricky.

    So if you can't write a big query to do this, then you have, actually, two more options :p. The one I typically do is to create a temporary, custom console command. Then, I will deploy, run the migration from step (A), then run this custom console command, which moves the data. Then on a future deploy, I'll generate and run the migration from step (C). The advantage here is that you have access to the container, entity manager, etc. A different, but similar approach is to get access to and use the container directly inside the migration itself (http://symfony.com/doc/curr.... I often do a console command instead, because it's much easier to handle things if this data migration fails, which is quite possible if you have a big data set (i.e. you could run out of memory). That's why I add a custom console command, and often make my code smart enough to continue where I left-off, in case the command failed in the middle.

    Phew!

    C) Finally, you'll remove the source column and generate a new migration. Depending on which strategy you use for part (B), you'll either do this at the same time as the other changes, or you'll need to do this in the future, after you deploy and migrate the data, so that the field is still there while you transfer the data.

    So, great question! This isn't something that comes up *all* that often, but it does happen (maybe a few times a year for the KnpU site). I try to write the query if I can, but if I need a little more logic and access to the container, I prefer a console command.

    Cheers!

  • 2016-10-07 Yang Liu

    Hi Ryan,

    I can't find the exact tutorial part for my question, so I try to post in here. For example, I have my Entity Post, in which there is the column "source", which would be facebook, twitter, whatever.... In the current state, its just a simple string. easy...
    But when I think of the future, there might be other new sources coming and it would be better when I create a new Entity, for example, Source, with an id and a name. and the id column will get the OneToMany-Relation to the source column in the Post-Entity. (I can recall somewhere in your symfony tutorial, you change the column "subfamily" of the genus and used a new Entity SubFamily instead, did you just recreate both Entities?).
    Thing is, since my Post-table is pretty big now, I can't just recreate both tables. And manually, I would first create a new source table, then add a new column source_id in Post-tabel, find out which id the sources has and update the source_id column, then remove the old source column. This will really suck when I need to do this every time on a different mashine.
    So my question is: Can I do this with Doctrine Migrations, when I already have an existing Entity? How can I "teach" Doctrine Migrations to replace the string in the old Post-table with the correct id from the new Entity?

  • 2016-06-14 JLChafardet

    I cant believe it! wow

    @ORM\ManyToOne(targetEntity="EntityName") <- SERIOUSLY?????? what have I done this past years? oh gawd, gimme my time back.

    ..... i want to go cry in a corner for a long while

  • 2016-06-14 weaverryan

    Yo!

    Yep, this is a perfect case for OneToOne. I dismiss OneToOne here, because OneToOne is really the same in the database as a ManyToOne, except that Doctrine makes user_id on the profile table unique, to prevent you from creating multiple. I want people to focus on the big two: ManyToOne and ManyToMany. Also, sometimes, OneToOne can give you more work. In this example, you *could* simply just put all the field on Profile onto User, and eliminate the complexity. Of course, then the User table becomes bigger and bigger, so splitting this into a OneToOne situation is legitimate (but sometimes I see people over-doing this and adding complexity for no benefit).

    So yes, you're in find shape :)

  • 2016-06-14 the_nuts

    Hi,

    I have an Entity User (with id, username, email, is_active, and other most used parameters)
    and another entity Profile (with personal info such as first and last name, address, etc... which are rarely used in the application)
    The PK ot the table profiles should be user_id, with users.id as FK.

    Can't I use OneToOne in this case?

  • 2016-05-31 weaverryan

    Hey Dan!

    Wow, you have a *very* good attention for detail! The truth is that nothing has changed - OneToMany still exists. In truth, you only *need* ManyToOne and ManyToMany. OneToMany is an optional way to look at a ManyToOne relationship. So really, ManyToOne and OneToMany are the *same* relationship, just looked to from different sides. So, I like to tell people initially just to worry about ManyToOne and ManyToMany. Later, we will learn about OneToMany, but it isn't really a true, new relationship type.

    Also, there is another - OneToOne. But again, this is *really* just a ManyToOne (it looks the same in the database), but Doctrine helps you to guarantee that you only link one object to one other object. There is limited use for this relationship in my opinion, so I save it for later :).

    Short answer: there is no difference! Just me simplifying how we explain this.

    Cheers!

  • 2016-05-27 Dan Costinel

    Hey Ryan,

    I'm having the old video, the one presented by Leanna, in which she says there are 3 (three) types of relationships: ManyToOne, ManyToMany and OneToMany. I know her version of Symfony, back then, was 2.4, and now, you are presenting this tutorial for Symfony 3, with just 2 (two) types of relationships: ManyToOne and ManyToMany.

    My question: the difference between the number of relationships is because of the Symfony different versions?

    Thank you.

  • 2016-03-23 weaverryan

    Hopefully this week - but definitely by next week :)

  • 2016-03-23 Andrew Grudin

    When?