WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:00.286 --> 00:00:06.176 align:middle
A lot of things, um, I hope it's not too fast.

00:00:06.526 --> 00:00:11.326 align:middle
But in any case I will still be around
afterwards, so if you want to talk about any

00:00:11.326 --> 00:00:15.836 align:middle
of those topics I will be talking about, we
can talk about that later on in more detail.

00:00:16.276 --> 00:00:21.426 align:middle
So first of all, because I already know that
in this room it's really hard to see the slides

00:00:21.426 --> 00:00:22.606 align:middle
if you're in the back of the room.

00:00:22.926 --> 00:00:25.646 align:middle
The qr code goes to joined.in to the talk.

00:00:25.646 --> 00:00:29.086 align:middle
I already uploaded the slides
with some additional pages

00:00:29.086 --> 00:00:30.826 align:middle
in there that you just have to skip over.

00:00:31.276 --> 00:00:39.636 align:middle
And yeah, you can just go to the talk/c1b8c is
the talk id and, and you can just get the slides

00:00:39.636 --> 00:00:43.746 align:middle
and you watch them on speaker deck
as well if you don't want to follow

00:00:43.746 --> 00:00:46.476 align:middle
on the screen or things are hard to read.

00:00:46.696 --> 00:00:48.736 align:middle
So, um, with that out of the way.

00:00:48.736 --> 00:00:51.446 align:middle
Um, hello again, my name is Denis Brumann.

00:00:51.446 --> 00:00:56.386 align:middle
I work for SensioLabs in Germany
as a software developer in Berlin.

00:00:56.896 --> 00:01:02.876 align:middle
And you can reach me via email denis.brumann
[at] sensiolabs.de and also on twitter

00:01:02.876 --> 00:01:05.146 align:middle
and GitHub with my initial and last name.

00:01:06.496 --> 00:01:10.246 align:middle
And before I start I want to make
clear that everything I will talk

00:01:10.246 --> 00:01:13.266 align:middle
about is about Doctrine 2 not Doctrine 3.

00:01:13.266 --> 00:01:16.416 align:middle
It's not out yet, but it's
already under active development.

00:01:16.416 --> 00:01:18.626 align:middle
The master branch already points to Doctrine 3.

00:01:19.366 --> 00:01:25.036 align:middle
Things might still apply in some way or another,
but, but it will probably not be the same.

00:01:25.126 --> 00:01:28.096 align:middle
For example, the unit of work
is probably not stick around.

00:01:28.716 --> 00:01:33.416 align:middle
Um, so keep in mind this is how things are
right now, but it's still helpful to know

00:01:33.416 --> 00:01:36.516 align:middle
because if you want to do
this switch to Doctrine 3,

00:01:36.516 --> 00:01:39.256 align:middle
you probably want to know how
Doctrine 2 works under the hood

00:01:39.576 --> 00:01:43.396 align:middle
to basically know does this change
affect me that they introduced.

00:01:43.396 --> 00:01:47.586 align:middle
And do I have to look at anything that
maybe could cause a bug in my code.

00:01:48.166 --> 00:01:54.856 align:middle
So we will start by just looking at a
simplified domain that we basically we'll follow

00:01:54.916 --> 00:01:56.556 align:middle
through the, through the whole talk.

00:01:57.326 --> 00:01:59.946 align:middle
And I only have two entities in the domain.

00:01:59.946 --> 00:02:01.246 align:middle
So it's kind of easy.

00:02:01.246 --> 00:02:05.496 align:middle
It's probably easier than all the entities
setups that you have in your projects,

00:02:05.556 --> 00:02:07.866 align:middle
but it will be enough to to
look at all these things.

00:02:08.466 --> 00:02:11.696 align:middle
So first of all, we have an
Order that just has an id.

00:02:11.746 --> 00:02:15.266 align:middle
It's an auto-increment id, very basic
stuff that you will probably all know.

00:02:16.116 --> 00:02:20.816 align:middle
We have a timestamp from when that order was
created and then it's basically just a list

00:02:20.816 --> 00:02:22.686 align:middle
of OtherItems which we'll look at later.

00:02:23.266 --> 00:02:29.006 align:middle
And everything is set via getters and setters
just like most people are familiar with.

00:02:29.506 --> 00:02:33.216 align:middle
There are other nicer ways of dealing
with things, with like rich domain models,

00:02:33.216 --> 00:02:37.886 align:middle
but where it's more expressive, but we will
just look at something that's kind of ordinary.

00:02:38.756 --> 00:02:41.186 align:middle
And the OrderItem is the same.

00:02:41.376 --> 00:02:43.346 align:middle
It has the same auto-incrementing id.

00:02:43.636 --> 00:02:45.316 align:middle
It's linked back to the Order.

00:02:45.316 --> 00:02:49.986 align:middle
Um, that's a necessity because
OneToMany requires ManyToOne.

00:02:49.986 --> 00:02:51.496 align:middle
We will look at that.

00:02:51.496 --> 00:02:55.466 align:middle
It has a name for, for the item
that we want to store in our Order.

00:02:55.756 --> 00:02:59.606 align:middle
And it also has a price which is a
string, which might seem weird at first.

00:03:00.206 --> 00:03:06.966 align:middle
But if you ever worked in an e-commerce
system using floats, it's really a pain.

00:03:06.966 --> 00:03:11.056 align:middle
It just causes rounding errors and, and,
and it's just horrible to work with.

00:03:11.386 --> 00:03:14.306 align:middle
So one workaround is to use ints, so integers.

00:03:14.906 --> 00:03:19.116 align:middle
So basically instead of using the
euro amount, use the cent amount:

00:03:19.226 --> 00:03:21.436 align:middle
100 cents are one euro and that's it.

00:03:21.906 --> 00:03:24.416 align:middle
And that makes things a little bit safer.

00:03:24.506 --> 00:03:30.756 align:middle
And I pushed it to the next level and used
string and you will see later on why we do this.

00:03:30.756 --> 00:03:32.316 align:middle
So let's look at the code.

00:03:32.376 --> 00:03:33.866 align:middle
So you probably all have seen this.

00:03:34.446 --> 00:03:36.376 align:middle
It's a very basic entity.

00:03:36.826 --> 00:03:38.846 align:middle
We have the usual annotations.

00:03:39.206 --> 00:03:43.106 align:middle
In this case we also add
a custom repository class.

00:03:43.106 --> 00:03:44.886 align:middle
You probably have seen that as well.

00:03:45.256 --> 00:03:47.706 align:middle
We give our table a specific name.

00:03:47.706 --> 00:03:49.886 align:middle
For the OrderItem it doesn't matter as much.

00:03:49.886 --> 00:03:56.946 align:middle
For the Order, it's more important because
order is a reserved word in most dbms.

00:03:57.076 --> 00:04:00.476 align:middle
So that kind of messes up things.

00:04:00.476 --> 00:04:04.486 align:middle
But when you work with Doctrine, um, so it's
nice to, to give it an alternative name.

00:04:05.346 --> 00:04:09.856 align:middle
As I already said, the auto-increment
integer, that's pretty much what you all know.

00:04:10.796 --> 00:04:12.086 align:middle
Then we link to our Order.

00:04:12.446 --> 00:04:16.396 align:middle
Um, the interesting thing is that
we basically tell the JoinColumn

00:04:16.396 --> 00:04:20.306 align:middle
that this OrderItem always
needs to be attached to an Order

00:04:20.306 --> 00:04:22.146 align:middle
because it doesn't really make much sense

00:04:22.146 --> 00:04:25.526 align:middle
to have an OrderItem just loosely
hanging around in the database.

00:04:25.526 --> 00:04:30.416 align:middle
So we just ensure this with
the JoinColumn(nullable=false).

