Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Browse all series

Build a Forum With Laravel

Building a forum is a great playground for getting acquainted with Laravel; there are so many little things to think about that really stretch the framework… and our minds! It's been a while since we built one on Laracasts, so join me as we create a feature rich forum together using the powerful ecosystem Laravel provides. Let's go!

Progress

Series Info

Episodes
51
Run Time
10h 45m
Difficulty
Advanced
Last Updated
Jun 14, 2024
Version
Latest

Series Episodes

  1. Stack, Setup and Structure (5)
    1. Selecting a Stack

      Before we can start building, we need to decide which tools to use. Let's whip up a new project using the Laravel installer and discuss our options.
    2. Configuring Jetstream

      Jetstream is not only powerful, but customizable! We should take the time to tweak the features on offer to suit the needs of our particular application. We'll also take a few minutes to discuss where Jetstream ends and where Fortify, the authentication package that Jetstream sits on, begins.
    3. Defining Our Data

      Now that Laravel and Jetstream are firing on all cylinders, it's time to turn our attention to our data structure. For a forum, we'll need three things: users, posts and comments. Let's scaffold out those entities using Eloquent.
    4. Factories and Seeding

      With our Eloquent models in place, it's very useful to have a way to quickly create dummy rows in our database. Laravel has you covered with model factories. We've already created the files, so let's fill them out and use them to fill our database.
    5. Test Suite Tinkering

      The last thing I'd like to do before we begin building is to check our test suite runs as expected. Jetstream publishes a number of tests into our application, so we already have a great base to start from. Getting this last step in will allow us to implement a smooth testing cycle into our workflow.
  2. Post Fundamentals (6)
    1. Pest Driving Posts

      Let's turn our attention to the index of posts. Let's play about with a little TDD to build out tests before writing the implementation. We'll also adapt Jestream's app layout to support both authenticated and guest users, which will be vital across many pages of our forum.
    2. From Model to Json

      Currently, Laravel is in charge of deciding how our Eloquent models are converted to JSON for our frontend. However, that can open us up to accidentally leaking private information. To resolve this issue going forwards, let's turn to API resources, which allow us to define a translation layer between Eloquent and JSON.
    3. Pagination and Performance

      Our Post index is in dire need of pagination to keep everything snappy. Laravel makes pagination a cinch, but we'll need to create a Vue component that we can drop into our Post index. We also need to fix a major performance bottleneck that we introduced in the last episode.
    4. Helpful Test Helpers

      Whilst exploring our Post index, we've sidelined our tests a little. Let's get back on track by building some helpful testing methods for easily validating the data we're passing to the frontend. We'll also see how taking the time to refactor code can make it so much easier to maintain going forwards.
    5. Showing a Single Post

      Let's make use of our new test helper whilst building out the show route for a Post. We'll get the basics in place to build on, introduce a frontend library for formatting dates, and extract another little test helper to save some keystrokes.
    6. Linking Up the Index

      It's time to connect our Post index to our Post show page. Thanks to the tools Inertia provides, that's smooth sailing! At the same time, we'll look at eager loading the user relationship on our Post index and make use of a nifty little group hover trick in Tailwind.
  3. The CRUD of Comments (12)
    1. Showing Comments on a Post

      With all of the groundwork in place, it should be pretty simple to add paginated comments to our Post show page. We'll reuse existing components, extract a few new ones and take another look at relative dates.
    2. The Only Inertia Trick You Need to Know

      Let's take a look at a small but important quirk with our current pagination: loading a new page of comments returns lots of extra data we just don't need. Thankfully, Inertia has a solution for this and it's very easy to implement.
    3. Posting a Comment

      Now that we have our views in place, let's work on a core feature of a forum: posting a comment! We'll take our first look at how forms are handled in Laravel and build out tests that prove our form works correctly.
    4. The Comment Form

      Thanks to Test Driven Development, we were able to build our comment form blind. Now that the backend is in place, let's add the UI to our Post show page.
    5. Auth Issues

      If you look closely, you'll note that we never placed our comment store route behind any auth layer. Whoops! We need to add a test for this to ensure that no guest can ever add a comment to a post.
    6. The "D" in "CRUD"

      We can now add comments, but what happens if we later regret our cyber-selves? We need to be able to delete! Let's build out this seemingly simple feature together, and take a look at some considerations you'll need to account for.
    7. Say Hello to Policies

      How can we unify authorization across backend and frontend? Policies! Policies allow us to easily wrap up our authorization logic behind a nice API to quickly authorize model actions from anywhere in our codebase.
    8. Preventing the Pagination Problem

      We need to style our delete button, but you'll also note a bug when we delete a comment… the pagination is reset! Let's look at one way to handle this.
    9. Editing Comments: The Backend Edition

      Let's get into a nice TDD rhythm as we build the backend for updating a comment. Once we have our tests passing, we can do a refactor pass to clean up our controller, policy and route files so that they're easier to maintain going forwards.
    10. Editing Comments: The Frontend Edition

      The frontend for editing comments should be fairly straightforward; we can reuse the form we made for adding a comment. Time to put your Vue head on and get to work. As always, feel free to skip this one if the frontend doesn't interest you.
    11. Useful User Feedback: Toasts

      When our user takes an action, it would be helpful to provide visual feedback that everything worked as expected. These are commonly referred to as toasts, and Jetstream actually already has a pretty great implementation out of the box.
    12. Useful User Feedback: Confirming Actions

      It's too easy to accidentally delete a comment! We don't want our users complaining, so let's add a confirmation step. How seamless can we make this? Let's find out!
  4. Creating New Posts (5)
    1. Creating Posts: the Backend Edition

      We've added many features to comments, but we're not even technically able to create a Post yet! Let's fix that in the next few episodes, starting with the logic to actually store a Post in our database.
    2. Creating Posts: the Frontend Edition

      With our posts.store endpoint configured, it should be simple enough to wire up a basic form for creating a new Post and see all our hard work come to life in the browser.
    3. Post Policies, Shared Data and Attributes

      Now that the basics are in, we can start fleshing out our Post creation process. Primarily, we'll need a link to the page, along with control over who can and cannot see that link.
    4. Using Slugs for SEO

      The URLs for our Post show pages are a little bland, especially for a forum. It would be much better if you got an indication of the Post's title in the URL itself, which search engines can then pick up to improve search results and surface our posts.
    5. Fixing a Broken Test Suite

      After our changes to Posts, a number of our tests now fail. Don't panic! Let's take it one test at a time and get them all patched up. Whilst we're at it, we should add tests for the new functionality we've added.
  5. Building a WYSIWYG Editor (6)
    1. I: A New Editor

      Our forum posts look so boring. We should allow the user to format their posts and comments by adding titles, lists, emphasis and italics. Markdown is a perfect format for this, so let's take a look at a powerful low-level editor called TipTap.
    2. II: Rise of the Toolbar

      Most word processors include a handy toolbar for visually adding formatting to text. As our forum is targeted at people who haven't even heard of Markdown, we should provide a toolbar, too. Thankfully, TipTap makes that endeavour pretty simple.
    3. III: The AI Wars

      Just before we look at converting our Markdown into HTML, I'd like to spend a few minutes tweaking our DatabaseSeeder to avoid a huge disparity between real posts and seeded posts. Let's make use of ChatGPT to generate some realistic posts for our database.
    4. IV: Return of the HTML

      Alright, it's time. We should intercept incoming Markdown, transform it into HTML, and display it to users on the frontend. As always, there are multiple approaches to this, so let's consider the best fit for our needs.
    5. V: The Comment Strikes Back

      With markdown configured for posts, let's extract a reusable trait so that we can add the same functionality to comments! We also need to make a few tweaks to our MarkdownEditor component to make it work for both posts and comments.
    6. VI: Revenge of the Fixtures

      It's frustrating that our seeders and tests can easily generate realistic post content, but as developers testing the frontend we have to do everything manually. Let's look at creating a local-only endpoint that will allow us to autofill our form with our fixtures.
  6. Post Topics (4)
    1. On the Topic of Posts

      All of our posts currently fall under a single generic category. Let's start building out the database structure for topics, which will allow us to better group the posts on our forum for users.
    2. Filtering the Index by Topic

      With our Topic model in place, we can wire up our post index route to allow for a topic, which we will then use to limit the posts we display on the index. We should also write tests to back up our new filter!
    3. Crafting a Topic Menu

      Whilst we can now filter by topic, there is no simple way to actually select a topic to filter down to. Let's spend a few minutes building a menu for this at the top of the index.
    4. Wiring Up the Form

      The last piece of our topic puzzle is allowing a user to select the topic that their post falls under. That will require us to update a number of methods on our PostController, along with the relevant tests.
  7. House Keeping (5)
    1. Squashing Bugs

      I know you probably think that bugs are beneath Laracasts teachers, but believe me they're not. Over time, bugs are guaranteed to sneak their way into your applications… and that's okay! Let's go ahead and patch a few up together.
    2. Random Refactors

      Along with bug reports, there have been some great suggestions for refactors that will improve the readability, maintainability and durability of our codebase. They'll only take a few minutes to implement, so let's get to it!
  8. Liking Content (5)
    1. Polymorphic Models

      The majority of forums allow you to like posts and comments. This provides our first look at polymorphic relationships - a complex term that basically means a Like can belong to a Post or a Comment. Let's take a look together as we build out the structure.
    2. Denormalizing the Database

      I know I've spent this series telling you to avoid optimizing too quickly, but I want to break that rule. At large scale, our method of counting likes on a post or comment will slow down our app. We can solve this with a nifty bit of database denormalization. "Denormalize-what-now?", I hear you say. Here, let me show you.
    3. He Likes Me

      Our next step is to create the controller logic that will allow our users to actually like content, be that a post or a comment. There are multiple approaches here, but we'll stick with polymorphism to handle both cases in one endpoint.
    4. He Likes Me Not

      "He doesn't like you… I don't like you either…" is hopefully something our users won't say too often. However, we need to provide the ability to unlike content they previously liked. A lot of this is copy-paste-tweak, so let's give the 'c' and 'v' on our keyboards some love.
    5. Smash That Like Button

      Backend… check. Now time to wire up our frontend. Inertia actually makes this a breeze, with the ability to create a Link that is actually a full-fledged form!
  9. Searching for Posts (3)
    1. A Simple Search Solution

      Searching for the content you're interested in is a fundamental part of the forum experience. In our final section of the series, let's turn our attention to two different approaches for searching across the title and body of the posts in our database, starting with a simple SQL LIKE query.
    2. Combining Search with Topics

      Our current search implementation has a few flaws. For example, clicking a topic will reset the search, and searching will reset the topic - not good! Let's tackle these bugs to ensure our search works seamlessly with all aspects of our post index.
    3. Let Scout Do the Searching

      All of the pitfalls of our current search implementation can be solved by a powerful first-party package called Scout. Let's see how easy it is to set up and integrate into our existing search, then discuss a few considerations you'll want to factor in.

Continue Learning