Laravel — P8: Blade Introduction

Using the Blade Engine to Remove PHP

Blade is a templating engine that allows you to write some front-end friendly code. The last thing that the designer wants to see is PHP wrapped up inside of the views. Looking at Blade components, you’ll quickly appreciate the elegance in the appearance vs the mess that PHP can create when used outside of the backend. Blade templates are compiled into PHP code, but we don’t need to worry about it. As long as we use the correct tags, Laravel/Blade will take care of this for us.

.blade.php

In order to use the Blade templating engine, your file names need to end in .blade.php. Where are they located? In the same directory that we have been working on this whole time: resources/views.

One such blade file that we created in the previous article is resources/views/cars/index.blade.php. It currently outputs a list of my favorite cars wrapped in a ul list.

<ul>
    <li>2003 Chevy Corvette</li>
    <li>2007 Chevy Corvette</li>
    <li>1999 Nissan Skyline GT-R</li>
    <li>2021 Nissan GT-R</li>
    <li>2022 Porsche 911 GT3</li>
    <li>1994 Toyota Supra 2JZGTE</li>
    <li>1989 Nissan 240SX Hatchback</li>
    <li>2019 Subaru WRX STi</li>
    <li>1998 Dodge Viper GTS-R</li>
</ul>

We want to be able to pass a list of cars as an array to our blade view and have the view loop through it and display it on the screen. So let’s do that.

Create a new route: /cars/favorite. This route will return a new blade view after it passes it an array of vehicle data.

<?php
// ...
Route::get('/cars/my/favorites', function() {
    return view('cars/favorite', [
        'cars' => [
            "2003 Chevy Corvette",
            "2007 Chevy Corvette",
            "1999 Nissan Skyline GT-R",
            "2021 Nissan GT-R",
            "2022 Porsche 911 GT3",
            "1994 Toyota Supra 2JZGTE",
            "1989 Nissan 240SX Hatchback",
            "2019 Subaru WRX STi",
            "1998 Dodge Viper GTS-R",
        ]
    ]);
});

Our route calls the cars/favorite view, which doesn’t exist yet. Let’s create it.

 

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Favorite Cars</title>

    <!-- Fonts -->
    <link href="https://fonts.bunny.net/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">

    <!-- Styles -->
    <style>
        /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.text-center{text-align:center}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity))}.dark\:bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity))}.dark\:border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity))}.dark\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.dark\:text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.dark\:text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}}
    </style>
</head>
<body class="p-6">
<h1>Here's a list of my favorite cars</h1>
<ul>
    <!-- This is where our list of cars will go -->
</ul>
</body>
</html>
How do we access the array of data that we just passed? Our array key is named cars, so we should have access to the $cars array. We can inject pure PHP into this and var_dump the $cars array.
<ul>
    <!-- This is where our list of cars will go -->
    <?php
        var_dump($cars);
    ?>
</ul>
The output looks like this.

Since we know that we have data coming in, we can simply loop through it with a foreach loop.
<ul>
    <!-- This is where our list of cars will go -->
    <?php
    foreach ($cars as $car) {
        echo "<li>" . $car . "</li>";
    }
    ?>
</ul>

Looks like PHP code mixed in with HTML. Not what we want to see. Let’s look at the rendered page.

How would we do this with Blade?

The Blade directive for a PHP foreach loop is simply @foreach. To end the foreach loop, you use @endforeach.

<ul>
    @foreach($cars as $car)
        <li>{{ $car }}</li>
    @endforeach
</ul>

So much cleaner. We loop through each of the $cars and output the value of $car. The {{ }} is what allows the variable to be evaluated. It’s pretty much like saying echo with the exception that it also automatically sends the data through PHP’s htmlspecialchars function to prevent XSS attacks.

If you refresh your page, you won’t notice a difference. The HTML that was generated is identical, but you can’t deny that the code looks much cleaner now.

Next

That’s it for this quick intro. We’ll continue looking at Blade in detail in the next article, where we’ll cover:

  • Displaying Data
  • Displaying Unescaped Data
  • If Statements
  • Switch Statements
  • Loops
  • The Loop Variable
  • Including Subviews

See you next time.

Laravel Series

Continue your Laravel Learning.

Laravel — P7: View Subdirectories and Checks

Organize Your Views Better With Subdirectories

Laravel – P7: View Subdirectories and Checks

We know how to grab URL parameters and return them from our route, but how do we pass arguments to the view?

Laravel — P8: Blade Introduction

Using the Blade Engine to Remove PHP

Laravel – P8: Blade Introduction

Blade is a templating engine that allows you to write some front-end friendly code. The last thing we want to see is PHP wrapped up inside of the views.

Laravel — P9- Displaying Data in Blade Files

Discussing Blade Directives

Laravel – P9: Displaying Data In Blade

What we really wanted to achieve was introduce what Blade is, understand that there are Blade Directives. These directives make our lives easier and not PHP.

Leave a Reply