The lessons are going hard already for me, these are the concepts I have never reached while learning PHP. Thanks a lot for not missing anything in your way to make us great.
Great video as always, thank you. Note: EntityManager::create() is deprecated We can use : $entityManager = new EntityManager( DriverManager::getConnection($params), ORMSetup::createAttributeMetadataConfiguration([ __DIR__ . '/Entity', ]) );
At timestamp 20:31, when the invoice item were displayed, i see there is invoice_id field has the id of the invoice just created. The question is, how did the value get inserted when we did not set this value at addItem() method?
Perfect video! Thank you so much for this hard work! The presentation is really cool! Always wanted to share the knowledge in same style!! Always have problems with this associations... Often have cases and problems in them to manage and map entities, when I have three linked entities like: Restaurant (OneToMany unidirectional) -> RestaurantPaymentType[] (OneToOne? unidirectional) -> PaymentType And the middle one have additional attributes, like ordering, DeliveryType (a enum class) Other example: Restaurant -> RestaurantProductCategory (has ordering, active flag) -> ProductCategory and in UI, you can choose, which Restaurant have which ProductCategories. (multi-select dropdown) The hardest part for me, is when I trying to figure out how to solve these relations updating. Creation is simple, as in your video, but when I trying to update, inverse side items (add/remove) - I have troubles and error. Either have too complex saving code, or have DB Errors for duplicating unique indexes or PK (One restaurant have only one payment type for one delivery type, so you can't add multiple same payment types for delivery and pickup real life methods) Some of my friends tell me about using removeOrphans attribute, to tell to Doctrine, that inverse side entity I want to remove - is only used for this one owning entity, and no one else referenced to it. So I really need to understand this case - how to organize proper mapping and saving (update inverse side entities - add/remove/[update]). I have existed PaymentTypes (online payment, cash, bank card) - entity in DB. 1) When I'm saving new Restaurant - I created an RestaurantPaymentType entities (in loop), link them to PaymentTypes and Restaurant, adding ordering and some other attributes. All saved correctly. 2) When I'm updating available restaurant payment types, say removed/or added one, then I need to realize, the diff between already existed entities, and new added/removed. Do I need to do this all manually (calculate diff, have multiple arrays - whta to add, what to remove, and exclude existed items), or I can somehow work only with ArrayCollection state, and sync them to DB state? 3) When I'm removing existed Restaurant, I can just use cascade operations, to delete only RestaurantPaymentType, but not PaymentType entity (just relation entity with additional fields). Well this also work correctly. Mainly have troubles with case number 2. I have a lot of pain doing this. And really need help from those, who understand all the process of managing mapped entities. (sorry if my English is bad) Really glad to found this helpful video and channel. Like Doctrine so much, but really need to understand how it works. Thank you in advance, if you reached this part of comment! :)
Thank you. It's a bit hard to help without seeing the code, I don't exactly understand the question or the problem, maybe if you showed me some part of code I could understand it better. You can ping me on Twitter.
In the Invoice example, do you need to have a reference to the Invoice in the Item class? I wouldn't want it in there since it's not needed; the Invoice is the aggregate root, so that's the object that gets passed around and is worked with, NOT the Item. You get to the Items through the root Invoice object. So can you just have the 1:m set up in the Invoice? Or would I have to do some custom mapping somewhere if I wanted it that way, such as in the save and find methods of the repository?
At 20:34, why in my invoice_items table, data for example: 'item 1' got id of 3 and item 2 got id of 2 and item 3 got id of 1, and item 3 is in first row, item 2 in second row and item 1 in third row, why is that , sir ?
It's auto increment id so u won't get exact same ids as I got on my video. If you've deleted some previous rows the id still gets incremented next time you insert
but why things got inserted in reverse order, ids ( primary key ids are ok ), but datas are not inserted in the way it's seen in the array, because in array the first item is item1 so I should see item1 inserted at top row in database, but I see it in bottom row, why ?
Wow, this was a bit more complex. Would take getting used to. But like you said practice and use will really help me get familiar. Never the less it was so much fun. I don't know where I would have learnt this... Gio, thank you
Hey, the $items property is typified with `Collection` class. However, we are instantiating it with `ArrayCollection` class. Is it the case of Contravariance when we typehint property with more general type?
How does the One-to-Many work when there are many tables linking back to a single table? For instance, it is common to see a table of country codes and/or state codes to be used in an application. The country codes and state codes are used many times with different displays, emails, etc. Even in this example there might not be that many tables that link but there might be more. Also, I am curious how that would apply to when a 'plug-in' type would be used. Is it possible for the entity object representing the table of country codes to know about the plug-in without changing the core of the application?
One-to-Many is a relationship between tables or entities, its not about how many times you display it or in how many places you use it. It's about how many transaction records in database table belong to a category via category_id column which references to categories table. In your example, countries could be a table that stores country code as well as some other information, you then could have another table called states which stores state code & other state related information but it also stores country id or country code which references to the country record in the countries table. I'm not sure what you mean by "plug-in" though.
Interesting, when you did the remove Invoice entity I noticed it was already removing the related InvoiceItems already, cascade on remove is the default behaviour it seems. Neat.
Great, I understood to use both dbal and orm but orm also have dbal functions so do i really need to use dbal? Or In which cases I should use dbal and orm
Up to timestamp 17:29, it was a lot to consume. From what i see is that we are doing so much thinking, remembering, understanding and coding just to get what we could do simply by using PDO. I am a business solution developer and i need to get solutions out to the users quickly. Doing all these codes, i estimate it would take 3 times more time, effort, documentation and team understanding (for later support). Too much intertwining which would make debugging so complex a nightmare for a third person (support unit). Perhaps all this knowledge would serve best to people who want to develop some sort of custom frameworks similar (Laravel, Codeigniter etc.). I am not saying its wrong but definitely say it should only be moderately used for business solution development. This is just my feeling up to this point. Perhaps this may change when we do the P series in the course. Definitely a great eye-opener on what PHP can do and realized that we should never compare PHP with the likes of Js frameworks.
Sure you can do a lot with just PDO, however ORMs help by alot and actually make developing apps much easier and faster. Symfony uses doctrine & a lot of enterprise level apps use it. Laravel has eloquent which is also ORM and plenty of startups as well as enterprise level apps use it. To me it's faster to whip out a working solution with an ORM than without it. But that can be different for everyone, if plain PDO works for you then stick with it, it also depends on the size of the application. For small apps ORM might be overkill
@@ProgramWithGio Agreed. We develope apps in small bits. Mostly headless cms, batch jobs and apis supporting our back-end CRM and transaction systems. Front-end, we are now strategizing on Vuejs and Alpinejs (looking into Astro Build). If i have to create a large app, i might as well stick to Codeigniter 4 (smaller and efficient footprint). Laravel in my opinion is overloaded. Thank you for your advise and comment.
Does this mean the only difference between a database abstraction layer and ORM is in the definition of the schema? By the way, I didn't understand the difference between a database abstraction layer and data access layer. They seemed the same to me in terms of usage. what is the actual difference between them?
DBAL (Database Abstraction Layer) provides unified/standard API to access various DB systems like MySQL, SQLite, etc. It does not handle any mapping or anything like that. ORM does the mapping part, it basically allows you to interact with your database in an object oriented way, hence the name "Object-Relational Mapping". PDO for example can be thought of as DBAL but it is not, PDO is more like a Database **Access** Abstraction Layer, just lets you run queries across multiple DB systems but does not give you query builder or anything like that.
Few monts later must instal doctrine/dbal 2.x. v3 have problem with install orm. Maybe I only have this problem. Doctrine\ORM\Tools\Setup at doctrine/orm:2.12 is deprecated... now ORMSetup.
Don't think that's true, at least not according to the documentation & I get an error if I don't map it. Can you share a link to the documentation that states it works this way? Maybe a configuration that I need to enable.
@@ProgramWithGio I have sent you a link to a source code of extension I'm using where strategy is set to UnderscoreNamingStrategy::class by default, but youtube probably deleted that comment, it's at github /contributte/doctrine-orm/blob/master/src/DI/OrmExtension.php at line 51.
@@rickstrafy4870 Thank you, did not know about that extension. It would not work in our setup without setting the naming strategy in container bindings where we configure the entity manager. But is definitely a handy extension, thank you 🙌
Posting the link to the docs here hoping RUclips won't remove it: www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/namingstrategy.html#underscore-naming-strategy
i have a problem, which is when i set one entity everything goes well , but when i make another one it shows the error : No identifier/primary key specified for Entity "SomeEntity" i've been tried every solution and didn't work
thanks again for the great content, by the way, is Doctrine recommended when compared to Raw PDO? how's its performance when compared to Raw PDO? have you used Doctrine a lot in your production project?
Raw queries are usually faster. Though the performance hit by the ORM is dependent on how you set it up and use. You do get a lot of flexibility and better structure though when working with Entities and ORM. I've used Laravel's ORM in production alot and haven't had any performance issues. I haven't used Doctrine a lot in production but when Ive used it I didn't face performance problems either.
ty for your lessons. it's pure gold. but i can't understand these onwning inverse concept)) looks like it's key topic on assositions. right now im strugling with user user_details "onotoone" relation, user.id is annotated as Autogenerared, and UserDetails.user_id have #[ORM\OneToOne(targetEntity: User::class)] #[ORM\JoinColumn(name: "user_id", referencedColumnName: "id")] private ?User $user_id = null; and on $em->flush() i got error that user_id is null, (i always annotated userDetails.user_id as not to be null). i suppose it should be autopopulated from user.id. but this didn't happen. trying to relisten your explanation several times.
"owning side is one that holds the foreign key." invoice_id is foreign key but next your phrase tricks me. "so invoiceItem is owning side", and in animation green arrow points to Invoice.
Why doesn't Doctrine persist the invoice items, without needing to specify "cascade persist" or call the ->persist() method? Doctrine forces me to enter one of those two options and only one? The exception is unnecessary because Doctrine can persist cascading by default, if none of the options are explicit, or simply do nothing. If the "invoice" entity does not depend on the existence of the items, the invoice can be created and the items wait. In another case, if my model says that for an invoice to exist there must be at least one associated item and I am creating it, I can avoid the instruction that the item must be created with the invoice
@@ProgramWithGio It seems redundant to specify this instruction twice; the initial setting should be sufficient. In computing, the "cascade persist" command should inherently imply a single, clear directive to Doctrine. This redundancy feels counterproductive and potentially introduces confusion. In computer science, the magic not exists.
This code at the end part of this video didn't work for me sir: $invoice = $entityManager->find (Invoice::class, 4); //$invoice->setStatus(InvoiceStatus::Paid); $invoice->getItems()->get(4)->setDescription('Foo Bar'); $entityManager->flush(); Fatal error: Uncaught Error: Call to a member function setDescription() on null in ...
Awesome content! But the relationship between Invoice and Invoice Items shouldn't be many to many? Many items can be associated with many different Invoices(Not just one) and many Invoices can be associated with many items.
Thank you. No it shouldnt be many to many because you dont want to have same line item belong to multiple invoices, that would cause some nasty bugs. An invoice item belongs to just one invoice
@@ProgramWithGio Ok.But I thoguht that "item" refers to a type of item/product. e.g. If an invoice have a pepperone pizza as one of its items, another invoice can't have a pepperone pizza as well? Creating the same item "pepperone pizza" again for new invoices wouldn't be redundant? But I might not clearly understood what is an invoice item in this context.
@@joellopescunhadesouza8617 Item is a row in invoice, it contains the description, quantity & price and invoice can be composed of multiple items, its like a line item. If you google invoice template you will see what I mean. To your example, item would be more closer to pizza slice, pizza can have many slices but that specific slice belongs only to that one pizza. Invoice can have pepperoni pizza as an item that was charged $14.99 for example for that item, now that specific row belongs only to that invoice, sure other invoices can have pepperoni pizzas as well but they would not necessarily be the same price right? Maybe some would be with a discount & so on. So each row on the invoice item is unique to that invoice.
I thought that it was referring to the product concept. For exemple, we could have a Item/Product table representing the inventory of items. If that was the case, the invoice item would be the table representing the relationship n:n between an Invoice and a type of item, containing the price which the item was sold, the quantity, amount, etc. Am I right? I know this don't have much to do with the Doctrine, but thank you very much for your attention! God bless you man
I believe I remember there was a package that would allow laravel users to do the same, however, it was never that popular. I believe that comments should never have any effect on the code functionality, regardless of programming language, framework, or whatever else.
@@ProgramWithGio In this case isnt't it just a convention? I've seen projects where one-line comments would only start with `#`, and the linter would just convert `//` to `#`. Maybe I'm missing something when you say "native support".
@@AngelinCalu attributes were added in PHP 8, it's structured & proper way to add metadata to the classes/methods/properties. It's not just a PHP thing, it exists in other languages as well. I have a video about attributes in this series, check it out. By native support I meant that prior to attributes we had to use comments like docblocks to add metadata, now there is native attributes support as of PHP8
Check orphan removal section in the docs: www.doctrine-project.org/projects/doctrine-orm/en/2.11/reference/working-with-associations.html#orphan-removal
The lessons are going hard already for me, these are the concepts I have never reached while learning PHP. Thanks a lot for not missing anything in your way to make us great.
You're welcome. Keep up the good work 💪
Great video as always, thank you.
Note: EntityManager::create() is deprecated
We can use :
$entityManager = new EntityManager(
DriverManager::getConnection($params),
ORMSetup::createAttributeMetadataConfiguration([
__DIR__ . '/Entity',
])
);
Yup, adjusted it later on
Doctrine has more deprecated functions than feudalism in Europe. Another wonderful lesson!
This is funny :D
the hell hahaha
Once again, great content, excellent presentation! Can't wait for the next one!
Thank you 🙌 💙
Doctrine has lots syntax to write, but at the same time it is satisfying that we see how ORM is intended to work. Thanks for the video.
Glad you like it, you're welcome
Use a symfony maker to speed up the process. Really makes the difference
Thank you bro! This helps me. This week I start with new company and they use this. Thnx!
Happy to hear that, good luck at the new company 🤞🤞
@@ProgramWithGio thank you bro!
I used Propel ORM it's really awesome, I also research on Doctrine ORM but not used yet. This video is a deep overview on Doctrine ORM.
Haven't used Propel ORM, looks interesting.
Great tutorial as always to make complicated things as simple as cup of tea
Thank you 💙
this is beautiful and clear🌷Thank you 🌟
Thank you
Great content as always. First time i see doctrine in action and i think eloquent is more user friendly.
Thank you. Yes Laravel Eloquent is much easier & has better Developer Experience.
At timestamp 20:31, when the invoice item were displayed, i see there is invoice_id field has the id of the invoice just created. The question is, how did the value get inserted when we did not set this value at addItem() method?
We are calling addItem on invoice entity, that basically takes care of it. It sets up the relationship between invoice & item.
Perfect video! Thank you so much for this hard work! The presentation is really cool! Always wanted to share the knowledge in same style!!
Always have problems with this associations...
Often have cases and problems in them to manage and map entities, when I have three linked entities like:
Restaurant (OneToMany unidirectional) -> RestaurantPaymentType[] (OneToOne? unidirectional) -> PaymentType
And the middle one have additional attributes, like ordering, DeliveryType (a enum class)
Other example: Restaurant -> RestaurantProductCategory (has ordering, active flag) -> ProductCategory
and in UI, you can choose, which Restaurant have which ProductCategories. (multi-select dropdown)
The hardest part for me, is when I trying to figure out how to solve these relations updating.
Creation is simple, as in your video, but when I trying to update, inverse side items (add/remove) - I have troubles and error.
Either have too complex saving code, or have DB Errors for duplicating unique indexes or PK (One restaurant have only one payment type for one delivery type, so you can't add multiple same payment types for delivery and pickup real life methods)
Some of my friends tell me about using removeOrphans attribute, to tell to Doctrine, that inverse side entity I want to remove - is only used for this one owning entity, and no one else referenced to it.
So I really need to understand this case - how to organize proper mapping and saving (update inverse side entities - add/remove/[update]).
I have existed PaymentTypes (online payment, cash, bank card) - entity in DB.
1) When I'm saving new Restaurant - I created an RestaurantPaymentType entities (in loop), link them to PaymentTypes and Restaurant, adding ordering and some other attributes. All saved correctly.
2) When I'm updating available restaurant payment types, say removed/or added one, then I need to realize, the diff between already existed entities, and new added/removed. Do I need to do this all manually (calculate diff, have multiple arrays - whta to add, what to remove, and exclude existed items), or I can somehow work only with ArrayCollection state, and sync them to DB state?
3) When I'm removing existed Restaurant, I can just use cascade operations, to delete only RestaurantPaymentType, but not PaymentType entity (just relation entity with additional fields). Well this also work correctly.
Mainly have troubles with case number 2. I have a lot of pain doing this. And really need help from those, who understand all the process of managing mapped entities.
(sorry if my English is bad)
Really glad to found this helpful video and channel. Like Doctrine so much, but really need to understand how it works.
Thank you in advance, if you reached this part of comment! :)
Thank you. It's a bit hard to help without seeing the code, I don't exactly understand the question or the problem, maybe if you showed me some part of code I could understand it better. You can ping me on Twitter.
great tutorial, thanks for everything! Can't wait for the final..
Thank you 🙌
Awesome content, simple and direct. Congrats...
Glad you like it, thank you 🙌
In the Invoice example, do you need to have a reference to the Invoice in the Item class? I wouldn't want it in there since it's not needed; the Invoice is the aggregate root, so that's the object that gets passed around and is worked with, NOT the Item. You get to the Items through the root Invoice object.
So can you just have the 1:m set up in the Invoice? Or would I have to do some custom mapping somewhere if I wanted it that way, such as in the save and find methods of the repository?
You could have that setup, it depends on how you use it within your app logic
At 20:34, why in my invoice_items table, data for example: 'item 1' got id of 3 and item 2 got id of 2 and item 3 got id of 1, and item 3 is in first row, item 2 in second row and item 1 in third row, why is that , sir ?
It's auto increment id so u won't get exact same ids as I got on my video. If you've deleted some previous rows the id still gets incremented next time you insert
but why things got inserted in reverse order, ids ( primary key ids are ok ), but datas are not inserted in the way it's seen in the array, because in array the first item is item1 so I should see item1 inserted at top row in database, but I see it in bottom row, why ?
@@expresscoding3525 i don't see your code so I don't know, if you share your code I can check. In the video the order looks fine
Good job! Thank you very much!
Thank you
Wow, this was a bit more complex. Would take getting used to. But like you said practice and use will really help me get familiar. Never the less it was so much fun. I don't know where I would have learnt this... Gio, thank you
It's totally normal, Doctrine & ORM/DBAL in general is not an easy concept so good job
Hey, the $items property is typified with `Collection` class. However, we are instantiating it with `ArrayCollection` class. Is it the case of Contravariance when we typehint property with more general type?
Collection is an interface that ArrayCollection implements
How does the One-to-Many work when there are many tables linking back to a single table? For instance, it is common to see a table of country codes and/or state codes to be used in an application. The country codes and state codes are used many times with different displays, emails, etc. Even in this example there might not be that many tables that link but there might be more. Also, I am curious how that would apply to when a 'plug-in' type would be used. Is it possible for the entity object representing the table of country codes to know about the plug-in without changing the core of the application?
One-to-Many is a relationship between tables or entities, its not about how many times you display it or in how many places you use it. It's about how many transaction records in database table belong to a category via category_id column which references to categories table.
In your example, countries could be a table that stores country code as well as some other information, you then could have another table called states which stores state code & other state related information but it also stores country id or country code which references to the country record in the countries table.
I'm not sure what you mean by "plug-in" though.
Great as usual thanks 🙂
Thank you 🙌
so relationsships, like manytoone etc. it's same as using foreign key?
A foreign key relationship can be onetoone, onetomany, etc
Does Yii2 and Laravel use the same pattern? Are there any differences the way ORM is implemented in these frameworks?
I don't know much about Yii2 so not sure
really cool tutorial
Thank you
Thanks you very much! excellent job)
Glad you like it, thank you 🙌
Interesting, when you did the remove Invoice entity I noticed it was already removing the related InvoiceItems already, cascade on remove is the default behaviour it seems. Neat.
We have cascade on persist & remove enabled in Invoice entity.
github.com/ggelashvili/learnphptherightway-project/blob/3.16/app/Entity/Invoice.php#L38
Great, I understood to use both dbal and orm but orm also have dbal functions so do i really need to use dbal?
Or
In which cases I should use dbal and orm
If you want to make use of entities and ORM then you use the ORM one. If you don't need entities and just need simple query builder then go for DBAL
@@ProgramWithGio Thanks it really saves me the trouble
The best. Thanks
Thanks
more than amazing content
Thank you 🙌
Up to timestamp 17:29, it was a lot to consume. From what i see is that we are doing so much thinking, remembering, understanding and coding just to get what we could do simply by using PDO. I am a business solution developer and i need to get solutions out to the users quickly. Doing all these codes, i estimate it would take 3 times more time, effort, documentation and team understanding (for later support). Too much intertwining which would make debugging so complex a nightmare for a third person (support unit). Perhaps all this knowledge would serve best to people who want to develop some sort of custom frameworks similar (Laravel, Codeigniter etc.). I am not saying its wrong but definitely say it should only be moderately used for business solution development. This is just my feeling up to this point. Perhaps this may change when we do the P series in the course. Definitely a great eye-opener on what PHP can do and realized that we should never compare PHP with the likes of Js frameworks.
Sure you can do a lot with just PDO, however ORMs help by alot and actually make developing apps much easier and faster. Symfony uses doctrine & a lot of enterprise level apps use it. Laravel has eloquent which is also ORM and plenty of startups as well as enterprise level apps use it.
To me it's faster to whip out a working solution with an ORM than without it. But that can be different for everyone, if plain PDO works for you then stick with it, it also depends on the size of the application. For small apps ORM might be overkill
@@ProgramWithGio Agreed. We develope apps in small bits. Mostly headless cms, batch jobs and apis supporting our back-end CRM and transaction systems. Front-end, we are now strategizing on Vuejs and Alpinejs (looking into Astro Build). If i have to create a large app, i might as well stick to Codeigniter 4 (smaller and efficient footprint). Laravel in my opinion is overloaded. Thank you for your advise and comment.
Does this mean the only difference between a database abstraction layer and ORM is in the definition of the schema? By the way, I didn't understand the difference between a database abstraction layer and data access layer. They seemed the same to me in terms of usage. what is the actual difference between them?
DBAL (Database Abstraction Layer) provides unified/standard API to access various DB systems like MySQL, SQLite, etc. It does not handle any mapping or anything like that. ORM does the mapping part, it basically allows you to interact with your database in an object oriented way, hence the name "Object-Relational Mapping".
PDO for example can be thought of as DBAL but it is not, PDO is more like a Database **Access** Abstraction Layer, just lets you run queries across multiple DB systems but does not give you query builder or anything like that.
Few monts later must instal doctrine/dbal 2.x. v3 have problem with install orm. Maybe I only have this problem.
Doctrine\ORM\Tools\Setup at doctrine/orm:2.12 is deprecated... now ORMSetup.
Yes, use the new class, old one was deprecated,
I love your channel
Thank you 💙
18:56 Class Setup seems to be deprecated now. Instead we should use ORMSetup class.
I did not know that, thank you for pointing it out. Seems like it will be removed in 3.0 version.
You don't need to set name to created_at and invoice_number, it's auto-translated (camelCase snake_case)
Don't think that's true, at least not according to the documentation & I get an error if I don't map it. Can you share a link to the documentation that states it works this way? Maybe a configuration that I need to enable.
@@ProgramWithGio I have sent you a link to a source code of extension I'm using where strategy is set to UnderscoreNamingStrategy::class by default, but youtube probably deleted that comment, it's at github /contributte/doctrine-orm/blob/master/src/DI/OrmExtension.php at line 51.
@@rickstrafy4870 Thank you, did not know about that extension. It would not work in our setup without setting the naming strategy in container bindings where we configure the entity manager.
But is definitely a handy extension, thank you 🙌
Posting the link to the docs here hoping RUclips won't remove it: www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/namingstrategy.html#underscore-naming-strategy
Thank you
💙
i have a problem,
which is when i set one entity everything goes well ,
but when i make another one it shows the error : No identifier/primary key specified for Entity "SomeEntity"
i've been tried every solution and didn't work
Did you add primary key identifier to your id property? #[Id] attribute or via annotation
@@ProgramWithGio when i set it by the annotation mode it works but with attriute mode it wont
@@iraqwin9889 can you share your code? Put it on GitHub
but what different between Entity and model .
each of them reference to table in database;
I think this has a good summary of each: gist.github.com/marlenesco/6e31ebc12f78583a9ae417ac0f6647e3
@@ProgramWithGio
super thank for you 🙏
Thanks.
You're welcome
thanks again for the great content, by the way, is Doctrine recommended when compared to Raw PDO? how's its performance when compared to Raw PDO? have you used Doctrine a lot in your production project?
Raw queries are usually faster. Though the performance hit by the ORM is dependent on how you set it up and use. You do get a lot of flexibility and better structure though when working with Entities and ORM. I've used Laravel's ORM in production alot and haven't had any performance issues. I haven't used Doctrine a lot in production but when Ive used it I didn't face performance problems either.
@@ProgramWithGio thanks for it, that helps a lot
ty
thank u
🙌🙌
Great content. What else can I say ?😃
Thank you 🙌
ty for your lessons.
it's pure gold.
but i can't understand these onwning inverse concept)) looks like it's key topic on assositions. right now im strugling with user user_details "onotoone" relation, user.id is annotated as Autogenerared, and UserDetails.user_id have
#[ORM\OneToOne(targetEntity: User::class)]
#[ORM\JoinColumn(name: "user_id", referencedColumnName: "id")]
private ?User $user_id = null;
and on $em->flush() i got error that user_id is null, (i always annotated userDetails.user_id as not to be null). i suppose it should be autopopulated from user.id. but this didn't happen.
trying to relisten your explanation several times.
"owning side is one that holds the foreign key." invoice_id is foreign key but next your phrase tricks me. "so invoiceItem is owning side", and in animation green arrow points to Invoice.
sorry but doctrine docs is more confusing)))
and i have onetoone relation one user can have one user details
should we use inversedBy and mappedBy in onetoone relation? in docs i see that it's optional.
Yes, owning side is the one holding the foreign key, arrow just points to the relation that it owns
Why doesn't Doctrine persist the invoice items, without needing to specify "cascade persist" or call the ->persist() method?
Doctrine forces me to enter one of those two options and only one? The exception is unnecessary because Doctrine can persist cascading by default, if none of the options are explicit, or simply do nothing.
If the "invoice" entity does not depend on the existence of the items, the invoice can be created and the items wait.
In another case, if my model says that for an invoice to exist there must be at least one associated item and I am creating it, I can avoid the instruction that the item must be created with the invoice
Doctrine was designed to be explicit and predictable, less magic going on.
@@ProgramWithGio It seems redundant to specify this instruction twice; the initial setting should be sufficient. In computing, the "cascade persist" command should inherently imply a single, clear directive to Doctrine. This redundancy feels counterproductive and potentially introduces confusion. In computer science, the magic not exists.
This code at the end part of this video didn't work for me sir:
$invoice = $entityManager->find (Invoice::class, 4);
//$invoice->setStatus(InvoiceStatus::Paid);
$invoice->getItems()->get(4)->setDescription('Foo Bar');
$entityManager->flush();
Fatal error: Uncaught Error: Call to a member function setDescription() on null in ...
That just means line item 4 doesn't exist, in video we get 0 not 4
I've invoice with id 4 in invoices table, sir, that's why I did 4
@@expresscoding3525 ->get doesn't take id, takes index
Index means? I mean where to see the index ?
@@expresscoding3525 position, like an array index/key.
Awesome content! But the relationship between Invoice and Invoice Items shouldn't be many to many? Many items can be associated with many different Invoices(Not just one) and many Invoices can be associated with many items.
Thank you. No it shouldnt be many to many because you dont want to have same line item belong to multiple invoices, that would cause some nasty bugs. An invoice item belongs to just one invoice
@@ProgramWithGio Ok.But I thoguht that "item" refers to a type of item/product. e.g. If an invoice have a pepperone pizza as one of its items, another invoice can't have a pepperone pizza as well? Creating the same item "pepperone pizza" again for new invoices wouldn't be redundant? But I might not clearly understood what is an invoice item in this context.
@@joellopescunhadesouza8617 Item is a row in invoice, it contains the description, quantity & price and invoice can be composed of multiple items, its like a line item. If you google invoice template you will see what I mean.
To your example, item would be more closer to pizza slice, pizza can have many slices but that specific slice belongs only to that one pizza.
Invoice can have pepperoni pizza as an item that was charged $14.99 for example for that item, now that specific row belongs only to that invoice, sure other invoices can have pepperoni pizzas as well but they would not necessarily be the same price right? Maybe some would be with a discount & so on. So each row on the invoice item is unique to that invoice.
@@ProgramWithGio Got this now, thank you very much!
I thought that it was referring to the product concept. For exemple, we could have a Item/Product table representing the inventory of items. If that was the case, the invoice item would be the table representing the relationship n:n between an Invoice and a type of item, containing the price which the item was sold, the quantity, amount, etc. Am I right? I know this don't have much to do with the Doctrine, but thank you very much for your attention! God bless you man
It breaks my heart to see Decimal(10,2) being casted to float. But great video regardless!
For simple projects that's fine in my opinion but yea in general I agree to avoid using floats for monetary values
Great job with the video. I really dislike the Doctrine ORM ways of linking data through the attributes in those # comments.
Thank you. I like it. I prefer attributes over docblocks & config files
I believe I remember there was a package that would allow laravel users to do the same, however, it was never that popular.
I believe that comments should never have any effect on the code functionality, regardless of programming language, framework, or whatever else.
@@AngelinCalu I agree, that's why I dislike docblocks. Attributes are not comments though, it's native support to add metadata
@@ProgramWithGio In this case isnt't it just a convention?
I've seen projects where one-line comments would only start with `#`, and the linter would just convert `//` to `#`.
Maybe I'm missing something when you say "native support".
@@AngelinCalu attributes were added in PHP 8, it's structured & proper way to add metadata to the classes/methods/properties. It's not just a PHP thing, it exists in other languages as well. I have a video about attributes in this series, check it out.
By native support I meant that prior to attributes we had to use comments like docblocks to add metadata, now there is native attributes support as of PHP8
if all authors on udemy would like him....
💙💙
sztring 🙂
Did I have a typo somewhere? :D
The girl in this video is very beautiful
It's a stock video 😁
How do cascade persist and remove work on a OneToOne and ManyToMany relationship?
Check orphan removal section in the docs: www.doctrine-project.org/projects/doctrine-orm/en/2.11/reference/working-with-associations.html#orphan-removal