00:04:30.416 --> 00:04:32.556 align:middle
And the rest is just basic stuff.

00:04:32.626 --> 00:04:34.616 align:middle
We get things, we set things.

00:04:34.616 --> 00:04:37.806 align:middle
You probably all have seen
this, you can auto-generate it.

00:04:37.906 --> 00:04:38.776 align:middle
So it's really simple.

00:04:38.776 --> 00:04:41.596 align:middle
With Order it's kind of the same thing.

00:04:41.596 --> 00:04:45.626 align:middle
We have an auto-incrementing id, we have
the relationship this time a @OneToMany

00:04:46.056 --> 00:04:49.946 align:middle
that maps back to the OrderItem $order property.

00:04:50.636 --> 00:04:54.006 align:middle
And if you think about the, the table layout,

00:04:54.006 --> 00:04:59.696 align:middle
it kind of gets clear why we needed the
other relationship from the OrderItem back

00:04:59.696 --> 00:05:05.846 align:middle
to the Order because obviously the, the
order ID is stored inside the OrderItem.

00:05:05.846 --> 00:05:06.776 align:middle
It links back to that.

00:05:06.886 --> 00:05:11.226 align:middle
So if we were just to have this
relationship with, on our Order,

00:05:11.526 --> 00:05:15.066 align:middle
that that wouldn't be a reference to:
okay, where is information stored?

00:05:15.066 --> 00:05:16.446 align:middle
It's in this different table.

00:05:16.746 --> 00:05:21.906 align:middle
So the, the OneToMany relationship is
the only one where you actually have

00:05:21.996 --> 00:05:24.516 align:middle
to have a bi-directional association.

00:05:24.866 --> 00:05:27.766 align:middle
In other cases you can just have
a unidirectional association.

00:05:28.306 --> 00:05:31.926 align:middle
And the other important thing here is
the cascade={"persist"}, which come,

00:05:31.926 --> 00:05:35.996 align:middle
will come in later, but just keep it in the
back of your head that this is important.

00:05:37.406 --> 00:05:40.906 align:middle
And yeah, for the timestamp I just
use the DateTimeImmutable object.

00:05:40.906 --> 00:05:44.416 align:middle
It's one of the types that Doctrine supports.

00:05:45.276 --> 00:05:49.626 align:middle
We initialize the items that we want to
put into our Order is an ArrayCollection.

00:05:49.626 --> 00:05:52.176 align:middle
You probably have seen it 100 times and more.

00:05:52.816 --> 00:05:57.956 align:middle
Um, in my case, I return the array
instead of the ArrayCollection.

00:05:57.956 --> 00:06:01.776 align:middle
This is just something I like, but
there's no specific reason to do that.

00:06:02.556 --> 00:06:06.076 align:middle
Um, and it doesn't really come up
later, so I just want to point it

00:06:06.076 --> 00:06:08.976 align:middle
out that this is a quirk I
have, you don't have to do that.

00:06:09.566 --> 00:06:13.426 align:middle
Um, what is important is
the addItem(), we basically,

00:06:13.426 --> 00:06:17.556 align:middle
because we have a bidirectional association,
we have to make sure that both the Order

00:06:17.556 --> 00:06:20.356 align:middle
and the OrderItem know what
object they are linked to.

00:06:20.696 --> 00:06:26.526 align:middle
So in this case, I set the Order um, to
$this on the $item and also add this item

00:06:26.526 --> 00:06:28.856 align:middle
to our current Order if that makes sense.

00:06:29.676 --> 00:06:34.306 align:middle
Um, and yeah, this is where the
string part for the price comes in.

00:06:34.306 --> 00:06:38.496 align:middle
I use the BC math extension for PHP.

00:06:38.576 --> 00:06:42.286 align:middle
If you use modern php where you
have strict-typing and everything,

00:06:42.766 --> 00:06:45.666 align:middle
you can't just pass in an integer
or float, it has to be a string,

00:06:45.666 --> 00:06:49.616 align:middle
otherwise you will get a type error and that's
why I use the string all the way through

00:06:49.616 --> 00:06:53.096 align:middle
and it will just add those
strings, strings up from the items

00:06:53.486 --> 00:06:55.576 align:middle
and then you get the final total price.

00:06:55.706 --> 00:06:57.176 align:middle
So it's really simple math.

00:06:57.176 --> 00:07:01.026 align:middle
It's just doing plus current
total plus the next item.

00:07:01.626 --> 00:07:03.266 align:middle
Okay. So those are the basics.

00:07:03.566 --> 00:07:09.936 align:middle
Um, I know that was kind of fast, but I, I kind
of hope that you got the structure in your head,

00:07:09.936 --> 00:07:13.366 align:middle
you know, what we're talking about in
terms of what kind of objects we're dealing

00:07:13.366 --> 00:07:15.856 align:middle
with because this is all we will use throughout.

00:07:16.506 --> 00:07:21.286 align:middle
And yeah, just assume that with our
very simplified e-commerce system

00:07:21.286 --> 00:07:23.576 align:middle
that we have now, we want to do a checkout.

00:07:23.576 --> 00:07:28.036 align:middle
We select items from a page - I don't
have everything built for this case -

00:07:28.036 --> 00:07:29.686 align:middle
it's just, let's assume it happened.

00:07:30.056 --> 00:07:33.076 align:middle
And then we pass things to a Checkout service.

00:07:33.306 --> 00:07:37.096 align:middle
I don't use the service suffix here,
but this is just a basic service class.

00:07:37.896 --> 00:07:42.416 align:middle
Um, I pass in the EntityManager
because we want to store the Order

00:07:42.416 --> 00:07:45.116 align:middle
when we do a checkout with all the OrderItems.

00:07:45.666 --> 00:07:48.396 align:middle
And this is what the actual
checkout method looks like.

00:07:48.496 --> 00:07:55.856 align:middle
In my case I just get some $cartItems which are
basically products that, uh, in a DTO entity

00:07:55.856 --> 00:07:58.766 align:middle
or whatever that is used on the frontend

00:07:58.766 --> 00:08:02.686 align:middle
for displaying my product
items in the cart and checkout.

00:08:03.196 --> 00:08:05.816 align:middle
And now I want to transform
them to, to an OrderItem.

00:08:05.896 --> 00:08:10.886 align:middle
It's basically to make sure that when
the product changes, I change the price,

00:08:10.886 --> 00:08:14.536 align:middle
my OrderItem is supposed to still have
that price because I will still want

00:08:14.536 --> 00:08:19.216 align:middle
to charge the customer the original price
they used when they used the checkout.

00:08:19.926 --> 00:08:21.556 align:middle
And then I just do some mapping.

00:08:21.556 --> 00:08:25.186 align:middle
I map the name and the price from
the $cartItem to the OrderItem.

00:08:25.926 --> 00:08:30.806 align:middle
I add that OrderItem to my existing
Order that I created up there in the top,

00:08:30.806 --> 00:08:34.936 align:middle
and then I just save that Order
and I flush the entity manager.

00:08:35.066 --> 00:08:36.466 align:middle
So you probably have all seen this.

00:08:36.466 --> 00:08:40.406 align:middle
This is really basic stuff and still,

00:08:40.406 --> 00:08:43.906 align:middle
there are some really interesting
things going on behind the scenes.

00:08:43.956 --> 00:08:48.656 align:middle
Because if you think about it, first of
all, we are only persisting the Order

00:08:48.656 --> 00:08:51.546 align:middle
but the OrderItems will be saved as well.

00:08:51.546 --> 00:08:56.506 align:middle
So Doctrine, for some reason knows it has to
save those items into that separate table.

00:08:57.156 --> 00:09:01.366 align:middle
Um, and it also knows that has to
do insert instead of just an update.

00:09:01.426 --> 00:09:04.196 align:middle
So let's look at why this happens?

