Full Stack Instagram Clone with Laravel and MongoDB – Tutorial

freeCodeCamp.org · Beginner ·🔧 Backend Engineering ·1y ago

Key Takeaways

This tutorial demonstrates building a full stack Instagram clone using Laravel and MongoDB, covering document-based schema design, authentication, social features, and performance optimization techniques.

Full Transcript

Welcome to this comprehensive tutorial where we'll use Laravel and MongoDB to build a fully functional full stack Instagram clone. I'm Bo KS and I'll be teaching this course. Laravel and MongoDB are a very versatile technology stack for modern web development. Whether you're building enterprise applications, e-commerce platforms, content management systems, or data inensive applications, this combination offers exceptional flexibility, scalability, and developer experience. You'll be able to use what you learn in this course to build a wide variety of full stack applications. Laravel is one of the most popular PHP frameworks known for its elegant syntax, robust features, and developerfriendly ecosystem. It follows the MVC or model view controller pattern, making your code organized and maintainable. Laravel excels at handling authentication, routing, and database operations with minimal effort, allowing you to focus on building your application's unique features. MongoDB, on the other hand, is a document database that stores data in flexible JSON-like documents. Unlike traditional relational databases, MongoDB doesn't require a predefined schema, making it ideal for applications where data structures might evolve over time. This flexibility is perfect for social media platforms like Instagram, where features and data models frequently change. Combining Laravel with MongoDB gives us the best of both worlds. Laravel's structured approach to application development with MahonguB's flexible data storage. This is particularly valuable for our Instagram clone which will handle various types of content including user profiles, posts, comments, and likes all with complex relationships between them. In this tutorial, we'll start from scratch setting up a Laravel project with MongoDB integration and then we'll progressively build all the core features of Instagram. We'll cover user authentication, profile management, creating and displaying posts, implementing likes and comments, and even handling image uploads both locally and in the cloud. By the end of this tutorial, you'll have a solid understanding of how to leverage Laravel and MongoDB to build modern scalable web applications. MongoDB provided a grant to make this course possible. So, let's get started by setting up our development environment and creating our Laravel project. Some prerequisites, you need PHP installed, composer, you need also MongoDB installed locally. Now, some of these things will be different depending on what setup you have. If you have Windows or Mac and on Mac, once you have MongoDB installed, I'm going to run this command MongoD. And then I need the path to where the database is. Now, on Windows, it should just be running automatically in the background once you installed MongoDB. So, we have our database running. So we can now connect to this database locally in our application. Now let's just make sure to install Laravel globally on our system. So I have composer global require Laravel installer. And so this is going to provide the Laravel command line tool that we'll use to create our Laravel project. So let's make our project Laravel new. And then I can name it anything I want. Insta Campamp. I'll call it InstaMamp. Basically, it's an InstaG clone. And then we I'll just select the defaults to most of these. And then for the database, um, it doesn't list MongoDB, so I'll just choose SQLite, but we'll switch it to MongoDB in a little bit here. So, let me just switch to the directory and then I can run it. There's a few ways to run the project that we've created. I'm going to use PHP Artisan serve. So, if I run that now, it's going to run the server. And I can just open this up in my web browser. And we can see this getting started page. So when we create the new Laravel project, it created just some basic scaffolding. I'm going to stop this for now and I'm going to install the MongoDB PHP extension. This is required to connect Laravel with MongoDB. So there's a pseudo pet install MongoDB. Now, I already have it installed, so I'm not going to need to do that. Now, I installed the extension. I need to add it to my php.ini file. So, first I'm going to have to locate my file. On Windows, it's going to be in the PHP installation directory. And on uh Mac OS, I can do PHP-S ini to find the location of the file. So I'm going to want to edit this file. So I'll just do nano and then put the file. So what I'm going to want to do is add a certain line. I've already added it, so I'm not going to save this, but it's going to be extension equals Mongodb.so. Now, you can edit anywhere. I mean, there's certain parts of the file where it will make more sense to add it. Um, if you are in Windows, it's it's not it's going to be extension equals, and it's going to be a little different. It will be PHP MongoDB. DLL. And you don't want it twice in there. You only want it once in there. So I'm not going to save this. And now I'm going to install the Laravel MongoDB package. Before we installed the PHP extension, now the Laravel package. So compose require MongoDB/Laravel. MongoDB and then we have the version at least 5.2. Okay. Now I'm going to open up this folder instacamp in my code editor in VS Code. When we set up this project, the database was SQLite, but we want to connect to MongoDB. So, let's configure the MongoDB connection. So, I'm just going to go to config and then database, and we'll go down here. So, these are the different connections. We have the variable, the setup for SQLite. Now, I'm going to add how you would connect to MongoDB. So we have this section right here, MongoDB. We have the drivers MongoDB. We have the URI we're connecting to, and then the database name. We can also change this default up here to MongoDB. But this isn't required because we're going to be updating this environment variable DB connection here. So let me save that. And then I'll go over to my environment variables. And here's the section about databases right here. So I'm just going to update all this. So the DB connection is not now MongoDB. And then here's our URI. So this local host with this port is what we have to connect to to connect to the database that we currently have running on our system. Now later I'll show you how we can update this to a web address on MongoDB Atlas so we can connect to a database that's in the cloud. That's going to be free and easy. But I want to first show you how to do it locally. And then we have our database name and it's just going to be called Instagram clone. Now we are going to update a few other things in here. Uh, and now that we're using the MongoDB database, we're going to change the cache store to MongoDB. And we also have to add a new environment variable called session connection. And we'll make that equal to MongoDB. So we are using MongoDB for the connection, the session connection, and the cache store. And to get this cache store to work, we are going to have to update one more thing. So, let me scroll up up here to config and then I will go to cache. We're going to have to add a configuration for the MongoDB cache. So, you're going to have to make sure you if it's already already there, you have to scroll down to the stores and we're adding another section to this stores array. So, I'll just go down to the bottom and there we go. We're setting the driver, the connection, the collection, lock connection, and then all this stuff will make sure the cache works correctly. So, I'll just save that. And now we have to register the MongoDB service provider. So, I'm just going to go up to uh Bootstrap providers and we add one more provider here. Mongbarlmong service provider and then colon class So when we add this line, we're basically telling Laravel to integrate MongoDB into its ecosystem. A service provider is Laravel's central place for connecting different parts of our application. Think of it as a registration system that tells Laravel, hey, I want to use MongoDB instead of my SQL or SQLite and here's how to connect to it and here's how to translate Laravel's database operations to MongoDB commands. This particular provider bridges Laravel's database functionality with MongoDB's unique way of storing data. Without it, Laravel wouldn't know how to talk to MongoDB when you use eloquent models or database queries. So basically providers are basically building blocks that let you swap out components or add new features without changing core code. So let me make sure everything's saved here. So now let's create our user model for MongoDB. So I have my terminal open and let me show you the command I would use to create a model. It's PHP artisan make model and then we have the model name and then this dash m that flag would normally create a migration file but with MongoDB we'll handle our schema differently. Now, I'm not going to need to run this command because the when I initially created this Laravel project, it started out with a user model that we can just use. But we will have to create the other models that we're going to be using in our application. So, let me go to app models user. And like I said, there's already something pre in here, but I'm going to update this with some new code. Now, a lot of this is similar to what was in there already, but let's go over some let's go over in some of the changes. So, by default, Laravel generates the user eloquent model. That's this in the app/models directory, which is where this was. So to enable authentication for MongoDB users, your user model must extend the MongoDB laravel users. That's what we have here. So we've updated it to extend this. So it used to say illuminate foundation/off user. Now it says Mongblar off/ user. And in both cases we extend we do it as authenticatable. And then we just ensure that the user class extends authenticatable. And then we'll use notifiable. And here are the lines where we specify that we're connecting to MongoDB and our table is called users. Now in MongoDB a we don't actually have tables. We have collections. But we use the word table here because that makes it more compatible with how things are usually done in Laravel. Then we have this fillable array which lists all the fields users can have like name, username, email, password, profile, image and bio. And then we have our hidden items. And then we have our cast where we are going the email verified at is going to be a date time. The password we're going to make sure it's hashed. And then we have our relationships. So a user can have can have many posts has many posts. A user can have many likes and a user can have many comments. These relationships work just like in regular Laravel, but behind the scenes, MongoDB handles them differently using document references instead of foreign keys. And next up, we're going to create our post model. We're actually going to have to make models for all these posts, likes, and comments. So, our posts model will be just like I already had here, but post. And then I'll just do that. And it's going to create some files for us. Most the main one is this model/post.php, which I'm now going to open here. And so it has the default like our eloquent model, but this is the thing that we're going to switch to being uh from MongoDB. So let me paste in the new code here. So like I said, we are extending MongoDB's version of the eloquent model. This gives us the MongoDB specific functionality we need. Again, we are having the the MongoDB and posts. Basically, this is this is saying that we're using our MongoDB connection and storing posts in a collection called posts. And then we need to store some information like the caption, the image path, the image URL, and the user ID. The the image path is where to it's stored on the server. This is the public URL. and it it's going to belong to a user and it can have has many comments and it has many likes. So the structure basically mirrors how Instagram works. Users create posts and those posts can receive comments and likes from other users. MongoDB will store these relationships as references between documents giving us the flexibility to query and display the data efficiently. So I'll save that and then in our terminal PHP artisan make model comment. So we have to make the comments. This is going to be very similar. I'm going to replace this code with the new code and it's basically just the same except the comment is going to have a comment, the user ID, the post ID. It belongs to a user. It belongs to a post. Save that. And then we'll create the the like model. And after I run that command line command. We can just click like here. And then I'll paste this in again. It's very similar. It has a you like has a user ID and a post ID. A like belongs to a user and belongs to a post. Pretty straightforward here. Next, we need to add user authentication so people can sign up, sign in, log in, and have their own accounts. So, let's look walk through the process. So, I have this new command here, composer require Laravel UI. We're installing Laravel's UI package, which gives us pre-built authentication screens. Next, we can generate the authentication scaffolding with Bootstrap styling. PHP artisan uib bootstrap-s off and I do want to replace the controller.php. So that command creates the login registration password reset views we need. It's a really big timesaver. And then you can see it says please run mpm install and npm rundev. So we can copy that and this will install and compile our frontend assets. And I'm just going to X out. It's running a server, but we're not going to run the server like that. So the final step is to make sure Laravel knows to use our MongoDB user model for authentication. So let's go to a file here, config, and then we'll scroll down a little bit to the providers. And we're basically just confirming that we want to use eleant and we are using this the user model for authentication. It's already set up correctly, but let's make it even more explicit by I'm going to just make it so it's not even accessing an environment variable. And we can just hardcode it. Appod users is what we're using for authentication. And I'll save that. So what's interesting here is that we don't need to change much in the O configuration. Even though we're using MongoDB instead of my SQL, Laravel's authentication system is abstracted enough that it works with our MongoDB models without major changes. Behind the scenes, Laravel will now use MongoDB to store and retrieve user credentials, session information, and authentication tokens. So our users users can create accounts, log in securely, and maintain their sessions. All powered by MongoDB instead of a traditional SQL database. Now let's build our post controller. Another terminal command here PHP artisan make controller called postcontroller dash resource. So this is b basically the brains of our application. The controller handles all post related actions and this gives us a controller with all the standard CRUD methods predefined which is obviously a huge timesaver. So if I go to apps http controllers and we go to postcontroller here now it creates a default one but I'm just going to paste in some updated code that's more specific to to what we want here. So you can see extends controller and if we look at the top here we have this section which ensures only logged in users can access any of these methods. So that's important security first. Now let's look at each method. We have the index method here which gets all posts sorted by newest first and displays them on our home feed. Notice we're using the with user that's here. The with the the user here that will eagerly load the user data with each post. This is a performance optimization that works with MongoDB just like it does with SQL. And then we have the create and store here. These handle new post creation. So, we're going to validate the post have both a caption and an image. We are going to store the image in the public uploads directory. Uh for this application, we're actually storing all the images locally, but at the end, I'll talk a little bit about how you can switch it to store through S3 in the cloud if you want. If obviously for a production app, you're going you're going to want to store the images in the cloud. We also create a new post that is linked to the current user and then we redirect to their profile page. And then for viewing individual posts, we have the show method which simply passes the post to the view. And then uh we have the edit and update methods which allow users to modify the their captions. So first we check if the current user owns their post. If not we block with 403 error. Otherwise, we validate and save their changes and then see with the the update we're we're validating and we're we're saving the challenge changes and then redirecting. Finally, we have the destroy method which handles post d deletion. So we verify the ownership. Then we uh delete the image from the storage. We delete the post from MongoDB. Then we redirect back to the user's profile. So what's cool here is even though we're using MongoDB, the controller code looks basically identical to what we'd write in a SQL database. Laravel's eloquent abstraction works beautifully with MongoDB, letting us focus on building features rather than worrying about database differences. Now we have to create a few more controllers. I'm going to create the profile controller and it's going to create the profile controller file right here. And I'll paste it in. It's a lot of similarities to the other controller. It has three main methods. So we have the index method which displays the user's profile page and all the information and posts. And then we have the edit and update methods. So you can see this is just going to return the the view so someone can update. And the update we're going to verify a user can only edit their own profiles. We validate their inputs name, username, bio, and optional profile image. And then if we up they upload a new profile profile, a new profile picture, we delete the old one and store the new one. And then we update and then we redirect back to their profile. So what's nice about MongoDB here is that we can easily store varying amounts of profile information without worrying about the about table structure changes. So uh for instance we are updating a user with a username, a bio and a profile image where before the user did not have this information when we originally created the user. So we're basically because in MongoDB we can add new fields to the user just like that. Okay, we just have a few other controllers to make quickly. the comment controller and that will just make the file here. Okay, got the comment controller file. I paste in the code there. It's very similar. It mainly focuses on two actions. We have the store where we're going to validate the comment that the comment isn't empty and isn't too long. We'll create a new comment link to both the current user and the post and then redirect back to the post. And then we have destroy. We check if the user is either the comment author or the post owner. We delete the comment from MongoDB. Then redirect back to the post. Now we have the like controller. So let me put in the command line to create the the like controller. And then I can open the like controller file. And then just like before, I'll paste in the code. And this code is all very similar. I'm not going to even go through it all, but it's it's it's very similar to to the other ones you can see. So, basically, all these controllers work together to create the social experience of our Instagram clone. Users can share posts, customize profiles, leave comments, and like content. And it's all powered by MongoDB's flexible document structure. So, I'll just make sure all this is saved. Now it's time to set up our application routes. We need to define all the URLs and endpoints for our Instagram clone. Routes are like the address book of our application. They tell Laravel where to send users when they visit different URLs. So let's open up our routes file. So we have our routes directory and the web.php file. This is our primary routes file. And I'm just going to paste in a new new code that will have all of our routes. So let's break down what we're doing in this routes file. So first we import all the controllers that we created earlier. Then we set our homepage. So this basically makes the root URL of our site show the posts feed but only for logged in users. The middleware off here ensures that anyone not logged in gets redirected to the the logged in the login page. Now in a more production application you probably would want something else as your homepage. You wouldn't want to go directly to the login page, but that's going to be good enough for with for us for now. Then we are going to include the Laravel's authentication routes. This single line adds all the routes we need for login, registration, password reset, and email verification. So, it's a huge timesaver. For our post, we define all the CRUD applications. So, it's relatively straightforward. Um, we have our views. We have our get request to view all the posts where we're going to show the post.index view. We have the create post, the post.create view. We have the um the post request for posts where we're storing a new post. We have the get request for a post and then the the post ID. We have the edit a post ID. We have the patch. So, we're basically going to update a post. And then we have the delete post to um destroy the post. And then all the same for users. We have the get user, get the user to the edit page of the user and the patch the the update the user. Then we have the comment routes. So a post request to a comment would be to store a new comment. A delete request to a comment is to destroy a comment. We don't ever show the comments by themselves. So we don't need a route for that. And then the likes the same or we're going to uh create a like and destroy a like. We never show the likes on their own. So we're using restful naming conventions throughout. This makes our routes predictable and easy to understand. Also by using the name method that's that we use the name method at the end of every one here. we can refer to these routes by name in our code instead of hard- coding uh URLs. So, so basically these are the the name of our routes which it's also going to correspond to to the views. And the beauty of Laravel's routing system is that it basically works identical no matter what database you're using. The routes connect to our controllers which then interact with our MongoDB models creating a seamless flow from the URL to the database and back. Okay, we'll save that and it's time to create our views, our application layout. So, we're going to build the visual structure of the actual site. So, let's start with the main layout that will wrap around all our pages. I'm going to go to resources, views, layouts, and app.blade.php. So, this layout file is the skeleton of our application. It contains the elements that appear on every page like the navigation bar and footer. So, this is all default. So, I'm going to paste in the specific code for what we're doing here. And at the top, we have our head of our page. This is basically the the HTML. And this has our meta tags, our title and CSS imports. So, we're we're using Bootstrap 5 for styling and font awesome for icons. They're both loaded with CDN's for simplicity. Then we have our navigation bar for our app's branding and main navigation links. So we have our brand. We can actually change this. I'm actually going to call this Insta Camp. But these are basically all our main navigation links. We can uh toggle it. And really on the left side of the navbar, we can click the feed link. And then on the right side of the navbar, there's going to be a few different things that could show up there. Uh we use blades conditional directives to show different navigation options based on whether the user is logged in. So that's why we have this this guest here. So if um the guest if it's a guest we are going to show this login item and then we can also show this register item but else if the person is logged in we are going to show the new post and then we can show a drop-down which is going to uh allow someone to access their profile. click the profile link. So if they I should have explained this before, but someone clicks profile, it's going to access the profile.show route and it's going to um the parameters are going to be the ID of the authenticated user. And then if someone clicks the log out link, we can we will submit that the the logout form. So they're they're logging out which is basically right here. It's going to make a post request to the logout route. And then we can keep going down to the main content area. So where it says yield content that directive is where the specific content of each page will be inserted. This is blades template inheritance system at work. So each individual view will extend this layout and provide its own content. So Blade, if you don't know, that's basically the templating engine that Laravel commonly uses. And then at the bottom, we include the Bootstrap JavaScript bundle. So that will help us with our interactive components like drop downs and modals. This layout gives our Instagram clone a consistent look and feel across all pages while still allowing each page to have its own unique content. It's also fully responsive, adapting the different screen sizes thanks to Bootstrap's grid system. Okay, now I'm going to create a new file for the post views. So in this layout section or in this views folder, I'm going to create a new file called posts. Now that's the directory slashindex.blade.php. So we created the file index.blade.php inside the posts directory. And I'll just paste in some code here. So this is basically the heart of our Instagram clo clone. It's the feed page that displays all posts from users. It's what what users will see when they first uh log in. So, first uh our feed is using Blade, Laravel's templating engine. And uh we first tell Laravel to use our main layout as the the wrapper for the page. That's what this extends layouts.app. And the section content defines the content that will be inserted into the yield content section of our layout. Inside the content section, we soon will loop through every single post. And for each post, we create a card with several key components. We basically have the profile picture and username. And if the user might not have an image, we show a placeholder. Then we show the post image that is coming from our local storage. And next we have our interaction interactive buttons for liking and commenting. So we can either like or we can we can destroy a like. We can um uh if there if it's already been liked, we can delete the like or we can add the like with this post request if it hasn't been liked quite yet. And then it will show the comment button here. And then we have the caption and comments section. We show the count, the post caption, and the link to view all the comments. And then at the very end we show the the timestamp here. So this shows a human. It says diff for humans. This shows a human readable time like two hours ago instead of a raw timestamp. So we basically access the data through the eleant relationships and all the things like um post to comments, post ID, post user username. Uh these are all MongoDB relationships, but Laravel's abstraction makes them feel natural and intuitive in our templates. Now, we got to create views for creating and managing posts. So, right in this post folder, I'm going to create a file called create.blade.php. And I'll just paste in some code here. So, this create post view has a just provides a simple form for users to create new posts. So, we extend layouts. Here is here's the content section. So, we're basically going to have a text area for the caption and a file input for the for uploading users. So, here's create new post. We have the card and then we have a post action for our form to post.store. And then we have the multiartform data which is important for file uploads to work properly. So, we have the label caption and our text area here. And this error uh basically just shows validation errors right below the field where the error occurred which gives users immediate feedback. And so we have the caption, we also have the image and then it's just another form here. So again we have the air right below the image here and then we have the submit button. So, pretty straightforward. I'll save that. And then we can create the the post view, which is going to be in this post folder. And it's going to be called show.blade.php. And so, this is our detailed view for a single post, similar to when you click on a post in the real Instagram. It's split into two columns. The left side is going to be the fullsize image. So we can see that right here. That's basically all the left side is the the image that we get. And then the right side is going to be slightly more complicated, but basically it's going to be the user info, caption, likes, and comments. So we got the profile image of the user who created the post where it's going to say profile. It's going to go to the profile. route and then we have the username. And if if we're the post owner, if the person viewing this is the post owner, we're going to show a drop-down menu with edit and delete options. So that's what all this is. So we can see we have the drop-own menu with the edit option and then we have the delete option and it calls the post.destroy destroy route and also if the user no longer exists, it's going to show that. And then we see where we show the caption. We show the likes, which can be um added or deleted depending on who's logged in. And then we have the comment section, which is going to have a for each loop. It's a basically a scrollable area that lists all the comments and it could be an actual user or a deleted user. And if you made the comment, it's possible to delete the comment. Also, um users can delete comment there. Uh if you own the post, you can delete any comment. And then at the bottom there's just this form for adding a new comment here. So we'll save that. And then we'll just create the edit post view. edit.blade.php and I'll paste in the code. And this is pretty straightforward. There's a the card the edit edit post. And then we are just going to make a uh we're going to you it's a basically a simple form that uses the patch method and it prefills the caption with the existing text and then it provides the feedback the air feedback and then we can update the post. So notice we don't allow changing the image. This is a common limitation in social media apps. It helps maintain the integrity of the conversation around a post. So all of these views work together to provide a complete post management system. You can create, view, edit and the backend handles all the data seamlessly with storing the relationship between the post and all the other things and basically creates our application. And now it's time to create the user profile page. So in the views folder, I'm going to create a new file. It's going to be called profiles. That's the directory slashindex.blade.php. So the file is called index.blade.php. And I'll paste in some code here. So, like we're creating the profile page, which is where users can see all their posts and personal information in one page. It's designed to look similar to Instagram's layout with a few key sections. So, at the top, we have the user's profile information displayed in two columns. So, here's the first column, basically, uh the profile image and everything. And there's the placeholder image like we've been using. And then we have the the right column here which displays the username as a large heading. An edit profile button which is only viewable to the profile owner. And then just stats about posts, followers, and following. And the user's full name and bio. And then finally, we list all the posts and what we're just showing the image from each post. And then clicking on the image takes you to the detailed view of that post. So one thing to note is that we're accessing the user's post directly through the relationship where it says user posts. So behind the scenes, MongoDB is handling this relationship between the user document and their post documents, but Laravel's eloquent makes it feel just like working with a SQL database. This profile page gives a user a complete overview of their presence uh on this social media app, which is the personal information and all their posts. And now we need the edit edit profile page. So new file edit.blade.php. And I've just pasted in some code that's going to allow users to customize their personal information. So we can see this first section here. We're using the patch http method which is the restful way to handle partial updates. And we include the multi-part form data over here because the form allows for uploading a profile image. And then the CSRF. I didn't mention this before, but it protects against cross-sight requests, forgery attacks. And then we basically have a form with all the key profile information. So we have the name. So you can see um all that here. And again we uh validate and we have the error handling and then we have the username and the way we're actually creating the application. There's some things when you first create your account you can't add certain things but if you go into this edit page you can add some other information. The username is one of the things. And then the bio you can add a bio. So we can see what that looks like. And then we can add an image. So this is the only place you can add the profile image. And again it's just like all the other things which have which also has the air handling. And we have the button to update the profile. So I'll just save that. And once this is uh submitted, the form sends the data to our profile controller update method, which will validate the input and update the user's document in the MongoDB database. Okay, we're getting closer and closer to being able to try this out. Next, we need to set up file storage for this application. We need to configure how our application will handle image uploads. So uh like I said earlier for at first we're just basically going to store the images locally. So we need to run a simple command to create a public storage link. So I got the terminal open here. PHP artisan storage link. And what this command does is create a symbolic link from public storage to storage/appublic. This is important because files stored in storage/app are not directly accessible from the web for security reasons. So by creating this link, files in storage/appublic become accessible through a web URL. This lets us store user uploads securely while still being able to display them on the site. So you can see it says the link has been created. Next, we need to configure our environment. Let me open up our env file. And then we're going to find where it says file system disk local. I'm going to change this to public. We're basically making sure our application knows to use the public disk for file storage. This tells Laravel to use a public disc as the default location for file uploads. So when our user uploads profile pictures or posts images, they'll automatically be stored in the storage/apppublic directory. So behind the scenes, when a user uploads an image in our Instagram clone, the files saved to storage/appublic/uploads for posts or storage/appublic/profile for profile images. And then thanks to our symbolic link, these are accessible through URLs like storage upload and the file name. And our application can then display the images in the feed, profile page, and individual post views. And this is going to work identically no matter what database we're using. The database stores the paths to the images while the actual image files live in the file system. And we can make the images be stored on AWS later. And uh we'll just store like the URL to the images in our database. Now I'm on in my routes file and I'm going to add one additional route before we test out our application. So I'm going to just paste in this code here. And this is going to redirect if it goes to slashhome just to our main feed here. That's because when a user registers an an account, it automatically goes to slhome, but we want it to show the feed. So I'll save that. Now in my terminal, I'm going to do PHP artisan php artisan serve. and that will start our application again. Okay, if I go to that URL, it will automatically forward us to our login page because we're not logged in. And I'm going to click register. And now I can register a new account. Just so you know, this is from an extension this year because I have one password installed. Um, that won't necessarily show up if you don't have the browser extension, but I'm not going to use it right now. So, I'm going to use a very insecure password, which is just password just for this example here. And that's why it's trying to tell me to change my password. Okay, we're logged in. Right now, there's nothing on the feed because there are no posts created, but I can create a new post. But actually, before I create a new post, I'm going to go to this dropdown and go to profile and edit my profile. This is how we're going to get a profile image. So, I can change my username. I can add a bio. I am a software developer. Now, I can choose my profile image. Okay, I selected an image from my computer and update profile. Okay, looking pretty good. Now, I am going to create a new post. So, just click new post. So, I'm going to choose an image. And we can't see the image until we actually post it. But I'm going to do a caption squeezing together. And after I post this, you'll see, okay, a bunch of people squeezing together. There's me right there. These are some free co team members from our last free co team summit. I'm going to do a new post playing code names and I will choose a file and post that. And then we'll just create one more staying warm by the lake. And you can see it's going to um show the different orientation depending on how the image is done. But if we So this is just our profile page where it's just going to show the image. But we'll see things a lot better in our feed. So, here's our feed. So, here's the image. You can see this card. We have likes. We have our comments. This has zero likes. I'm just going to add a like to this one. I'm going to add a like to this picture. And I can click here to go into the post. And now we can see all the comments. So, here's our post page. And we can see all the comments. There are no comments. So, I'll I'll leave a comment. I'm about to jump in, which is true. I actually did jump in that lake a little bit after that picture. So, now we can see how the name and the comment shows up just like that. I can delete a comment. So, anytime I created the comment, I can delete it. But I can also delete all comments on my posts. So go back to the feed and we can see that this has one comment and we can keep going down. And so right now I'm actually zoomed in on this page. So if I go to 100% it's going to look a little like this. And to see this how this works even more, I'm actually going to create a new account. So I'll just log out and I'll register a new account. Quincy Quincy@frecodecamp.org. Just don't tell him I'm making an account for him on here. And then I will register. And then I am going to go and update my profile. And just filled in all that really quick. Update profile. Now we can see Quincy's profile. And we'll do a new post from Quincy's profile. Caption. Check out this high score. And then I can choose a file. And you can see I accidentally tried to post it before choosing the file. And it says this image field is required. So I can post that. So we can go into that. And we can see high score FCC for free coamp. There's Quincy. And then we'll just do one more post. Amazing team meeting. Choose the file. Okay. Now I can go into the feed and now we can see in the feed we can see posts from multiple people. So here's the post from Quincy. Um zero likes yet. And then we get this post. But if we come down here we can also see the post from Bo KS. And this has one like but now Quincy's account can like it. And we can go down and now it shows two likes. Currently, when you do click the like, it reloads the page and goes to the top. That's something that could be fixed in a future update. But let's go into the comments here. I would I wouldn't jump in if I were you. Post. Okay. So, now we see it shows multiple comments and Quincy can delete this one, but not the first comment. So this is working. We have all the basic features. If I go to the boge account, I the Quincy account can see uh can see different accounts on here and everything's being stored on MongoDB except for the images which are being stored locally. Okay, now let's talk about migrating to MongoDB Atlas. So, we have a working application with a local MongoDB database. So, let's migrate to MongoDB Atlas for production because you're not going to want to host your database uh locally in a production application. And the great thing about MongoDB Atlas is that you can do a free account, which will allow us to do a lot just with our free account. And we can grow our website and only have to start paying once our database gets to a certain size. So the first step in hosting our database online for free is to go to the MongoDB Atlas website link in the description and we can either sign in or try free to create an account. I'm going to just sign in. I already have an account and once I get logged in I'm going to make sure to go to projects and then go to new project. If you are creating a an account for the first time, it will likely go through this create a project this create a project onboarding as part of your like right after your account creation. So I'll call the project Insta Camp and then we can choose whether we want to add any tags. Um no and I'm the project owner and create a project. Okay, now I want to create a cluster and there's different options we can use. I'm going to use the free option and you can see it says free forever. Your free cluster is ideal for experimenting in a limited sandbox and you can upgrade to production anytime. So we can um choose the cluster name. I'm just going to call this Instacamp again. And then we can choose the provider. You can choose any of them really, but I'm just going to stick to the defaults AWS. For the region, you're going to want to choose what region is closest to you. Uh, this one probably is the closest to me. And then I can just go to create deployment. Okay. Now, it's going to give us some instructions on connecting. So, add a connection IP address. It's going to automatically add my current IP address so I can connect locally. Uh but if you are hosting your website somewhere else, you may have to add a different connection IP address. And then we have to create a database user. And I'll just leave this as B. And I'll use the default password which I will change or delete later before this course goes live. and I'll do create database user. Okay, now I can just do choose a connection method and we're going to I'm just go to drivers and uh truthfully we're not even using any of these. We're just trying to get our connection string but right now it's still provisioning so we can't even get our connection string yet. It says it takes an average of 10 to 15 seconds to provision your deployment. So, it's probably been that much time, but okay, here is it's actually saying your cluster is being created. So, we're just going to have to wait until this finishes being created. Okay, so now let's go back to connect. We can get our connection string this this way. And we have it right here. We could actually change this driver to PHP, but truthfully, the connection string is basically the same. And I can copy this connection string. And now I can just click done. Now I'll go back over to my code editor and open up my ENV file. Here we go. And then we just update this URI. Instead of connecting to our local host, I can put this URL that I this connection string. And then I just have to update this DB password. And I actually have this copied. So it's just all these letters and numbers. That was like the default password here. And I'm going to save this. And that's it. That's all we have to do to start hosting our database in the cloud for free. But let's just verify and check it out. So let me refresh this page here. I'm not logged in anymore. And if I try to log in, it shouldn't work because there's not any users in our database yet because it's now connecting to the new database. But let's just try it. And then my super secure password. These credentials do not match our records. So, we're basically going to have to create everything again. So, I register my account again. Again, it's an and we see there's nothing in the feed. There's been no post. But I could just create post just like before. and post and we'll just Oh yeah, we have to edit the profile and update the profile and then I'll add just a two more post really quick. Okay, so add those posts and again I'm going to create another account and uh add posts for that account. Okay, so I just made all those posts again. We'll go to the feed and we can see it looks just like before but now everything is being stored on the database on MongoDB Atlas and we can confirm that. So I'm back on MongoDB Atlas and I'm going to click browse collections. So now we can actually see everything in the database. So we have posts or we have users. I'm going to see the users first. So there's two different users. We have posts and you can see it's has all the information about each post. Currently the images are still stored on my local computer, but like I said, that can easily be switched to S3 or be stored somewhere online. And one thing you can see that's interesting is that it's only showing posts and users. It's not showing likes. The like collection hasn't even been created because there are no likes yet. But if I go back over here and click like and we go back and if I just refresh the data really quick by clicking this refresh button. Now we can see there are likes. So the collections don't get created until they're needed. And we can see the like from this user ID of this post ID. And same with comments. So I can add a comment here. Looks so fun from Quincy Larson. And if we go back to our MongoDB Atlas and refresh again, we should see the comments in here. Now you can also edit things right from the database. I mean, it's not really recommended to do it that much in production, but if I click edit here, I can change this fun to boring and then update. Then, if I go back over here and refresh looks so boring. So, that's kind of cool. So, that's pretty much it for this tutorial. I'll just quickly tell you how you could implement S3 storage for images, but I'll leave that to you to do on your own. But basically, you would start by adding the uh installing the AWS SDK for Laravel, which would be composer require leaguefly system- AWS-s3-v3. Then you are going to have to make sure you have an an AWS account. You're going to have to update your environment variables, your MV file with S3 credentials and also there's a file systems configuration like we would go to config and file systems and then we can see we actually have S3 is already in here. We would just want to make sure that's properly configured. It probably already is. And then we would just update the controllers to use S3. It's a very quick change in the code and then update the views to use the S3 URLs. Again, it's pretty simple. Also, apart from using S3, we could also set it up to store files in MongoDB with the grid fs/fly system. And we're done. Through building this Instagram clone, you've mastered a powerful technology stack that extends far beyond social media applications. You now understand how Laravel's elegant structure pairs perfectly with MongoDB's flexible document model to create adaptable, scalable applications. This combination equips you to build sophisticated web applications that can evolve with changing requirements. Happy coding.

