Back Button Laravel
Build A Laravel App With TDD

Build A Laravel App With TDD

It's time to take the techniques we learned in Laravel From Scratch, and put them to good use building your first real-world application. Together, we'll leverage TDD to create Birdboard: a minimal Basecamp-like project management app.

This series will give us a wide range of opportunities to pull up our sleeves and test our Laravel chops. As always, we start from scratch: laravel new birdboard.

Intermediate
44 episodes
8:51:04 hrs
44
Latest Episode in This Series

Added 11 months ago

Wrap it Up

A series like this could go on for hundreds of hours, but, at some point, we have...

Watch
Build A Laravel App With TDD

Build A Laravel App With TDD

It's time to take the techniques we learned in Laravel From Scratch, and put them to good use building your first real-world application. Together, we'll leverage TDD to create Birdboard: a minimal Basecamp-like project management app.

This series will give us a wide range of opportunities to pull up our sleeves and test our Laravel chops. As always, we start from scratch: laravel new birdboard.

Begin
44
Latest Episode in This Series

Added 11 months ago

Wrap it Up

A series like this could go on for hundreds of hours, but, at some point, we have...
Watch

Your Teacher | Jeffrey Way

https://laracasts.s3.amazonaws.com/avatars/jeffrey-avatar.jpg's avatar
Hi, I'm Jeffrey. I'm the creator of Laracasts and spend most of my days building the site and thinking of new ways to teach confusing concepts. I live in Orlando, Florida with my wife and two kids.
    1. EPISODE 1

      Run Time 2:31

      Free

      Let's begin by reviewing the application that we plan to build. We'll then finish up by installing Laravel and performing the first commit.

    2. EPISODE 2

      Run Time 12:48

      Free

      My hope is to demonstrate, as much as possible, my actual workflow when writing my own applications. With that in mind, let's begin with our first feature test.

    3. EPISODE 3

      Run Time 5:32

      We haven't yet written any request validation logic. As before, let's use a TDD approach for specifying each validation requirement.

    4. EPISODE 4

      Run Time 7:33

      We must next ensure that a user can visit any project page. Though we should start with a feature test, this episode will provide a nice opportunity to pause and drop down a level to a model test.

    5. EPISODE 5

      Run Time 11:17

      It's true that we can now create and persist projects to the database, but they aren't currently associated with any user. This isn't practical. To fix this, we'll write a test to confirm that the authenticated user is always assigned as the owner of any new project that is created during their session.

    6. EPISODE 6

      Run Time 11:39

      In this episode, we'll continue tweaking which projects are displayed to the user. We'll also begin implementing the appropriate page authorization.

    7. EPISODE 7

      Run Time 6:38

      We already have the necessary logic to persist new projects, however, we haven't yet created the "create project" page, itself. Let's take care of that quickly in this episode.

    8. EPISODE 8

      Run Time 8:19

      Before I begin writing CSS, we first need to set the stage. We'll begin by pulling in all necessary npm dependencies and configuring Tailwind compilation with Laravel Mix.

    9. EPISODE 9

      Run Time 16:39

      Free

      In this episode, we'll leverage Tailwind to begin constructing the Birdboard UI.

    10. EPISODE 10

      Run Time 16:56

      Let's continue working on the CSS for the projects dashboard. This will give us an opportunity to discuss grid spacing, and how we can use a combination of padding and negative margins to perfectly align our columns.

    11. EPISODE 11

      Run Time 12:20

      Before we jump back to PHP, let's write one more lesson's worth of CSS. Specifically, we'll get the single project page up and running.

    12. EPISODE 12

      Run Time 15:24

      We've added a section to our project page for tasks, but that functionality doesn't yet exist. It sounds like we have our next step.

      View the source code for this episode on GitHub.

    13. EPISODE 13

      Run Time 9:11

      The next step is to update your project page UI to allow for displaying and adding new tasks.

    14. EPISODE 14

      Run Time 18:31

      In this episode, we'll wrap every task within a form so that we may easily update its description or completion status with the click of a button.

      View the source code for this episode on GitHub.

    15. EPISODE 15

      Run Time 5:05

      I'd like to sort all projects in our dashboard according to those that have been most recently updated. This means, when you add or modify a task within a project, we need to touch the parent project's updated_at timestamp in the process. Let's learn how in this episode.

      View the source code for this episode on GitHub.

    16. EPISODE 16

      Run Time 18:04

      Next up, we need to make the "General Notes" section of the project page dynamic. As always, we'll use tests to drive this new update. When finished, we'll also switch over to using dedicated authorization policy classes.

      View the source code for this episode on GitHub.

    17. Let's take a moment to improve the structure of our tests. Have you noticed that, time and time again, we follow a similar pattern when arranging the world for a test? Instead, let's refactor this code into a fluent factory class to save time. To do this, we'll use a technique that I first learned from John Bonaccorsi in his Tidy up Your Tests with Class-Based Model Factories article. I encourage you to give it a read if you'd like to learn more.

      View the source code for this episode on GitHub.

    18. EPISODE 18

      Run Time 14:06

      In this lesson, we'll add a form to update an existing project. But in the process, we'll review how to reduce duplication in the create and edit views by extracting a reusable partial.

      View the source code for this episode on GitHub.

    19. We'll begin this episode by addressing a small regression that was introduced in the previous episode: we can no longer update the general notes without triggering a validation error. While of course we'll review the easy solution to this issue, we'll additionally discuss a recent user comment related to the pros and cons of extracting a form request class. Would it make the code cleaner or better? You can look forward to lots of fun tips in this episode.

      View the source code for this episode on GitHub.

    20. EPISODE 20

      Run Time 13:39

      Let's move on to our next feature: every project generates an activity feed.

      View the source code for this episode on GitHub.

    21. EPISODE 21

      Run Time 13:53

      Let's continue working on the project activity feature. We should additionally record activity when a task is created or completed. Let's take care of that in this episode.

      View the source code for this episode on GitHub.

    22. EPISODE 22

      Run Time 5:57

      Before moving on to the larger activity feed refactor, let's first make a few small tweaks to clean things up.

      View the completed source code for this episode on GitHub.

    23. EPISODE 23

      Run Time 12:08

      We have just a few loose ends to wrap up, before finally viewing the project's activity feed in the browser.

      View the source code for this episode on GitHub.

    24. EPISODE 24

      Run Time 10:35

      It's time to render a project's activity feed on the page. This will give us an opportunity to review how to use polymorphism to load the appropriate view, based on the description type of the activity.

      View the source code for this episode on GitHub.

    25. EPISODE 25

      Run Time 12:00

      Now that we're successfully displaying a project's activity feed on the page, I'd like to provide more information for each update. For example, rather than the message, "You completed a task", it should probably include the name of the task: 'You completed "Finish Lesson"'. This presents a problem because, when we record activity, we don't yet include any reference to the subject. Let's fix that in this episode.

      View the source code for this episode on GitHub.

    26. EPISODE 26

      Run Time 15:49

      Our next job is to track which attributes have changed when a model is updated. This will allow us to record, for example, that the user changed the title of the project from "Test Project" to "Real Project".

      View the source code for this episode on GitHub.

    27. EPISODE 27

      Run Time 21:47

      In this episode, we'll refactor all "activity" functionality to a reusable trait. As you'll see, we'll quickly fall into a rapid refactor flow: make a small tweak, run the tests, see green, make another small tweak, rinse and repeat.

    28. EPISODE 28

      Run Time 13:51

      Let's work on tweaking the output of the activity card in this lesson. I'd like it to show which fields were updated, and who performed the update.

      View the source code for this episode on GitHub.

    29. We have an easy one this episode: users who have the proper permissions may delete or archive projects. Let's knock that out now, before moving on to something more exciting in the next episode.

      View the source code for this episode on GitHub.

    30. EPISODE 30

      Run Time 12:43

      As we move on to inviting users to projects, this will give us a nice opportunity to discuss layered tests. In this episode, we'll write the same test name at two different levels: from the outside-in (feature), and at a lower level (unit).

      View the source code for this episode on GitHub.

    31. EPISODE 31

      Run Time 14:08

      In this episode, as we work to allow users to see all projects they've been invited to from their dashboard, we'll also discuss false positives. A passing test doesn't always guarantee that your code works as expected.

      View the source code for this episode on GitHub.

    32. EPISODE 32

      Run Time 7:26

      Our project page doesn't yet display all members who have access to it. Let's use Gravatar to generate these thumbnails. In doing so, this will give us the opportunity to discuss how to create and load a helper functions file.

      View the source code for this episode on GitHub.

    33. EPISODE 33

      Run Time 15:11

      In this episode, we'll write a few new feature tests to confirm the conditions under which a project owner may invite a user to a project.

      View the source code for this episode on GitHub.

    34. EPISODE 34

      Run Time 13:57

      Once you add multiple forms to a page, you'll quickly find that you can no longer depend on the default validation errors "bag." In this episode, we'll learn how to associate your form request class with a named error bag.

      View the source code for this episode on GitHub.

    35. It looks like we have a small hiccup. At the moment, any invited user has permission to delete the project entirely. This action should be restricted to the owner of the project exclusively.

      View the source code for this episode on GitHub.

    36. EPISODE 36

      Run Time 14:06

      Free

      We have a relatively nice light theme at the moment. But what if we wanted to offer users the ability to toggle to a darker UI theme? How exactly might we accomplish that, considering that Tailwind classes like text-grey and text-blue are scattered throughout our HTML? The answer is to leverage CSS variables. I'll show you how in this episode.

      View the source code for this episode on GitHub.

    37. EPISODE 37

      Run Time 2:15

      Free

      Behind the scenes, I've finished up our two themes. Before moving on to building the theme switcher, very quickly, let's review the results as well as the organizational structure I opted for.

      View the source code for this episode on GitHub.

    38. EPISODE 38

      Run Time 15:07

      Now that we have multiple UI themes available to us, the next step is to construct a theme switcher that we'll position in the navigation bar of our site. Because there's behavior associated with each theme button, we'll use Vue to build this little component.

      View the source code for this episode on GitHub.

    39. EPISODE 39

      Run Time 12:20

      Because we're approaching the end of this series, let's dedicate a few episodes to reviewing some JavaScript-specific enhancements. Specifically, we'll transition the "New Project" form into a dynamic modal Vue component.

      To begin, we'll pull in the vue-js-modal component and construct the design of our form with Tailwind.

    40. EPISODE 40

      Run Time 17:51

      Now that the basic styling for the "New Project" modal is complete, we can move on to its behavior. Luckily, because we have Vue backing us up each step of the way, this should be a cinch to complete.

    41. EPISODE 41

      Run Time 4:45

      There's one final step to complete: our controller doesn't yet allow tasks to be created alongside the project. Let's fix that now.

      View the source code for this episode on GitHub.

    42. EPISODE 42

      Run Time 20:44

      If we take another look at our NewProjectModal file, you'll notice that most of the JavaScript deals with the submission and handling of the form. It sure would be a shame to repeat this same generic code for every form in our application. With that in mind, let's extract a BirdboardForm class to help clean things up a bit.

      View the source code for this episode on GitHub.

    43. EPISODE 43

      Run Time 23:27

      Let's wrap things up by creating a reusable dropdown Vue component from scratch.

      View the source code for this episode on GitHub.

    44. EPISODE 44

      Run Time 1:37

      A series like this could go on for hundreds of hours, but, at some point, we have to wrap things up. That time is now. Let's do one final review of what we accomplished before saying our goodbyes!

      View the source code for this series on GitHub.