00:09:04.196 --> 00:09:06.706 align:middle
How does Doctrine know, which items to save?

00:09:06.706 --> 00:09:13.076 align:middle
And that is really interesting and
it works based on the unit of work.

00:09:13.426 --> 00:09:17.676 align:middle
This is a really huge object and,
and it's kind of a basic pattern.

00:09:17.726 --> 00:09:23.426 align:middle
So, um, the, the example on the right
is basically what Martin Fowler has

00:09:23.466 --> 00:09:24.796 align:middle
in his pattern catalog.

00:09:25.256 --> 00:09:30.146 align:middle
I omitted a few methods that we don't really
care about, but basically this is an object

00:09:30.146 --> 00:09:36.816 align:middle
that stores our changes for the database
and, and keeps them in memory until we flush

00:09:36.816 --> 00:09:38.196 align:middle
and we actually want to write them.

00:09:38.566 --> 00:09:44.056 align:middle
And then this unit of work, will figure out
what writes it has to do: if it's an insert,

00:09:44.056 --> 00:09:46.646 align:middle
if it's an update and which
order things have to happen.

00:09:46.956 --> 00:09:51.186 align:middle
And that's really a lot of stuff going
on there and it's a huge class right now,

00:09:51.186 --> 00:09:54.446 align:middle
which is probably why in Doctrine 3 that
they want to split it up a little bit.

00:09:54.936 --> 00:09:58.076 align:middle
Um, and it's also kind of ugly to look into it.

00:09:58.076 --> 00:10:01.986 align:middle
Um, so it's fun to dive into
it if you want to do it.

00:10:02.206 --> 00:10:05.756 align:middle
If you have to do it because things
go wrong, then it's just a pain.

00:10:05.756 --> 00:10:10.286 align:middle
So I want to save you from doing that and
just enjoy looking into it for the fun of it.

00:10:10.886 --> 00:10:15.326 align:middle
Um, and you can already see
that there are some states for,

00:10:15.326 --> 00:10:17.206 align:middle
for insertions, for updates, for deletions.

00:10:17.286 --> 00:10:21.636 align:middle
We have the entityChangeSets, so what
changes need to be written to the database.

00:10:22.486 --> 00:10:28.566 align:middle
And more importantly we see some of
the methods that look a lot of similar

00:10:28.566 --> 00:10:30.936 align:middle
to the methods on the EntityManager.

00:10:31.566 --> 00:10:35.306 align:middle
Um, so for example, we have a persist()
method that looks basically the same.

00:10:35.306 --> 00:10:38.846 align:middle
The remove() method, the flush() method
that kind of looks like the commit() method.

00:10:39.256 --> 00:10:42.106 align:middle
So that, there's some kind of overlap.

00:10:42.476 --> 00:10:50.816 align:middle
And that's no, no that's intentional because
basically the EntityManager will pass its called

00:10:50.816 --> 00:10:54.816 align:middle
to the UnitOfWork and the UnitOfWork
will store all those things.

00:10:54.886 --> 00:10:59.666 align:middle
So when we pass in the Order, the UnitOfWork
will figure out: ah those other properties

00:10:59.736 --> 00:11:01.346 align:middle
that map to a database table,

00:11:01.556 --> 00:11:05.846 align:middle
I have to basically save the data
that's in there for later change.

00:11:06.236 --> 00:11:10.566 align:middle
And I will also have to remember that
this object that they wanted to persist,

00:11:11.146 --> 00:11:15.666 align:middle
I have to basically write that to the
database as a new object based on the state.

00:11:16.856 --> 00:11:21.126 align:middle
And the reason why this thing
works with the OtherItems as well

00:11:21.126 --> 00:11:23.536 align:middle
as because we have this cascade
persist in there.

00:11:24.056 --> 00:11:29.296 align:middle
Because when we persist our
OrderItem, what will always happen is

00:11:29.376 --> 00:11:34.316 align:middle
that the EntityManager will also look
through the associations on our entity.

00:11:34.316 --> 00:11:39.586 align:middle
So on our Order it will look at the the items
property and say, "Oh this is an association,

00:11:39.586 --> 00:11:42.606 align:middle
the items in there I probably
have to save as well".

00:11:42.776 --> 00:11:47.436 align:middle
And then just loops over them and sees
either if we persist them manually

00:11:47.436 --> 00:11:52.556 align:middle
or if we have the cascade persist, then
obviously Doctrine knows everything that I put

00:11:52.556 --> 00:11:55.986 align:middle
in there I have to store in the
database as well on an insert.

00:11:57.066 --> 00:11:58.516 align:middle
And yeah, this is basically what happens.

00:11:58.516 --> 00:12:02.606 align:middle
So we pass in the Order and then Doctrine
figures out, the OrderItems in there,

00:12:02.606 --> 00:12:06.086 align:middle
I have INSERT them as well and
have to write to the changesets.

00:12:06.526 --> 00:12:11.376 align:middle
And this is roughly equivalent
to adding a second persist

00:12:11.446 --> 00:12:13.276 align:middle
in our foreach loop for each item.

00:12:13.756 --> 00:12:18.476 align:middle
There are some subtle differences,
but basically it works out the same.

00:12:19.116 --> 00:12:24.276 align:middle
And if you don't do either of those
things, so neither the cascade annotation

00:12:24.716 --> 00:12:28.606 align:middle
or persisting all the objects
manually, what you will get this error.

00:12:29.316 --> 00:12:35.296 align:middle
Because, obviously, Doctrine knows that some
objects should be stored in the database

00:12:35.296 --> 00:12:39.326 align:middle
because we have the association
there, but it doesn't want

00:12:39.326 --> 00:12:42.366 align:middle
to write this unless we tell Doctrine to do so.

00:12:42.636 --> 00:12:45.736 align:middle
Because it would be kind of bad
that when Doctrine thinks: yeah,

00:12:45.736 --> 00:12:49.336 align:middle
I know Dennis is kinda lazy and he
probably forgot to do the annotation.

00:12:49.336 --> 00:12:50.826 align:middle
I will just save it for him.

00:12:51.316 --> 00:12:56.786 align:middle
And that could be fine, but if it just writes
stuff to the database that I really didn't want

00:12:56.786 --> 00:12:58.806 align:middle
to have, then yeah, I'm in trouble.

00:12:58.876 --> 00:13:00.786 align:middle
So Doctrine says no, I won't touch that.

00:13:01.646 --> 00:13:02.576 align:middle
Figure it out yourself.

00:13:02.576 --> 00:13:03.976 align:middle
Do you really want to persist this?

00:13:04.116 --> 00:13:08.986 align:middle
Then either call persist or cascade
or just move it out of the collection.

00:13:09.086 --> 00:13:13.236 align:middle
So this is something you have to be
aware of when you work with Doctrine

00:13:13.236 --> 00:13:17.166 align:middle
that unintentionally non-persistent
entities that come

00:13:17.166 --> 00:13:20.006 align:middle
up in the changeset, Doctrine
will not touch them.

00:13:20.366 --> 00:13:21.656 align:middle
You have to figure things out.

00:13:21.866 --> 00:13:25.746 align:middle
It will give you a nice error like you
saw before where it tells you what to do,

00:13:25.976 --> 00:13:30.126 align:middle
but still you have to check if: is this really
something that has to go into the database?

00:13:30.286 --> 00:13:33.216 align:middle
Probably yes, and then you
have to act on it and do that.

00:13:33.786 --> 00:13:39.076 align:middle
And also you have to add this
cascade annotation to make sure

00:13:39.076 --> 00:13:41.366 align:middle
that this happens automatically for you.

00:13:41.656 --> 00:13:45.626 align:middle
And obviously only on the entity
that is supposed to cascade.