Original Description

Master MongoDB with Laravel by building an Instagram clone. Learn document-based schema design, authentication, social features, and performance optimization techniques. Perfect for Laravel developers ready to move beyond SQL databases and leverage MongoDB's flexibility and scalability for modern web applications. ✏️ Course created by @beau Code: https://github.com/beaucarnes/instacamp Sign up for MongoDB Atlas: https://www.mongodb.com/cloud/atlas/register?utm_campaign=freecodecamp_igclone&utm_source=freecodecamp&utm_medium=referral)? Thanks to MongoDB for providing a grant to make this course possible. ⭐️ Contents ⭐️ 0:00:00 Introduction 0:02:57 Setting Up Environment and Project 0:07:01 Connecting to MongoDB 0:10:40 Creating Data Models 0:18:42 Developing Controllers 0:25:32 Configuring Application Routes 0:29:42 Creating Views 0:48:49 Testing Application 0:55:32 Connecting Database to MongoDB Atlas 1:02:47 Configuring S3 1:03:47 Conclusion
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from freeCodeCamp.org · freeCodeCamp.org · 0 of 60

← Previous Next →
1 React: Production Server Setup Part 2 - Live Coding with Jesse
React: Production Server Setup Part 2 - Live Coding with Jesse
freeCodeCamp.org
2 cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
freeCodeCamp.org
3 Browser history tutorial - Beau teaches JavaScript
Browser history tutorial - Beau teaches JavaScript
freeCodeCamp.org
4 Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
freeCodeCamp.org
5 React: Parameterized Routing with Next.js - Live Coding with Jesse
React: Parameterized Routing with Next.js - Live Coding with Jesse
freeCodeCamp.org
6 React: Dealing with jQuery Issues - Live Coding with Jesse
React: Dealing with jQuery Issues - Live Coding with Jesse
freeCodeCamp.org
7 setInterval and setTimeout: timing events - Beau teaches JavaScript
setInterval and setTimeout: timing events - Beau teaches JavaScript
freeCodeCamp.org
8 Browser and Device Testing - Live Coding with Jesse
Browser and Device Testing - Live Coding with Jesse
freeCodeCamp.org
9 Last Minute Updates - Live Coding with Jesse
Last Minute Updates - Live Coding with Jesse
freeCodeCamp.org
10 Post Launch Updates - Live Coding with Jesse
Post Launch Updates - Live Coding with Jesse
freeCodeCamp.org
11 React: Setting Up Google Analytics - Live Coding with Jesse
React: Setting Up Google Analytics - Live Coding with Jesse
freeCodeCamp.org
12 React: Masonry Layout - Live Coding with Jesse
React: Masonry Layout - Live Coding with Jesse
freeCodeCamp.org
13 Load Balancing Digital Ocean Droplets - Live Coding with Jesse
Load Balancing Digital Ocean Droplets - Live Coding with Jesse
freeCodeCamp.org
14 try, catch, finally, throw - error handling in JavaScript
try, catch, finally, throw - error handling in JavaScript
freeCodeCamp.org
15 Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
freeCodeCamp.org
16 Graphs: breadth-first search - Beau teaches JavaScript
Graphs: breadth-first search - Beau teaches JavaScript
freeCodeCamp.org
17 React: Masonry Layout Part 2 - Live Coding with Jesse
React: Masonry Layout Part 2 - Live Coding with Jesse
freeCodeCamp.org
18 React: WordPress API Live Search - Live Coding with Jesse
React: WordPress API Live Search - Live Coding with Jesse
freeCodeCamp.org
19 Creating WordPress Custom Post Types - Live Coding With Jesse
Creating WordPress Custom Post Types - Live Coding With Jesse
freeCodeCamp.org
20 Dates - Beau teaches JavaScript
Dates - Beau teaches JavaScript
freeCodeCamp.org
21 Miscellaneous Front End Updates - Live Coding with Jesse
Miscellaneous Front End Updates - Live Coding with Jesse
freeCodeCamp.org
22 Merging a Pull Request from GitHub - Live Coding with Jesse
Merging a Pull Request from GitHub - Live Coding with Jesse
freeCodeCamp.org
23 React + Prettier + Standard JS - Live Coding with Jesse
React + Prettier + Standard JS - Live Coding with Jesse
freeCodeCamp.org
24 React: Sortable Responsive Table - Live Coding with Jesse
React: Sortable Responsive Table - Live Coding with Jesse
freeCodeCamp.org
25 Geolocation Sorting by Distance - Live Coding with Jesse
Geolocation Sorting by Distance - Live Coding with Jesse
freeCodeCamp.org
26 Tradeoff Matrix - Agile Software Development
Tradeoff Matrix - Agile Software Development
freeCodeCamp.org
27 The Definition of Ready - Agile Software Development
The Definition of Ready - Agile Software Development
freeCodeCamp.org
28 Getting first React job without experience - Ask Preethi
Getting first React job without experience - Ask Preethi
freeCodeCamp.org
29 React: Google Analytics Click Tracking - Live Coding with Jesse
React: Google Analytics Click Tracking - Live Coding with Jesse
freeCodeCamp.org
30 Submitting a PR to an Open Source Project - Live Coding with Jesse
Submitting a PR to an Open Source Project - Live Coding with Jesse
freeCodeCamp.org
31 Should I go back to school to get CS degree? - Ask Preethi
Should I go back to school to get CS degree? - Ask Preethi
freeCodeCamp.org
32 Hero Section CSS Changes - Live Coding with Jesse
Hero Section CSS Changes - Live Coding with Jesse
freeCodeCamp.org
33 Working Agreement - Agile Software Development
Working Agreement - Agile Software Development
freeCodeCamp.org
34 A day at Pennybox with Co-Founder Reji Eapen
A day at Pennybox with Co-Founder Reji Eapen
freeCodeCamp.org
35 React: Sorting and Filtering Data - Live Coding with Jesse
React: Sorting and Filtering Data - Live Coding with Jesse
freeCodeCamp.org
36 React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
freeCodeCamp.org
37 React: Building a New UI - Live Coding with Jesse
React: Building a New UI - Live Coding with Jesse
freeCodeCamp.org
38 Definition of Done - Agile Software Development
Definition of Done - Agile Software Development
freeCodeCamp.org
39 Getting started with jQuery (tutorial) - Beau teaches JavaScript
Getting started with jQuery (tutorial) - Beau teaches JavaScript
freeCodeCamp.org
40 Making a React Blog with WordPress Content - Live Coding with Jesse
Making a React Blog with WordPress Content - Live Coding with Jesse
freeCodeCamp.org
41 React, NextJS, CSS - Live Coding with Jesse
React, NextJS, CSS - Live Coding with Jesse
freeCodeCamp.org
42 jQuery events - Beau teaches JavaScript
jQuery events - Beau teaches JavaScript
freeCodeCamp.org
43 React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
freeCodeCamp.org
44 React: Working with API Data - Live Coding with Jesse
React: Working with API Data - Live Coding with Jesse
freeCodeCamp.org
45 React: Refactoring Components - Live Streaming with Jesse
React: Refactoring Components - Live Streaming with Jesse
freeCodeCamp.org
46 jQuery effects - Beau teaches JavaScript
jQuery effects - Beau teaches JavaScript
freeCodeCamp.org
47 More React Refactoring - Live Coding with Jesse
More React Refactoring - Live Coding with Jesse
freeCodeCamp.org
48 animate in jQuery - Beau teaches JavaScript
animate in jQuery - Beau teaches JavaScript
freeCodeCamp.org
49 "Finishing" My React Site - Live Coding with Jesse
"Finishing" My React Site - Live Coding with Jesse
freeCodeCamp.org
50 Starting a New React Project (P2D1) - Live Coding with Jesse
Starting a New React Project (P2D1) - Live Coding with Jesse
freeCodeCamp.org
51 React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
freeCodeCamp.org
52 The Agile Manifesto - Agile Software Development
The Agile Manifesto - Agile Software Development
freeCodeCamp.org
53 jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
freeCodeCamp.org
54 React Project 2 Day 3 - Live Coding with Jesse
React Project 2 Day 3 - Live Coding with Jesse
freeCodeCamp.org
55 The INVEST approach to product backlog items
The INVEST approach to product backlog items
freeCodeCamp.org
56 React Project 2 Day 4 - Live Coding with Jesse
React Project 2 Day 4 - Live Coding with Jesse
freeCodeCamp.org
57 Chickens and Pigs - Agile Software Development
Chickens and Pigs - Agile Software Development
freeCodeCamp.org
58 React Project 2 Day 5 - Live Coding with Jesse
React Project 2 Day 5 - Live Coding with Jesse
freeCodeCamp.org
59 jQuery: add and remove DOM elements - Beau teaches JavaScript
jQuery: add and remove DOM elements - Beau teaches JavaScript
freeCodeCamp.org
60 React Project 2 Day 6 - Live Coding with Jesse
React Project 2 Day 6 - Live Coding with Jesse
freeCodeCamp.org

This tutorial teaches how to build a full stack Instagram clone using Laravel and MongoDB, covering key concepts such as document-based schema design and performance optimization. By following this tutorial, learners can master MongoDB with Laravel and leverage its flexibility and scalability for modern web applications. The tutorial provides a comprehensive guide to building a real-world application, making it perfect for Laravel developers ready to move beyond SQL databases.

Key Takeaways
  1. Set up environment and project
  2. Connect to MongoDB
  3. Create data models
  4. Develop controllers
  5. Configure application routes
  6. Create views
  7. Test application
  8. Connect database to MongoDB Atlas
  9. Configure S3
💡 Using a NoSQL database like MongoDB can provide flexibility and scalability for modern web applications, and Laravel provides a robust framework for building full stack applications.

Related Reads

Chapters (11)

Introduction
2:57 Setting Up Environment and Project
7:01 Connecting to MongoDB
10:40 Creating Data Models
18:42 Developing Controllers
25:32 Configuring Application Routes
29:42 Creating Views
48:49 Testing Application
55:32 Connecting Database to MongoDB Atlas
1:02:47 Configuring S3
1:03:47 Conclusion
Up next
Beginners Guide to GPT4 API & ChatGPT 3.5 Turbo API Tutorial
Adrian Twarog
Watch →