3.1 Creating a Database Structure and Seeding Data
In this lesson, we’ll begin our store app by creating a database structure. We’ll create our models and seed our new database with some test data.
1.Introduction1 lesson, 01:04
2.Getting Ready3 lessons, 09:01
3.Using Cashier4 lessons, 38:13
4.Conclusion1 lesson, 01:32
3.1 Creating a Database Structure and Seeding Data
In this lesson, we're going to be preparing our database by creating some tables and saving some data. When we configured Laravel earlier, we changed the database to one called Cashier. We're going to need to create that database so I'm going to do that through the MySQL Workbench. I'll connect to my Homestead connection and on the left, we can right-click and select Create Schema. And we'll name the schema Cashier. Then we'll simply hit the Apply button and then in the next window, we'll hit Apply again to execute the query. So we've got our Cashier database although it doesn't have any tables yet. So let's go ahead and look at some migrations that we can run. By default, Laravel ships with two migrations, one for a user's table and another for a password resets table. We won't be worrying about password resets, so let's start by deleting the Password Resets Migration file. We are going to have a users table, though, so let's just quickly look at that migration. It's a pretty simple migration. It creates the user's table in the up method and drops it in the down method. We don't need all of these columns. However for the sake of simplicity, we'll just leave these migration as it is. So let's run this users table migration. In our terminal, make sure your SS edged into Homestead if you're doing this on Homestead and then we'll simply run php arson migrate because this is the first time that we've ran migrations, the migrations table will be created for us as well. Now let's just quickly switch back to the MySQL Workbench and we'll refresh our tables for the Cashier database. We now have two tables, the migrations table and our users table, and we can use the table inspector to check the columns on our users table. Now the next migration that we want to run is part of the Cashier component. It will create a few more columns on the users table that would be used by Cashier when we communicate with the strap API. To run this migration, we must first have it created. The Cashier component contains an artisan command that will do this for us. But before we can use it, we need to make sure that the Cashier's service provider is loaded. In our config/app.php file, let's reference the Laravel Cashier service provider in our providers array. Now then, back in our terminal let's run php artisan cashier:table. And for the argument, we'll pass in users cuz that's the table that we want the columns created on. Let's take a quick look at the migration that was just created. It will be called add_cashier_columns. So this migration will add some columns to our users table. It will add a stripe_active column, which will be either 1 or 0 depending on whether or not the user has an active stripe subscription. The stripe_id column will be the user's unique stripe identifier. The stripe_subscription column will be a unique stripe subscription identifier. The stripe_plan column will be the identifier of the plan that the user is subscribed to. The last_four column will be the last four digits of the user's credit card. The trial_ends_at column will be the date and time that the trial will expire if the plan has a trial period. And finally the subscription_ends_at column will be the date and time that the subscription itself will expire once it's cancelled. And of course, in the down method, all of the above columns are simply dropped from the easiest table. Right, so let's go ahead and run this migration from our terminal with php artisan migrate. While we're here in the terminal, let's create a new migration for our products table. We're going to store a few products that the users can buy. We'll run php artisan make:migration, create products and the migration will be called create_products_table then we'll make another one for our cart which will store the products and their quantities for our users. So, again we'll run php artisan make:migration, we'll be using the create option again with the cut table and name it create_cart_table. Right, now it's time to fill up both of these migrations. Let's start with the products migration. After the order incrementing id column, we'll add a string column called name. Then we'll add a float column called price. We'll remove the time stamp columns as we don't need them for this table. Right, so that's the products table done. Now let's move on to the cart table. The first column we're going to need is an integer, and it's going to be called user_id. Then we'll add another integer called product_id. And finally, we'll add yet another integer, and this time it will be called quantity. And just like the other migration, we don't need the timestamps for this table, so let's just remove them. Okay, now let's jump back over into our terminal and we'll run these migrations with php artisan migrate. Excellent. What we need now is some sample data to work with, and we'll also need to set up some models and relationships so that we can retrieve the data. To seed our data, we're going to make use of Laravel's model factories so we're going to need to create our models. So, while we're in our terminal, lets run php artisan make:model and we'll create the product model. Then we'll run it again, except we'll create a Cart model. So now in our app folder, we'll have two new files, Cart.php and Product.php. Let's start with the cart model, it's a bit empty at the moment so the first thing we're going to do is disable time stamps since they're enabled by default but we didn't create those columns in our migration. So we'll just set public time stamps to false. We're also going to need to set our table name on this class. By default, Elequin will use the plural of the class name as the table name. However, for this table, we've actually named it cart and it's not plural. So we're going to have to set it ourselves. So we'll just add a protected table property and we'll set it to cart. Next we need to configure some relationships. One relationship we could add is the inverse user relationship which would link a cart to a user. This would be a belongs to, because a cart belongs to a given user but we don't really need that relationship. What we do need is the inverse relationship for the product. Now cart contains a product_id which links it to a product in the products table. Because it's an inverse relationship, that is, the foreign key is on the base table, which is our cart table, we need to use a belongsTo relationship. So, let's set this up. We'll define a public method called, product, and in it we'll return this belongsTo product class. And that's all we're going to need in our cart model. Now, let's look at our product model. Again, we're going to want to disable time stamps, so we'll set that public time stamps property to false. Now, a product itself doesn't really need any relationships, so let's just move straight to the user model. This model already has a little bit more fluff than the others. We don't really need to worry about any of it though, so let's just define our relationship. Unlike the other models, a user can have many different cart items so we're going to need a hasMany relationship. We'll add a new public method called cart where we'll return this hasMany cart class. Excellent. So we've got our models and our relationships all sorted. Now all that's left to do, is actually create our model factories, and then seed some data. I'll just very quickly explain what model factories are and why they're so useful. Model factories allow us to define some default values for our model attributes, or the columns on our table. These default values, however, are completely random, thanks to the excellent fake a library. So in a nutshell, they let us seed large amounts of dummy data without having to manually fill out each entry. We define these factories in the database factories model factories.php file. As you can see, we already have a factory defined for the user model. The closure accepts a thicker generator instance, which contains a bunch of methods we can use to get randomly generated values. Let's just change the user factory slightly by generating a user name instead of a regular name. This is just a personal preference. Now, let me demonstrate how we can use these factories to generate some data. In our terminal, let's run php artisan tinker. And we'll run the factory(App\User class)-> make. As you can see, we've generated a new instance of our AppUser model and it's been populated with some randomly generated data. If we run the command again, we'll see a different result. And the beauty of these factories is that we can pass the number of results to generate as the second parameter to the help of function. We can also use the create method to have them created in our database. But let's just run app/User::truncate() for now so that we can clear out those entries. Right, so now that we know how factories work, let's create some more for our products and cart models. First, let's start with products. So we define a new factory for the app/Product class. And passing a closure that accepts the Faker\Generator as its only parameter. Now we just need to return an array with some dummy data for our columns. For the product's name, we'll use a random element from an array so we have at least some sensible names for our products. I'm going to use some gaming consoles for our products, but you can use whatever you like. So I'll have a xbox, Playstation, Nintendo 64, Super Nintendo, a Sega, a Game Boy and a 3DS. Next we'll set the price to a random float. The first parameter is the number of decimal places which will be 2. Then we can give it the minimum and maximum. So we'll go for a minimum of 50 and a maximum of 500. Now that's our product factory done. Now for the cart. Let's just duplicate our product factory and the class name. For our cart, we first need a product id. I'll only be generating 10 products. So we'll use a number between 1 and 10. And finally, we want a quantity. We'll go with a number between 1 and 3. All right so we've finally got our factories ready to go. Now it's time to seed the data. We're going to seed our data in our seed/database seeder class. We're going to place the seeds between the model on guard and model reguard calls. So first up, let's truncate our three classes so that we always have fresh data if we ever rerun the seeds. So we'll need App\Use::truncate():. Then App\Car::truncate and finally App\product::truncate():. Then we'll seed our products table. We'll call the factory function passing in App\Product::class) and we'll generate 10 records. Then we'll just call the create method. Next we'll see our users table. Again, we'll call the factory function passing in the App\User::class) this time and we'll also generate 10 records. Again, we'll call the create method, this time however we'll call the each method on the returned collection and passing a closure. So for each of the users that we just created, we want to add some items to their cart. Because we've set up our relationships, we can simply call user::cart) to grab the relationship instance. And then we'll call saveMany and in here we'll again call the factory function, passing in the App\Cart::class), and we'll generate 2 records. Instead of calling create, we'll simply call the make() method to get the model instances. Now, because this is utilizing the cart relationship, the user ID column will automatically be set to the ID of the user we're currently iterating over. It's pretty handy. So that's how Sat's done. We can now switch to our terminal, and we'll run php artisan db:seed. Once the data is seated we can refresh our database in MySQL Workbench and query any of the tables to see the seeded data. Excellent, we're now ready to start charging our users and creating subscriptions.