00:13:45.686 --> 00:13:50.836 align:middle
So on the OrderItem we didn't cascade for the
Order, because I decided that I always want

00:13:50.996 --> 00:13:55.716 align:middle
to save the Order with the items but not an
item and then create a new Order for that item.

00:13:55.716 --> 00:13:58.876 align:middle
Because in my e-commerce
context, that doesn't make sense.

00:13:58.876 --> 00:14:04.716 align:middle
If you have this context where this makes
sense and your item can be the primary object,

00:14:04.906 --> 00:14:09.876 align:middle
basically, then you can just do that: just add
the cascade and it will also save the new Order

00:14:09.876 --> 00:14:12.396 align:middle
through the item as well
when you persist one item.

00:14:13.436 --> 00:14:16.506 align:middle
And Doctrine will also figure
out in what order to do that.

00:14:17.486 --> 00:14:21.906 align:middle
Okay. So much INSERT, there was already
like really, really lots of stuff in there.

00:14:21.906 --> 00:14:27.676 align:middle
And it's basically getting worse,
but at least we have nice pictures.

00:14:28.216 --> 00:14:33.356 align:middle
So let's think about like we're inserting
new orders, we do our checkouts and,

00:14:33.356 --> 00:14:36.846 align:middle
and we now want to have a backend
where we want to look at our orders.

00:14:36.886 --> 00:14:39.446 align:middle
And we want to have some additional details.

00:14:39.446 --> 00:14:42.046 align:middle
So in our order list, we don't
just want to show the order number,

00:14:42.046 --> 00:14:46.276 align:middle
we want to see how many items are in there,
what will be the total price for that.

00:14:47.176 --> 00:14:49.016 align:middle
And what you can see on the bottom is

00:14:49.206 --> 00:14:53.186 align:middle
that this will issue 2 database
queries which might seem odd to some.

00:14:53.666 --> 00:14:57.996 align:middle
Um, because yeah, it's just, we just wanted
our order list and that could be one query.

00:14:59.116 --> 00:15:04.226 align:middle
And the reason this happens is you don't
have to look at the full Twig template,

00:15:04.226 --> 00:15:08.676 align:middle
but this is basically the bottom part that
that shows how many items are in there

00:15:08.676 --> 00:15:11.326 align:middle
and what they cost - the total price.

00:15:11.326 --> 00:15:15.716 align:middle
And this is our Order, method, getTotal()
price that iterates over the items.

00:15:15.716 --> 00:15:18.686 align:middle
So I'm not calling the items
themselves, the, the, the method does,

00:15:19.016 --> 00:15:22.366 align:middle
but still Doctrine recognizes: ah,
those items I need to get somewhere.

00:15:22.826 --> 00:15:26.086 align:middle
And it will just issue the
second query for those items.

00:15:26.956 --> 00:15:32.596 align:middle
And this can get bad if you have more than
one item in your overview or one order

00:15:32.596 --> 00:15:36.816 align:middle
in your overview, because for every
Order it has to fetch the items.

00:15:36.876 --> 00:15:41.726 align:middle
So if we have five orders, it issues
one query for getting all the orders

00:15:42.066 --> 00:15:45.456 align:middle
and then another query for
every order to get its items.

00:15:45.456 --> 00:15:49.456 align:middle
This is often referred to as the N+1 problem.

00:15:49.456 --> 00:15:53.716 align:middle
So Doctrine will basically issue more
queries than you might think it will.

00:15:54.886 --> 00:15:57.436 align:middle
And yeah, this is basically what
it looks like in a profiler.

00:15:57.436 --> 00:16:01.826 align:middle
So you can see that on the bottom you
have the query for the order list,

00:16:01.826 --> 00:16:07.166 align:middle
fetching all the orders and then for every order
of 5 times you get the same SELECT statement,

00:16:07.166 --> 00:16:10.096 align:middle
um, for the items fetching
all the items for that order.

00:16:11.306 --> 00:16:13.696 align:middle
And the reason this happens is lazy loading.

00:16:13.696 --> 00:16:15.756 align:middle
You probably have heard that before.

00:16:16.366 --> 00:16:20.866 align:middle
And how it works in Doctrine is
it uses a so-called proxy pattern.

00:16:21.466 --> 00:16:28.066 align:middle
So when you call getOrderItems() or even just
accessing the items property on your Order,

00:16:28.726 --> 00:16:32.926 align:middle
Doctrine has not loaded this beforehand,
because we only wanted the orders

00:16:32.986 --> 00:16:34.826 align:middle
in the beginning and our controller.

00:16:35.276 --> 00:16:39.616 align:middle
Instead it will see that those items
are not loaded, load from the database.

00:16:39.716 --> 00:16:43.616 align:middle
And once that is done and will return those
other items and it will keep them in there.

00:16:43.646 --> 00:16:46.606 align:middle
So it will not do the same query on
the same object over and over again.

00:16:46.876 --> 00:16:50.196 align:middle
It just remembers: ah these items
were not fetched the first time

00:16:50.606 --> 00:16:52.166 align:middle
and that's why I'm fetching it now.

00:16:52.166 --> 00:16:56.336 align:middle
And then subsequent calls will get
those items we previously fetched.

00:16:57.056 --> 00:17:02.276 align:middle
And what's kind of responsible is
the, I already mentioned the proxy,

00:17:02.276 --> 00:17:07.886 align:middle
the proxy objects that Doctrine generates -
at least if you're not in debug mode, so, um,

00:17:07.886 --> 00:17:12.396 align:middle
it might create the folder but you will probably
not see files on there, so just do debug false

00:17:12.776 --> 00:17:17.386 align:middle
and you will see those proxy
files and we can look at them.

00:17:18.246 --> 00:17:24.316 align:middle
They are huge and ugly and, and I never
had to look at them in any real cases.

00:17:24.316 --> 00:17:26.456 align:middle
It's just basically to show
you what they look like.

00:17:26.896 --> 00:17:30.886 align:middle
Um, you can already see that it's just
an object over our original Order.

00:17:30.886 --> 00:17:35.976 align:middle
That's also why we can't have,
entities final, because something has

00:17:36.026 --> 00:17:37.736 align:middle
to extend them - the proxy object.

00:17:37.736 --> 00:17:41.226 align:middle
And then have an initializer and
then you have tons and tons of code

00:17:41.226 --> 00:17:45.236 align:middle
that basically is unreadable and, and you
don't have to, it's automatically generated

00:17:45.236 --> 00:17:46.316 align:middle
and you don't have to care about it.

00:17:46.586 --> 00:17:50.946 align:middle
But you can already see that if I want to
get those items, some initializer is looked

00:17:50.946 --> 00:17:52.356 align:middle
at it, and it will invoke a method.

00:17:52.356 --> 00:17:56.856 align:middle
And this initializer is basically responsible
for doing the querying in the background.

00:17:57.196 --> 00:18:02.186 align:middle
And then it will just get the items as our
method on our parent object basically described.

00:18:02.276 --> 00:18:07.856 align:middle
So, um, this is the magic
behind it, so to speak.

00:18:07.856 --> 00:18:09.366 align:middle
And this is how it looks as UML.

00:18:09.366 --> 00:18:13.156 align:middle
I hope I got the arrows right
the direction and the arrow tip.

00:18:13.376 --> 00:18:17.656 align:middle
I, I'm, I'm not a computer scientist, so I have
never learned this and I never get this right.

00:18:18.446 --> 00:18:20.606 align:middle
Um, but yeah, this is basically
what it looks like.

00:18:20.606 --> 00:18:25.566 align:middle
You have a wrapper on your Order object
on the right that has the same methods,

00:18:25.566 --> 00:18:29.066 align:middle
it just has some additional stuff on there
that you don't really have to care about.

