db:seed Command Overview0:00
Like we've been doing with a lot of the other lessons, in this video, let's go behind the scenes and figure out how all of this database seeding is orchestrated. The first thing we might want to look at is this. Well, we run php artisan db:seed, and that magically calls our master database seeder by default. But if I were to do a quick help on this, you'll see that we can also pass a class option. So this would be if you don't want to call that root database seeder, if you want to call the PostsTableSeeder, well, you could pass that through as an option, and we will only trigger that one. Okay, so maybe that's a good entry point. Let's just figure out what happens when we call this command. Now, if I switch back to my editor, you can often guess what the name of a command class is. For example, I could do something like Seeder commands, and I don't see it there, so maybe Seed, and there we go. Or, these classes will typically
what the name of a command class is. For example, I could do something like seeder commands, and I don't see it there, so maybe seed, and there we go. Or, these classes will typically be stored within your Illuminate\Database folder within the vendor directory. So you could look for Illuminate\Database, and then we could hunt down any commands, and there we go. Seed command, as well as lots of the other commands that you can run. Cool. So if we take a look, here's the name of the command that you would trigger from the console, so we know this is right. And if we scroll down, well, let's see exactly what happens. When you run an artisan command, the fire method will be triggered by default. So yeah, it looks pretty simple. We call this confirm to proceed, and if I scroll to the top, you'll see that we pull in a ConfirmableTrait. When you create your own artisan commands, you can pull this in as well if you want. And the main thing that this does is,
Production Confirmation Check1:29
and if I scroll to the top, you'll see that we pull in a ConfirmableTrait. When you create your own artisan commands, you can pull this in as well if you want. And the main thing that this does is, well, it protects you in the production environment. For example, imagine that by mistake you had a different tab open in the console that was set to your production server rather than your local VM. Well, imagine if we didn't do a little bit of checking there or a little bit of security. You run php artisan db:seed, and it truncates your entire production database and replaces it with a bunch of dummy data. Imagine how unbelievably bad that would be. So instead, well, we ask you to confirm to proceed, doing something as simple as, are you sure you want to run this in production? I'll show you this in action, in fact. If we temporarily set our environment to production, and if we were to run this, you'll see this in action. There you go. Do you really wish to run
I'll show you this in action, in fact. If we temporarily set our environment to production, and if we were to run this, you'll see this in action. There you go. Do you really wish to run this command? You're in production, so you probably don't want to do this, but are you sure? And if you say yes, we'll go ahead and do it, but you probably want to back out. Okay, so let's bring that back and figure out what goes on here. Well, the first step is you can pass a closure when you call confirm to proceed, but if you don't, we'll just use a default callback. And if we take a look at that, it's literally just returning a closure here where we check to see is the current environment production, and if it is, well, we want to confirm to proceed. So if that returns a true value, well, if you pass the force option, meaning if I were to say force, well, we will ignore this and force it to run without any kind of confirmation. But you probably won't have that, so instead we
well, if you pass the --force option, meaning if I were to say --force, well, we will ignore this and force it to run without any kind of confirmation. But you probably won't have that, so instead we will build up the output here, and that's exactly what you see here. Just a bunch of stars to make it look nice and pretty, and then we call an artisan command, this confirm, where we ask them do you really wish to proceed. Now, when the User types y or n, that will be translated into a Boolean. So we can say if they did not confirm, they definitely do not want to do this, so let's echo out command cancelled, which is exactly what happened here, and then finally return false. Otherwise, they do want to proceed, so we return true. And that's it for this trait. You can use that in any of your artisan commands. Okay, so if we switch back, now we know that part. If they didn't confirm to proceed, don't proceed. Otherwise, well, what's going on here? This resolver set
Selecting Database Connection3:52
that in any of your artisan commands. Okay, so if we switch back, now we know that part. If they didn't confirm to proceed, don't proceed. Otherwise, well, what's going on here? This resolver set default connection, and then we call this getDatabase. Mostly you don't have to worry about this too much. We are setting the default connection to either whatever is the default value in your database configuration file right here, sqlite, but sometimes you'll want to run this on a different connection. So you'll see that we get an option right here, and if the user provided that doing something like this, well, we know that they want to run this on a different connection. So this method will either return what you pass or whatever you have set as the default connection. Okay, so if we scroll back up, then we just pass that to setDefaultConnection. You can see this is just the database connection resolver. Like I said, don't worry about this too much if this
Resolving the Seeder Class4:41
Okay, so if we scroll back up, then we just pass that to setDefaultConnection. You can see this is just the database connection resolver. Like I said, don't worry about this too much if this is confusing. It's just an option to set the default connection that you want this command to run under. Okay, so next, well, we get the seeder, and then we call that run method. We already learned about this. LessonsTableSeeder, we have a run method. Okay, so how do we get the seeder? Well, we use Laravel's container. Same thing as if you did this, app, or in this case, Laravel, we're getting the container or the Laravel application, and then we're calling make. Or from the Laravel four days, or you can still do this now, same thing here. Okay, so we are resolving whatever the class is out of the IOC container. And if you remember at the beginning of the video, I talked about this. You can call class to be explicit about which database file you want to
whatever the class is out of the IOC container. And if you remember at the beginning of the video, I talked about this. You can call class to be explicit about which database file you want to seed or run. Now, what happens if you don't pass any, though? Well, you can see we have a default here. So if you don't pass anything here, we'll use the default of the DatabaseSeeder class. And that's why when you run php artisan db:seed, this file gets resolved out of the container, and we trigger a run method on it. Okay, cool. This all seems to make good sense. So if I scroll back up, we get the seeder, we resolve it out of the container, and then what's this? We call two setters here, setContainer and setCommand. Okay, well, on the Seeder class, let's go to DatabaseSeeder, and you'll see that it extends the Seeder class. So here is where you will find those two methods, setContainer and setCommand. Here we just set the
How Seeder call() Works6:16
on the Seeder class, let's go to DatabaseSeeder, and you'll see that it extends the Seeder class. So here is where you will find those two methods, setContainer and setCommand. Here we just set the current layer of Laravel Container, and then the command is to set the current artisan command that is being triggered. But you're probably wondering, well, why do we have to do this? What is the point of this? I'll show you. Let's take a look at a little bit more of this. Well, we know at this point the DatabaseSeeder class has been resolved out of the container, and we called a run method. So when we run php artisan db:seed, we've learned enough to know that this method body will be triggered. But now what about call? How does call work? Okay, well, let's go back and take a look. call. And really, it looks about the same. Once again, we resolve whatever class you pass. So remember, if I say this call LessonsTableSeeder, well, that's going to resolve this class name out
Call. And really, it looks about the same. Once again, we resolve whatever class you pass. So remember, if I say this call LessonsTableSeeder, well, that's going to resolve this class name out of the container. Think of that as just newing it up, but it has some perks that go with it. If you have dependencies declared in the constructor, those will automatically, if possible, be resolved themselves and passed through for you. We call that automatic resolution. So anyways, we resolve that, and then we call a run method on that class. So we can see right here, when we call UsersTableSeeder, we're just newing it up, essentially, and calling a run method on that class, like so. Okay, but let's go back here, because, well, we're not saying anything like app class run. So what happens with this resolve method? Let's see. Well, we have a couple checks here, actually. We're checking to see if the container was set. So do we have a Laravel
app class run. So what happens with this resolve method? Let's see. Well, we have a couple checks here, actually. We're checking to see if the container was set. So do we have a Laravel container available? And we know already that we do. If we go back right here, we set the container right here. So that means, yes, we have a container. So once again, we resolve the class out of the container, like this, UsersTableSeeder. And then on that instance, we'll once again set the container. Okay, cool. Now, otherwise, if we don't have a container, we just new it up. So nothing more than new UsersTableSeeder. Basic stuff. And then finally, if we did set a command on this current object, well, after we have our instance, we want to set the command on that one as well. Okay, cool. So not that complicated. Resolve the child DatabaseSeeder and call a run method on it. But now, if you're anything like me, you might be thinking, well, why does this exist here?
Why Seeders Output Status8:45
So not that complicated. Resolve the ChildDatabaseSeeder and call a run method on it. But now, if you're anything like me, you might be thinking, well, why does this exist here? If we have a command, that's sort of just saying, if the user triggered this from the command line, well, after we run this, we want to say that the class was successfully seeded. But you might be thinking, well, why does this exist here? Why not instead place it within your seed command, which is the artisan command where you would provide output? Why wouldn't it be placed somewhere right here? Something like this, this->info('seeded'). And the reason is because of this. If you were to simply call php artisan db:seed, where we defer to the DatabaseSeeder, and it does some stuff and returns, that would really be fine. You could put the output within the artisan command. But within here, you can call any number of other classes that need to be seeded. And the
does some stuff and returns, that would really be fine. You could put the output within the artisan command. But within here, you can call any number of other classes that need to be seeded. And the db:seed command knows nothing about this. So that's why within the seeder, well, we accept the command object as a dependency and then do the writeLine or the info call directly from here. When we call usersTableSeeder, resolve it out of the container, call a run method on it. And then if we have that command object property, well, let's provide some feedback to the user that says, yes, we just seeded this specific class that you called from your database seeder. And you know what? That's really all there is to it. This isn't the most complicated stuff in the world. So now, if in the past you were using db:seed and seed classes, just trusting that it would work, well, we've taken a look behind the curtain and we've realized, hey,
if in the past you were using dbSeed and seed classes, just trusting that it would work, well, we've taken a look behind the curtain and we've realized, hey, this is pretty easy stuff to understand if we just take the time to look.
