WEBVTT NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com 00:00:01.016 --> 00:00:05.596 align:middle Doctrine is an ORM: an object relational mapper. 00:00:06.016 --> 00:00:09.906 align:middle That's a fancy way of saying that, for each table in the database, 00:00:10.186 --> 00:00:13.276 align:middle we will have a corresponding class in PHP. 00:00:13.276 --> 00:00:18.906 align:middle And for each column on that table, there will be a property in that class. 00:00:19.656 --> 00:00:24.156 align:middle When you query for a row in a table, Doctrine will give you an object 00:00:24.156 --> 00:00:26.656 align:middle with that row's data set on the properties. 00:00:27.506 --> 00:00:32.586 align:middle So if you want to create a database table in Doctrine, the way you do that is actually 00:00:32.586 --> 00:00:35.356 align:middle by creating the class it will map to. 00:00:36.306 --> 00:00:41.666 align:middle These "classes" that map to tables have a special name: entity classes. 00:00:42.616 --> 00:00:47.966 align:middle You can create an entity class by hand - there's nothing very special about them. 00:00:48.856 --> 00:00:50.146 align:middle But... come on! 00:00:50.536 --> 00:00:52.266 align:middle There's a much easier way. 00:00:52.266 --> 00:00:57.066 align:middle Find your terminal and run one of my favorite bin/console commands: 00:00:57.066 --> 00:01:04.486 align:middle php bin/console make:entity You can also run: symfony console make:entity It doesn't matter 00:01:04.486 --> 00:01:09.756 align:middle in this case, because this command won't talk directly to the database, and so, 00:01:10.036 --> 00:01:12.346 align:middle it doesn't need the environment variables. 00:01:13.006 --> 00:01:15.266 align:middle This command just generates code. 00:01:16.316 --> 00:01:20.826 align:middle Now remember: the whole point of our site is for witches and wizards 00:01:20.856 --> 00:01:23.596 align:middle to ask questions and then post answers. 00:01:24.326 --> 00:01:28.266 align:middle So the very first thing we need is a Question entity. 00:01:28.266 --> 00:01:31.436 align:middle So, a question table in the database. 00:01:32.116 --> 00:01:33.056 align:middle Enter Question. 00:01:33.916 --> 00:01:38.246 align:middle The command immediately starts asking what properties we want, which really, 00:01:38.246 --> 00:01:41.136 align:middle also means what columns we want in the table. 00:01:41.916 --> 00:01:43.136 align:middle Let's add a few. 00:01:43.776 --> 00:01:48.176 align:middle Call the first one name - that will be the short name or "title" 00:01:48.176 --> 00:01:50.856 align:middle of the question like "Reversing a Spell". 00:01:52.876 --> 00:01:55.576 align:middle The command then asks what "type" we want. 00:01:56.246 --> 00:01:58.966 align:middle Doctrine has its own type system: enter "?" 00:01:58.966 --> 00:02:00.756 align:middle to see the full list. 00:02:01.506 --> 00:02:05.736 align:middle These aren't MySQL column types, but each maps to one. 00:02:05.736 --> 00:02:10.556 align:middle For example, a string maps to a VARCHAR in MySQL. 00:02:11.086 --> 00:02:12.816 align:middle And there are a bunch more. 00:02:13.456 --> 00:02:19.776 align:middle In our case, choose string: that's good for any text 255 characters or less. 00:02:19.776 --> 00:02:23.926 align:middle For the column length, I'll use the default 255. 00:02:24.976 --> 00:02:29.186 align:middle The next question says: Can this field be nullable in the database? 00:02:29.746 --> 00:02:35.536 align:middle Say "No". This means that the column will be required in the database. 00:02:36.106 --> 00:02:37.556 align:middle And... congrats! 00:02:37.806 --> 00:02:40.156 align:middle We just added our first field! 00:02:40.946 --> 00:02:41.776 align:middle Let's add a few more. 00:02:42.306 --> 00:02:49.646 align:middle Call the next slug: this will be the URL-safe version of the name that shows up in the URL. 00:02:50.666 --> 00:02:55.296 align:middle It will also be a string, let's set its length to 100 and, 00:02:55.526 --> 00:02:58.906 align:middle once again, I'll say "no" to "nullable". 00:02:58.906 --> 00:03:03.626 align:middle For the actual body of the question, let's call it question. 00:03:04.346 --> 00:03:07.606 align:middle This will be long, so we can't use the string type. 00:03:09.616 --> 00:03:11.906 align:middle Instead, use text... 00:03:11.906 --> 00:03:14.626 align:middle and make this also required in the database. 00:03:15.486 --> 00:03:18.396 align:middle Add one more field: askedAt. 00:03:19.306 --> 00:03:23.956 align:middle This will be a date field - kind of like a "published at" field. 00:03:23.956 --> 00:03:26.456 align:middle For the type, ooh! 00:03:26.736 --> 00:03:30.966 align:middle It recommends datetime - that is exactly what we want! 00:03:31.676 --> 00:03:35.046 align:middle Hit enter and this time say "yes" to nullable. 00:03:35.936 --> 00:03:41.586 align:middle The idea is that users will be able to start writing a question and save it to the database 00:03:41.586 --> 00:03:45.606 align:middle with a null askedAt because it's not finished. 00:03:46.406 --> 00:03:50.886 align:middle When the user is finished and ready to post it, then we would set that value. 00:03:51.726 --> 00:03:52.956 align:middle And... we're done! 00:03:53.406 --> 00:03:56.956 align:middle Hit enter one more time to exit make:entity. 00:03:57.786 --> 00:03:59.756 align:middle So... what did this do? 00:04:00.546 --> 00:04:06.376 align:middle Well, first, I'll tell you that this made absolutely no changes to our database: 00:04:06.646 --> 00:04:09.366 align:middle we do not have a question database table yet. 00:04:09.366 --> 00:04:15.696 align:middle If you scroll back up to the top of the command, you can see that it created 2 files: 00:04:16.076 --> 00:04:22.126 align:middle src/Entity/Question.php and src/Repository/QuestionRepository.php. 00:04:22.126 --> 00:04:28.086 align:middle For now, completely ignore the repository class: it's not important 00:04:28.086 --> 00:04:29.626 align:middle yet and we'll talk about it later. 00:04:30.406 --> 00:04:34.556 align:middle This entity class, however, is super important. 00:04:35.146 --> 00:04:38.376 align:middle Go open it up: src/Entity/Question.php. 00:04:38.376 --> 00:04:43.486 align:middle As we talked about, we're going to have one class per table. 00:04:44.216 --> 00:04:46.996 align:middle The first thing I want you to notice is that... 00:04:47.206 --> 00:04:49.606 align:middle there's nothing special about this class. 00:04:50.176 --> 00:04:52.426 align:middle It's a boring, normal class... 00:04:52.606 --> 00:04:55.226 align:middle it doesn't even extend a base class! 00:04:55.896 --> 00:05:01.596 align:middle It has several private properties and, to access those, the command generated getter 00:05:01.596 --> 00:05:05.746 align:middle and setter methods, like getName(), getSlug() and setSlug(). 00:05:06.626 --> 00:05:09.576 align:middle It's just about the most boring class you'll ever see. 00:05:10.276 --> 00:05:14.556 align:middle But of course, if Doctrine is going to map this class and its properties 00:05:14.556 --> 00:05:17.786 align:middle to a database table, it's needs to know a few things. 00:05:17.786 --> 00:05:22.516 align:middle For example, it needs to know that the name property should map 00:05:22.516 --> 00:05:26.956 align:middle to a name column and that its type is a string. 00:05:27.776 --> 00:05:31.266 align:middle The way that Doctrine does this is by reading annotations. 00:05:31.746 --> 00:05:36.366 align:middle Well, you can also use XML, but I love annotations. 00:05:36.366 --> 00:05:44.576 align:middle For example, the @ORM\Entity() above the class is what actually tells Doctrine: Hey! 00:05:44.946 --> 00:05:48.116 align:middle This is not just a normal, boring PHP class. 00:05:48.506 --> 00:05:54.366 align:middle This is an "entity": a class that I want to be able to store in the database. 00:05:55.476 --> 00:06:00.226 align:middle Then, the @ORM\Column() above the properties is how Doctrine knows 00:06:00.226 --> 00:06:03.746 align:middle which properties should be stored in the table and their types. 00:06:04.666 --> 00:06:09.456 align:middle Now, there are a bunch of different annotations and options you can use to configure Doctrine. 00:06:09.916 --> 00:06:14.066 align:middle Most are pretty simple - but let me show you am awesome reference. 00:06:14.066 --> 00:06:21.166 align:middle Search for doctrine annotations reference to find a really nice spot on their site 00:06:21.366 --> 00:06:26.156 align:middle where you can see a list of all the different possible annotations and their options. 00:06:26.156 --> 00:06:30.576 align:middle For example, @Column() tells you all the different options 00:06:30.576 --> 00:06:33.516 align:middle that you can pass to it, like a name option. 00:06:33.516 --> 00:06:38.356 align:middle So if you wanted to control the name of the slug column - 00:06:38.486 --> 00:06:41.266 align:middle instead of letting Doctrine determine it automatically - 00:06:41.736 --> 00:06:43.986 align:middle you would do that by adding a name option. 00:06:44.776 --> 00:06:48.186 align:middle One of the other annotations that you'll see here is @Table. 00:06:48.806 --> 00:06:53.386 align:middle Oh, and notice, in the docs, the annotation will be called @Table. 00:06:53.746 --> 00:06:58.556 align:middle But inside Symfony, we always use @ORM\Table. 00:06:59.146 --> 00:07:01.016 align:middle Those are both referring to the same thing. 00:07:01.906 --> 00:07:08.116 align:middle Anyways, if you wanted to control the name of the table, we could say @ORM\Table() 00:07:08.286 --> 00:07:11.686 align:middle and pass it name="" with some cool table name. 00:07:12.386 --> 00:07:16.906 align:middle But I won't bother doing that because Doctrine will guess a good table name from the class. 00:07:17.846 --> 00:07:23.656 align:middle Oh, and by the way, the auto-completion that you're seeing on the annotations comes from the 00:07:23.656 --> 00:07:26.246 align:middle "PHP Annotations" plugin in PhpStorm. 00:07:27.096 --> 00:07:28.566 align:middle Ok: status check! 00:07:28.946 --> 00:07:32.736 align:middle The make:entity command helped us create this new entity class, 00:07:33.046 --> 00:07:35.866 align:middle but it did not talk to the database. 00:07:36.146 --> 00:07:38.426 align:middle There is still no question table. 00:07:39.216 --> 00:07:40.986 align:middle How do we create the table? 00:07:41.676 --> 00:07:43.856 align:middle By generating a migration. 00:07:44.546 --> 00:07:47.416 align:middle Doctrine's migrations system is amazing. 00:07:47.906 --> 00:07:53.696 align:middle It will even allow us to perform table changes with basically zero work. 00:07:54.316 --> 00:07:55.846 align:middle Let's find out how next.