00:18:29.066 --> 00:18:30.746 align:middle
You don't have to access yourself.

00:18:30.846 --> 00:18:32.996 align:middle
Doctrine does this under the hood for you.

00:18:33.856 --> 00:18:36.596 align:middle
And this is fine if it's actually what you want.

00:18:36.596 --> 00:18:39.856 align:middle
So for example, if you fetch orders
and you don't want to access the items,

00:18:39.926 --> 00:18:44.916 align:middle
it's really good that doctrine doesn't fetch
the items every time you, you get this order.

00:18:45.186 --> 00:18:50.026 align:middle
But when you want to have the items
and it issues these additional queries,

00:18:50.096 --> 00:18:54.956 align:middle
then you kind of want to address this in
some cases where it makes the site slow.

00:18:56.066 --> 00:19:00.326 align:middle
And what you, what you can do is add
another option to the annotation and say:

00:19:00.646 --> 00:19:04.326 align:middle
this relationship I want to fetch
eagerly, so always fetch those items.

00:19:05.206 --> 00:19:09.986 align:middle
Um, obviously this has the same
drawback as fetching things lazily does

00:19:10.066 --> 00:19:12.566 align:middle
because now everything is always fetched.

00:19:12.566 --> 00:19:16.646 align:middle
And as I said, if we have cases where we just
want to work with the Order without items,

00:19:16.926 --> 00:19:19.386 align:middle
we now do a query that we don't really need.

00:19:19.486 --> 00:19:23.306 align:middle
So this might not work as well,
but, but it's a nice and easy way

00:19:23.306 --> 00:19:25.256 align:middle
to address this issue to, to not lazy-load.

00:19:25.766 --> 00:19:30.806 align:middle
The other kind of more involved approach
is since we have our own repositories

00:19:30.806 --> 00:19:35.976 align:middle
and we can write our own DQL queries, we
can just tell Doctrine to join the items

00:19:36.486 --> 00:19:40.376 align:middle
in certain cases where we define the
method and we just call this method.

00:19:40.456 --> 00:19:42.746 align:middle
So in this case, findOrderWithItems().

00:19:43.646 --> 00:19:45.896 align:middle
And the interesting bit is the join part.

00:19:46.446 --> 00:19:49.566 align:middle
You can see that this is DQ,
it works on the object level.

00:19:49.566 --> 00:19:54.416 align:middle
So we're not talking to the database
table, we're talking about our objects.

00:19:54.416 --> 00:20:00.876 align:middle
In this case, the Order object that has
alias o, it has some items property -

00:20:00.996 --> 00:20:05.016 align:middle
we already know that - and this item's
property, everything that's in there,

00:20:05.346 --> 00:20:07.266 align:middle
in the association, that's what we want to join.

00:20:07.566 --> 00:20:11.016 align:middle
And that's also what we want to select because
if you don't select then it will just join it

00:20:11.016 --> 00:20:14.476 align:middle
and throw it away when hydrating the object.

00:20:14.746 --> 00:20:18.396 align:middle
That's basically if you want
to ask something from the items

00:20:18.396 --> 00:20:21.366 align:middle
without actually fetching the
items, then this can be useful.

00:20:21.936 --> 00:20:28.006 align:middle
And so this is a more involved query because
you actually have to write the query other

00:20:28.006 --> 00:20:32.926 align:middle
than just doing find(), but, but it can already
help you that I can now figure out my cases

00:20:32.926 --> 00:20:36.346 align:middle
where I want to do Order with
items and Order without items.

00:20:37.176 --> 00:20:42.546 align:middle
Another approach that I personally like
even better is custom object hydration.

00:20:43.066 --> 00:20:46.896 align:middle
Um, so take for example, a DTO
object that looks like this.

00:20:46.896 --> 00:20:48.346 align:middle
It's probably really hard to read.

00:20:48.796 --> 00:20:53.116 align:middle
So we have an OrderSummary and it
describes all the information we want

00:20:53.116 --> 00:20:54.136 align:middle
to see in our Order list.

00:20:54.136 --> 00:20:58.036 align:middle
We have the Order id that we want
to display, the created timestamp

00:20:58.346 --> 00:21:00.956 align:middle
and then the item count and the item total.

00:21:01.496 --> 00:21:05.006 align:middle
Um, and then we have just getters,
we don't want to change this data

00:21:05.006 --> 00:21:09.716 align:middle
because this is basically a read
model on our database and we just want

00:21:09.716 --> 00:21:11.526 align:middle
to fill this model with the data.

00:21:11.986 --> 00:21:13.816 align:middle
And we can still use the DQL query.

00:21:14.186 --> 00:21:16.996 align:middle
Let's go through it, like
not in chronological order.

00:21:17.266 --> 00:21:21.046 align:middle
So first we see that we fetch all the
stuff that we need for our OrderSummary

00:21:21.356 --> 00:21:25.246 align:middle
and the interesting part here is that
we count the items in the database

00:21:25.276 --> 00:21:28.776 align:middle
and also we use the SUM method in the database.

00:21:29.066 --> 00:21:31.876 align:middle
So we don't have to run the PHP query stuff.

00:21:31.876 --> 00:21:34.426 align:middle
We can actually do this in the
database which is really fast

00:21:34.426 --> 00:21:37.096 align:middle
for doing the kind of integer operations.

00:21:38.206 --> 00:21:41.966 align:middle
Then we still fetch the data
as if it were the Order object.

00:21:42.246 --> 00:21:46.646 align:middle
So we say every data that you would get
from the Order object, just just get it.

00:21:46.946 --> 00:21:49.146 align:middle
And then we extract the data we want.

00:21:49.626 --> 00:21:53.626 align:middle
And then we just create a new
object with our DTO in there.

00:21:54.036 --> 00:21:59.046 align:middle
And basically it will map the data not
to the Order object but to our DTO.

00:21:59.536 --> 00:22:04.156 align:middle
And this will also perform only one
query and it has all the data in there

00:22:04.156 --> 00:22:06.736 align:middle
and we don't even need all the
item information that we don't need

00:22:06.736 --> 00:22:09.706 align:middle
and we just need the stuff,
we get the stuff that we need.

00:22:10.206 --> 00:22:12.056 align:middle
And this is what it would look in plain SQL.

00:22:12.056 --> 00:22:17.776 align:middle
So probably a little bit simpler, but yeah, the,
you just have to translate that back to DQL.

00:22:17.806 --> 00:22:21.146 align:middle
Or you can even use sql and
use the ResultSetMapping

00:22:21.466 --> 00:22:23.596 align:middle
to map it back to the object instead.

00:22:24.336 --> 00:22:28.306 align:middle
And so, just to remind you, this
is the queries that we had before.

00:22:28.706 --> 00:22:32.526 align:middle
And this is what we get now: we have
one query you, can see in the bottom,

00:22:32.526 --> 00:22:38.896 align:middle
it kind of looks like the SQL query we just
saw, Doctrine just uses different identifiers.

00:22:39.406 --> 00:22:45.596 align:middle
And it's also a lot faster, like 3 ms,
roughly 3 ms. And 3 ms doesn't sound

00:22:45.636 --> 00:22:47.446 align:middle
like a lot, but obviously it adds up.

00:22:47.766 --> 00:22:51.296 align:middle
If you have more than six
items, like 1,000 orders.

00:22:52.786 --> 00:22:58.776 align:middle
And yeah. So basically your takeaway for this
is: Doctrine loads, associated entities lazily

00:22:58.776 --> 00:23:04.616 align:middle
by default, which can be good, but it
can also be a problem for querying.

00:23:04.866 --> 00:23:10.316 align:middle
So you can do custom queries with a join
and then select those items yourself.

00:23:10.316 --> 00:23:16.896 align:middle
You, you can do a custom hydrations, either into
a DTO object or if you just need a scalar value,

