Welcome to part two in our series about building a social network in Laravel, if you haven't already you can check out part 1 here.
In this section we are going to focus on creating some dummy users with profiles and status updates, it's going to be quite a long section but you'll see there's quite a lot to cover.
Database Structure
First up we want to plan our database structure, then we know what data we will be using and work out what Models and Controllers we'll require.
We know we want each user to be able to create status updates and have an info/about me section on their profile, we also want users to be able to write a status on someone elses profile. These are the basic features we are going to be working with today.
So, to start off we'll use our command line to run php artisan to generate a database migration file:
This will generate two migration files in the database/migrations folder, open them and take a look at the contents.
You'll notice they contain two functions; up and down. Up will create the database and is where we state what fields we want, and down will drop the table if we request it to.
For our status updates we will need a text field for the content and a destination id (the destination id will be where the status is sent, if the user is writing on their own profile it will be their own id, if they are writing on a friends profile it will be the friends id).
Update the up function to match the following:
Let's take a quick look at that foreign key statement, the reason we have specified the tables users on the second delcaration is because Laravel will default to looking for a 'destination' table, but we want to point to the users table. This is why we have to declare it on that field, but not the user_id declaration.
Next we'll move to the other migration file, for the about_mes table, add the following fields to the up function.
A couple of things to notice here, the first is the nullable attribute, this allows the field to be null/not required.
The other is we've used both string and mediumText, string is best used for short text inputs which is ideal here for location whereas we expect more content in the about me section which is why we use mediumText for that.
To now run these migrations we simply run php artisan migrate
and our tables will be ready for data!
Defining The Models
For both of our tables we are going to create models, where we specify the table, fillable fields and any relationships that model has.
Run the following:
Our models will be created inside the app/Models folder, we'll need to edit all three models in this folder.
First open AboutMe.php and add the following inside the class:
In order to link to the User class in the relationship we need to import the User class by adding use App\Models\User;
to the top of the file just before the class.
We'll do the same in the StatusUpdate.php class file, and don't forget to import the User class at the top of the file.
Now we need to go into the User.php model and import the other two models at the top of the file.
use App\Models\AboutMe;
use App\Models\StatusUpdate;
The relationships here are going to be a little different, a user has only one about_me record but a user can have many status_update records.
Inserting fake data
Now we get to the fun part, playing with dummy data! But before we can do that we have to create a factory, a factory tells laravel what data types to input to the fields.
Note: If you get an error during this section saying something similar to class not found, first check your spelling and second run
composer dump-autoload
.
In your console run the following to create your Factory files.
The factory files are created in database/factories, the definition function is where we'll use the faker library to create fake data.
Lets take a look at the StatusUpdate factory and add some field types to the function.
Since this is just dummy data we are asking laravel to relate the status update to a random user with an id between 1 and 30, the same goes for the destination id.
Now you can go to your console and enter php artisan tinker
, the tinker interface will open and we can test our Models by creating users and status updates.
First you'll want to run StatusUpdate::factory()->make();
and assuming all is well, tinker will return a dummy status update.
Now, let's do the same with our AboutMe factory:
The only difference here is that instead of attaching our model to a random user id, we want an About Me for every user. To do that we set a static number and then on each iteration we add 1 with ++.
Test your new factory in Tinker with AboutMe::factory->make();
Now that we're happy with the dummy content created, we're going to ask Tinker to create 30 users, 30 about me's, and 60 status updates and save all into the database.
In tinker ->make() will simply show the data generated, but it won't save it anywhere, whilst ->create() will save the data to the database.
Once the factories are created you will need to do composer dump-autoload before you can load up tinker.
If you have phpmyadmin installed you can now go to your database and view all the data that Tinker has generated and saved for us, alternatively you can use mysql command ;)
Take a break here
We're about half way through this tutorial, and we've done quite a bit, make sure you get up and stretch, give your eyes a break for at least 15 minutes before getting into the next section.
Routes
Before we begin setting up our controllers we need to create the routes, or urls that will be visited to access the data.
In our routes/web.php is where we will add all our routes:
Two things to note here, we only want registered users to be able to access other users pages so we are using the built in Laravel middleware to check for authentication when the user attempts to visit the url. Any urls specified within the middleware will require a user to be logged in else they get redirected to a log in page.
The other thing to notice is that, although we've specified all those routes for status updates, we haven't done so for the users. This is because all the user routes are handled by jetstream.
Controllers
We're going to save ourselves some time and get artisan to create our controllers for us, we can also use the --resource
tag which will populate with basic crud functions for us.
The controllers will be created in the app\Http\Controllers folder, open all three and notice they have been prefilled with helpful functions.
First lets concentrate on the easiest, the UserController.php, here we only need one function, the show() function. Update it to match below:
Quick note here that we are passing our data to a view that has not been created yet, this OK but if you want to test that the controller function is returning the correct data you can always dd($user) before the view is returned. This will spit out all the data rather than try to display a view that doesn't exist yet.
Whichever you decide to return, the view or data dump, you can now go to the route specified in our routes/web.php file, in our case domain.test/profile/1.
Templating
Almost there for this article, now we're going to set up a very basic view to return our user data, it's not going to look great but that's no important right now, we're focussing on data only.
So, all views are found in the resouces/views folder, you will get very familiar with this folder and if you're not careful it can become very difficult to manage when we reach the stage of multiple views.
First we want to make a quick change to the default layout so open up /resources/views/layouts/app.blade.php and we're going to update the Page Content section helpfully labelled with a comment. Update it to the following:
It's important to understand what we just did. We will be making use of both types blade component imports, the {$slot} needs to be there for our jetstream files to work and our own blade templates will be appearing in the yield('section'). This may not all make sense now, but it will in a later series when we focus on templating.
Now we want to make a quick change to the navigation, so open up resources/views/navigation-menu.blade.php and we're going to update in two places; lines 100 and 164.
At line 100 you will see the profile link already created by jetstream, we want to duplicate that and update the top one to link to the user profile.
Now scroll down to line 168, you should find {{ __('Profile') }}
just update that to {{ __('Settings') }}
.
Jetstream was already linking a 'Profile' link to the user settings page, we've simply renamed it to settings and created a new link to our users profile page.
If in your controller you are only returning a data dump, you'll now want to go back and return the view we're about to create.
Now in your resources/views folder create a new directory called pages, and inside there a file called profile.blade.php. We need it to have the following:
You can now go to your profile url and you should see the user details, the about me and the status updates listed below.
As said earlier, it won't look too pretty at this point, visual design comes later, for now though you've just created user profiles!
Next Steps
The next stage for us is going to the adding, editing and deleting of status updates so our users can create their own data rather having laravel do it for them.
Thank you so much for following along and see you next time!