00:23:16.896 --> 00:23:21.716 align:middle
like a count, you can just get this as well and
you don't even have to wrap it into an object.

00:23:22.076 --> 00:23:24.556 align:middle
And this can improve read
performance tremendously for you.

00:23:25.886 --> 00:23:31.076 align:middle
And something that kind of relates to that,
to optimizing querying, is identity map.

00:23:31.496 --> 00:23:35.646 align:middle
This is also a pattern that that's
wrapped inside the UnitOfWork.

00:23:36.196 --> 00:23:42.566 align:middle
So whenever you call the EntityManager
find() method with the object class name

00:23:42.986 --> 00:23:46.286 align:middle
like Order::class and then
the id you want to fetch.

00:23:46.646 --> 00:23:51.366 align:middle
What will happen is, the first thing that the
EntityManager does is look into the UnitOfWork,

00:23:51.366 --> 00:23:55.716 align:middle
into the identity map to see
if someone, well actually,

00:23:55.716 --> 00:24:01.886 align:middle
if we performed this query earlier before and
we already have the object in this identity map.

00:24:01.886 --> 00:24:04.066 align:middle
And if we do, then it will just get the object

00:24:04.066 --> 00:24:06.596 align:middle
from the identity map and
don't even issue a query.

00:24:07.126 --> 00:24:10.466 align:middle
If not, then obviously it will just
do the database query as before the,

00:24:10.466 --> 00:24:12.416 align:middle
the typical find() method and it's fine.

00:24:12.526 --> 00:24:15.876 align:middle
So, um, just to, to basically
see how this works.

00:24:15.956 --> 00:24:20.036 align:middle
This is very simplified code with just
some, some dump in there to see the results.

00:24:20.436 --> 00:24:26.576 align:middle
So we do the same find() twice and in between we
look at the UnitOfWork and at the end we looked

00:24:26.576 --> 00:24:31.206 align:middle
at the $order and the $sameOrder,
um, are actually the same object.

00:24:32.176 --> 00:24:33.576 align:middle
And yeah, this is what it looks like.

00:24:33.636 --> 00:24:38.756 align:middle
So the identity map contains the class name
and then an array where the ID is the key

00:24:38.986 --> 00:24:40.996 align:middle
and the object itself is the value.

00:24:41.216 --> 00:24:42.846 align:middle
And this is how Doctrine looks it up.

00:24:42.846 --> 00:24:46.216 align:middle
Like, okay, I have this class, I
have this id, the user wants that,

00:24:46.216 --> 00:24:47.936 align:middle
so I have to pass this object on.

00:24:49.206 --> 00:24:54.356 align:middle
And on the bottom you see that yea, both
objects are actually the same identical object.

00:24:54.356 --> 00:25:00.416 align:middle
So every change you do to the object is
basically kept and the when you do find again,

00:25:00.416 --> 00:25:04.766 align:middle
then you get the object that you already had in
memory, it doesn't issue an additional query.

00:25:05.536 --> 00:25:09.556 align:middle
Um, and you can see that, on the bottom as well,
there was only one database query in this case.

00:25:09.836 --> 00:25:13.826 align:middle
And this is basically for our Order
object with the find items, it will,

00:25:14.146 --> 00:25:19.066 align:middle
at the same time also fetch those items as well
and put them into the identity map as well.

00:25:19.416 --> 00:25:23.626 align:middle
So if you want to fetch an OrderItem later on
by its id, then it will also not issue a query

00:25:23.626 --> 00:25:27.636 align:middle
because it already got this item
through the Order with the OrderItems.

00:25:28.236 --> 00:25:32.696 align:middle
And obviously the downside is that
it keeps a lot of data in the memory.

00:25:32.696 --> 00:25:38.126 align:middle
But also it's probably doing one request, you
won't have like dozens and dozens of entities

00:25:38.436 --> 00:25:40.826 align:middle
that it has to keep in the identity
map and, and has to work with.

00:25:41.886 --> 00:25:44.986 align:middle
And yeah, so basically that's
another important point when you want

00:25:44.986 --> 00:25:48.756 align:middle
to improve your read performance,
you have to look out that

00:25:48.756 --> 00:25:53.656 align:middle
when you use the repository's find()
method, it uses the criteria array thing,

00:25:53.656 --> 00:25:56.716 align:middle
which is not the same as the
EntityManager find() method.

00:25:56.716 --> 00:25:59.586 align:middle
So it will actually perform the query twice.

00:26:00.076 --> 00:26:03.776 align:middle
It will still fetch the data from the
identity map, but it does the query

00:26:03.776 --> 00:26:07.736 align:middle
because it can't figure out that, even
if you just fetch the id, the find method

00:26:07.736 --> 00:26:10.686 align:middle
or your custom query, the
EntityManager, the UnitOfWork,

00:26:11.036 --> 00:26:13.966 align:middle
don't know how to introspect
it and figure it out.

00:26:14.226 --> 00:26:15.706 align:middle
But if you're using EntityManager::find(),

00:26:15.706 --> 00:26:20.486 align:middle
then you can actually have fewer
queries than you would expect.

00:26:22.456 --> 00:26:26.596 align:middle
Okay. So we looked at INSERT,
we looked at the find() method.

00:26:26.596 --> 00:26:28.396 align:middle
Let's also look at updates.

00:26:29.926 --> 00:26:33.106 align:middle
Um, so let's assume we have
an object, we create it new.

00:26:33.226 --> 00:26:34.846 align:middle
And then we set the ID.

00:26:35.336 --> 00:26:38.706 align:middle
Some people might assume that
since my object now has an ID,

00:26:38.706 --> 00:26:41.856 align:middle
I can just update this object
if it's already in the database.

00:26:42.456 --> 00:26:46.426 align:middle
And the thing is, obviously, this will not work,

00:26:46.986 --> 00:26:50.336 align:middle
because the UnitOfWork keeps
track of an entity's state.

00:26:51.046 --> 00:26:55.276 align:middle
And since it didn't know the object
before, it, it doesn't know what to do.

00:26:55.536 --> 00:26:57.266 align:middle
It assumes it's a new object.

00:26:57.266 --> 00:26:59.626 align:middle
And so it wants to insert that new object.

00:26:59.626 --> 00:27:05.926 align:middle
Because internally, Doctrine keeps track of
entities not by the ID but by the object hash.

00:27:06.926 --> 00:27:11.616 align:middle
And so Doctrine has a set of
states that it kind of looks

00:27:11.616 --> 00:27:15.536 align:middle
at and, and tries to sort entities into.

00:27:16.256 --> 00:27:21.546 align:middle
Obviously, for new entities, the new state,
the managed state, when UnitOfWork knows

00:27:21.546 --> 00:27:27.246 align:middle
of this object, it's already managed somehow,
that that's both new objects, updated objects

00:27:27.306 --> 00:27:31.346 align:middle
and deleted objects and detached objects.

00:27:31.346 --> 00:27:36.596 align:middle
So objects we don't, no longer want to maintain
via the UnitOfWork and via the EntityManager.

00:27:36.596 --> 00:27:41.066 align:middle
So all the changes we do to that object, they
will not be persisted, they will not be saved.

00:27:41.656 --> 00:27:44.676 align:middle
And removed objects, or something
that's basically said that:

00:27:44.906 --> 00:27:46.956 align:middle
once you do flush, we want to delete this.

00:27:48.036 --> 00:27:49.496 align:middle
This is how it looks on the code.

00:27:49.896 --> 00:27:52.166 align:middle
Um, there are some nice explanations in there.

00:27:52.786 --> 00:27:59.596 align:middle
And so basically what happens is, since we
created a new object, not via the UnitOfWork

00:27:59.596 --> 00:28:03.636 align:middle
and the EntityManager, but by ourselves,
the UnitOfWork doesn't know what kind

00:28:03.636 --> 00:28:06.546 align:middle
of object is this, and it
says: ah, this must be new,

00:28:06.546 --> 00:28:09.126 align:middle
I will give it the new state
and I will insert it.

00:28:09.726 --> 00:28:16.516 align:middle
And on the other hand, if we fetch an object
via the EntityManager, the UnitOfWork now knows

00:28:16.576 --> 00:28:19.226 align:middle
that this entity was fetched before,

00:28:19.416 --> 00:28:23.596 align:middle
it's already part of the UnitOfWork
inside the identity map for example.

00:28:23.986 --> 00:28:26.626 align:middle
And that's why, when we do
this, we no longer need

00:28:26.626 --> 00:28:29.406 align:middle
to persist obviously, because
it's already in there.

00:28:29.406 --> 00:28:33.006 align:middle
Now it knows that I can update this
object: this is not something new,

00:28:33.006 --> 00:28:34.466 align:middle
this is something I have to update.

00:28:35.016 --> 00:28:41.426 align:middle
And so basically, for you, what you
have to look out for is, just, kind of,

00:28:41.426 --> 00:28:43.836 align:middle
keep in mind that the UnitOfWork
manages the state for you.

00:28:43.836 --> 00:28:47.386 align:middle
And you don't, you have to make
sure that everything you want

00:28:47.386 --> 00:28:49.886 align:middle
to insert is part of the inserts sets and so on.

00:28:49.956 --> 00:28:51.956 align:middle
So yeah, it's, it's just, it's a lot.

00:28:51.956 --> 00:28:54.216 align:middle
I know last session, but we're almost done.

00:28:55.706 --> 00:28:59.856 align:middle
So finally, which is kind of
unrelated to everything before but,

00:28:59.856 --> 00:29:03.176 align:middle
but I promise it in the abstract,
so I figured I have to deliver it,

00:29:03.426 --> 00:29:05.986 align:middle
is a kind of comparison to, to active record.

00:29:05.986 --> 00:29:10.646 align:middle
So I don't know how many of you know
that Doctrine uses the so-called

00:29:10.646 --> 00:29:12.796 align:middle
"data mapper" pattern to map things.

00:29:13.716 --> 00:29:16.446 align:middle
And another famous approach as active record.

00:29:16.716 --> 00:29:22.546 align:middle
Actually Doctrine 1 used it, Propel was
another famous object relational mapper,

00:29:22.546 --> 00:29:23.896 align:middle
that uses active record pattern.

00:29:24.386 --> 00:29:27.186 align:middle
In Ruby on Rails you have the,
I don't know what it's called.

00:29:27.676 --> 00:29:31.196 align:middle
And obviously Laravel is
famously using Eloquent,

00:29:31.196 --> 00:29:33.116 align:middle
which is also using the active record pattern.

00:29:33.616 --> 00:29:41.596 align:middle
And what the active record pattern does is it
wraps an object in a way that everything related

00:29:41.596 --> 00:29:44.546 align:middle
to the database is part of this object.

00:29:44.966 --> 00:29:49.366 align:middle
So usually what happens is you extend
the base model, base record or whatever,

00:29:49.606 --> 00:29:53.326 align:middle
and in this base record you have
all the database-related stuff.

00:29:53.326 --> 00:29:57.856 align:middle
You can query things, you can save things
and then you create your new entity,

00:29:57.856 --> 00:30:02.386 align:middle
with some restrictions as to
how the entity is created.

00:30:02.386 --> 00:30:05.686 align:middle
And and then you can do all the
database operations on there.

00:30:06.066 --> 00:30:10.766 align:middle
So basically the models allow for, for querying
the data and you don't need special classes

00:30:10.806 --> 00:30:15.946 align:middle
like the EntityManager or repository or anything
else, you just do everything for the record.

00:30:16.336 --> 00:30:21.096 align:middle
So this is how it looked in doctrine
1: the abstract Doctrine_Record class.

00:30:21.376 --> 00:30:22.916 align:middle
This would be what you would extend.

00:30:23.136 --> 00:30:26.316 align:middle
And you can already see that
there are some states in there,

00:30:26.316 --> 00:30:31.156 align:middle
so it kind of still does all the
same things that Doctrine 2 does

00:30:31.286 --> 00:30:34.766 align:middle
with the keeping the entity states, for example.

00:30:34.766 --> 00:30:40.236 align:middle
So there's this kind of the same feature set,
but everything is part of this basic model.

00:30:40.586 --> 00:30:43.526 align:middle
And sure there are things that work differently

00:30:43.526 --> 00:30:49.166 align:middle
but there's even a proxy thing,
so it kind of looks the same.

00:30:49.606 --> 00:30:55.276 align:middle
So just to give you kind of look at how you
would act on an active record kind of model.

00:30:55.276 --> 00:30:59.306 align:middle
And I didn't put the, the
entities on there as a record,

00:30:59.566 --> 00:31:02.446 align:middle
because based on the library they
will look differently anyway.

00:31:03.056 --> 00:31:05.546 align:middle
But roughly, this is what would change.

00:31:05.546 --> 00:31:09.496 align:middle
So first of all, since we don't have the
EntityManager anymore, all operations are

00:31:09.496 --> 00:31:15.276 align:middle
on our model, we just call an $order-&gt;save()
and this bubbles down to the record and this is

00:31:15.276 --> 00:31:17.166 align:middle
where everything is implemented,
it uses a connection.

00:31:17.616 --> 00:31:18.556 align:middle
Same with an update.

00:31:18.646 --> 00:31:22.586 align:middle
Basically instead of getting the
EntityManager to find our object,

00:31:22.776 --> 00:31:30.106 align:middle
we use a static method called for find() for
example or query to get a new Order object.

00:31:30.526 --> 00:31:32.446 align:middle
And obviously the flush() has to go as well.

00:31:32.446 --> 00:31:33.836 align:middle
We still do the $order-&gt;save().

00:31:34.226 --> 00:31:37.746 align:middle
and so we don't need any additional
classes, which might seem nice.

00:31:37.746 --> 00:31:39.826 align:middle
We actually saw that the code kind

00:31:39.826 --> 00:31:44.296 align:middle
of gets a little bit more compact,
so that's less stuff to do.

00:31:44.686 --> 00:31:51.796 align:middle
And just just to keep kind of a record of
what are the benefits and drawbacks of it.

00:31:51.796 --> 00:31:55.366 align:middle
Um, because it, it really
depends on what your use cases.

00:31:55.876 --> 00:32:00.886 align:middle
Um, so if you look at the data
mapper, um, what's really neat is

00:32:00.986 --> 00:32:05.146 align:middle
that basically you don't have to care about all
these additional classes doing all these things.

00:32:05.236 --> 00:32:09.946 align:middle
Everything is inside my model and I don't
have to to remember to inject anything.

00:32:09.946 --> 00:32:13.626 align:middle
I can just work with my object and do
everything on it that I want to do,

00:32:13.626 --> 00:32:15.686 align:middle
like saving stuff which can be nice.

00:32:15.976 --> 00:32:19.436 align:middle
It's, I don't have to use injection in
the service to get the EntityManager,

00:32:19.436 --> 00:32:21.826 align:middle
I'll just pass the object and say save.

00:32:21.826 --> 00:32:23.246 align:middle
And that's it.

00:32:23.636 --> 00:32:30.316 align:middle
And obviously this comes with a downside that,
that my object has to fit some conventions

00:32:30.376 --> 00:32:34.506 align:middle
that this record gives me, to,
to basically be able to figure

00:32:34.506 --> 00:32:36.226 align:middle
out what stuff to write and what not.

00:32:36.676 --> 00:32:39.696 align:middle
And with Doctrine you do it
very implicit, ah explicitly.

00:32:39.696 --> 00:32:42.376 align:middle
You put the annotations on
there, you have the yaml file.

00:32:42.696 --> 00:32:47.086 align:middle
But with an active record, you basically have
to figure out what do they want me to do?

00:32:47.086 --> 00:32:50.146 align:middle
Where do I have to store my properties,
how do I give it the table name?

00:32:50.526 --> 00:32:54.976 align:middle
Um, maybe there are some limitations,
like usually you can't use the constructor

00:32:55.146 --> 00:33:01.026 align:middle
because this initializes some, some basic
database stuff which can be annoying,

00:33:01.206 --> 00:33:05.476 align:middle
when you want to do like, rich domain models for
example, and you want to have this constructor,

00:33:05.636 --> 00:33:07.516 align:middle
you have to remember to,
to call parent construct.

00:33:08.686 --> 00:33:12.526 align:middle
And yeah, the, the obvious benefit
is that it's less code to write.

00:33:12.526 --> 00:33:16.546 align:middle
It's just easy: save, no
EntityManager, no custom repositories,

00:33:16.576 --> 00:33:18.216 align:middle
you can just go ahead and do things.

00:33:18.976 --> 00:33:21.056 align:middle
And just to wrap things up.

00:33:21.506 --> 00:33:22.516 align:middle
So what did we look at?

00:33:22.596 --> 00:33:30.236 align:middle
First of all, um, the, the Doctrine
EntityManager uses underneath the UnitOfWork

00:33:30.426 --> 00:33:36.386 align:middle
which does all the heavy lifting and storing
the entity changes until they are persisted.

00:33:36.386 --> 00:33:39.486 align:middle
It takes care of the commit
order and everything.

00:33:40.706 --> 00:33:46.736 align:middle
The proxies for, for finding stuff are useful
that it basically allows us to lazily load stuff

00:33:47.136 --> 00:33:51.136 align:middle
if we want to, and if not then we can
just bypass it by writing custom queries.

00:33:52.126 --> 00:33:56.956 align:middle
And the identity map as well for finding
stuff is really useful when it comes

00:33:57.046 --> 00:34:02.656 align:middle
to minimizing queries and to make sure that
we, when we fetch an object from the database

00:34:03.216 --> 00:34:07.346 align:middle
and it's something that we worked on before
that, that it still has the same state:

00:34:07.346 --> 00:34:14.396 align:middle
we work on a consistent object and not like
one OrderItem of the name x and one OrderItem

00:34:14.396 --> 00:34:19.766 align:middle
of the name y, and then we want to save it, they
don't really fit together or the last one wins.

00:34:20.286 --> 00:34:23.516 align:middle
And yeah, that's basically it.

00:34:23.636 --> 00:34:26.706 align:middle
So I don't know how much time I have left.

00:34:27.416 --> 00:34:30.606 align:middle
I think I rushed through it quite
a lot more than I would have to.

00:34:30.956 --> 00:34:45.106 align:middle
Um, so yeah, plenty of times
for questions I guess.

00:34:45.316 --> 00:34:47.336 align:middle
Yeah. Wait, there's a microphone.

00:34:48.506 --> 00:34:54.036 align:middle
Cool, thanks, thanks for catching
that, so I don't look bad.

00:34:54.626 --> 00:34:58.586 align:middle
(unaudible) Doctrine to handle
concurrent persistent

00:34:58.626 --> 00:35:00.816 align:middle
in different processes, the same database?

00:35:01.726 --> 00:35:06.506 align:middle
Um, so, so again, uh, how does
Doctrine handle different repositories?

00:35:06.616 --> 00:35:11.986 align:middle
No, if Doctrine is running into
2 processes, php processes?

00:35:11.986 --> 00:35:13.656 align:middle
In different PHP processes.

00:35:13.656 --> 00:35:17.176 align:middle
Yeah. So, um, when you have
different PHP processes,

00:35:17.206 --> 00:35:19.746 align:middle
you will obviously have different unit of works.

00:35:20.456 --> 00:35:26.936 align:middle
So there, things will, will not apply, in
terms of, you will not have the identity map

00:35:26.936 --> 00:35:29.226 align:middle
from one process work with the other process.

00:35:29.786 --> 00:35:34.796 align:middle
Um, I'm not sure if there's some
common caching you could use,

00:35:34.796 --> 00:35:36.556 align:middle
like the l2 caching things like that.

00:35:36.556 --> 00:35:37.556 align:middle
I haven't looked into that.

00:35:38.026 --> 00:35:43.766 align:middle
Um, but yea, so those things are really,
if you work on one php process and,

00:35:43.766 --> 00:35:47.086 align:middle
and you just want to access your data there,
which is kind of the most common use case.

00:35:47.326 --> 00:35:50.396 align:middle
I can't really tell you how it
works with multiple PHP process.

00:35:50.786 --> 00:35:54.896 align:middle
So, um, everything is good.

00:35:55.696 --> 00:35:59.266 align:middle
Um, I think there was someone in
the back who had a question or not.

00:36:00.166 --> 00:36:04.486 align:middle
Okay. Uh, since we all have some time,
I don't know how eagerly you want

00:36:04.486 --> 00:36:06.666 align:middle
to go to, to the jeopardy, I kinda do.

00:36:06.666 --> 00:36:12.776 align:middle
But, um, I, I have some code if you kind
of feel that this, this was like rushing

00:36:12.776 --> 00:36:15.936 align:middle
through everything and just
getting a glimpse here and there.

00:36:16.136 --> 00:36:20.076 align:middle
If you want, I can give you a quick
rundown of the code for, for example,

00:36:20.076 --> 00:36:23.966 align:middle
the querying of how it looks in a
real project to make it more hands-on

00:36:23.966 --> 00:36:25.146 align:middle
and a little bit more approachable.

00:36:25.676 --> 00:36:27.166 align:middle
Um, I see someone not?

00:36:27.576 --> 00:36:30.326 align:middle
Okay, then let's just do
that for, for five minutes.

00:36:30.896 --> 00:36:35.636 align:middle
And whoever else wants to leave for, for
the, the Jeopardy or just to get some drinks

00:36:35.636 --> 00:36:37.486 align:middle
or whatever, feel free to do that.

00:36:41.046 --> 00:36:44.676 align:middle
So only two minutes.

00:36:45.146 --> 00:36:49.486 align:middle
Okay then, then we will do it really fast.

00:36:49.686 --> 00:36:50.616 align:middle
I, I'm used to that.

00:36:50.726 --> 00:36:52.616 align:middle
So I already did this with the talk.

00:36:53.456 --> 00:37:01.176 align:middle
So, um, let's look at our
list orders controller.

00:37:02.106 --> 00:37:06.866 align:middle
So in this case I used an invokable controller.

00:37:06.866 --> 00:37:09.266 align:middle
So one controller only has
one action, the invoke action.

00:37:10.736 --> 00:37:13.036 align:middle
Um, oh, it doesn't, wait a second.

00:37:13.266 --> 00:37:16.486 align:middle
Well, since the time it's up anyway.

00:37:16.486 --> 00:37:17.466 align:middle
Let's do it differently.

00:37:17.466 --> 00:37:22.086 align:middle
Whoever was interested, you can come up
and I will, I will show you on my notebook

00:37:22.506 --> 00:37:25.386 align:middle
and since I can't get the screen to work.

00:37:25.386 --> 00:37:29.566 align:middle
And everyone else, thanks for staying
here, for, for listening to my talk.

00:37:29.926 --> 00:37:31.586 align:middle
Please give me feedback.

00:37:31.916 --> 00:37:38.866 align:middle
Um, and yeah, have a good day
and hopefully see you around.

