Laravel: How to create view helpers

Carlos Costa • 31/10/2024 View helpers are a simple way to reuse code in multiple views; let's see how to use service providers to create these helpers.

Introduction


Sometimes we need to reuse code in multiple views. For example, I have a function that returns a thumbnail of a YouTube video, or a function that returns the favicon of a website, or that formats some text. Service providers can be a good solution to reuse this code in multiple views.

In Laravel, a Service Provider is a central place where you can configure and bind services to the Laravel service container. Service Providers manage the bootstrapping of application services, helping organize and group related functionality.

Okay, let’s learn how to create a service provider to share our functions across multiple views.

Helper functions


Our file will be created in app/Helpers/ViewHelpers.php. Example:

//app/Helpers/ViewHelpers.php

//get the YouTube ID from a YouTube URL
if (!function_exists('getYoutubeId')) {
    function getYoutubeId($url)
    {
        $pattern = '/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/i';
        preg_match($pattern, $url, $matches);

        return isset($matches[1]) ? $matches[1] : false;
    }
}

//get the thumbnail of a YouTube video
if (!function_exists('getYoutubeThumbnail')) {
    function getYoutubeThumbnail($id)
    {
        return "https://img.youtube.com/vi/{$id}/mqdefault.jpg";
    }
}

// get the favicon of a website
if (!function_exists('getFavicon')) {
    function getFavicon($url)
    {
        $url = parse_url($url);
        return "https://www.google.com/s2/favicons?domain=" . $url['host'] . '&sz=128';
    }
}

function_exists() is a PHP function that checks if a function exists in the current scope. If the function doesn’t exist, it will return false, otherwise, it will return true.

Now, let’s create a service provider to register our functions.

Creating a service provider


First of all, we need to run the following command from php artisan:

php artisan make:provider HelpersServiceProvider

That command will create and register our service provider.

Or file will look like this:

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        require_once app_path('Helpers/ViewHelpers.php');
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        //
    }
}

The line require_once app_path('Helpers/ViewHelpers.php'); will include the file ViewHelpers.php in the current scope, then we can use the functions in our views.

Automatically, Laravel will register our service provider in the bootstrap/providers.php file:

return [
    App\Providers\AppServiceProvider::class,
    App\Providers\HelperServiceProvider::class,
];

Now, we can use our functions in our views:

@php
    $video = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
@endphp

<img src="{{ getYoutubeThumbnail(getYoutubeId($video)); }}">

Tests


To conclude, let’s apply some tests to our helpers. With this command, Laravel will create a test file for our helpers in tests/Feature/Helpers/ViewHelpersTest.php.

php artisan make:test Helpers/ViewHelpersTest

Now, let’s write some tests.

describe('ViewHelpers', function () {
    beforeEach(function () {
        require_once app_path('Helpers/ViewHelpers.php');
    });

    test('check if getYoutubeId returns correct id', function () {
        $id = getYoutubeId('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
        $wrongId = getYoutubeId('https://www.youtube.com/watch?v=wrongId');
        $wrongUrl = getYoutubeId('https://www.google.com/watch?v=wrongId');

        $this->assertEquals('dQw4w9WgXcQ', $id);
        $this->assertEquals(false, $wrongId);
        $this->assertEquals(false, $wrongUrl);
    });

    test('check if getYoutubeThumbnail returns correct thumbnail', function () {
        $thumbnail = getYoutubeThumbnail('dQw4w9WgXcQ');

        $this->assertStringContainsString('https://img.youtube.com/vi/dQw4w9WgXcQ/mqdefault.jpg', $thumbnail);
    });

    test('check if getFavicon returns correct favicon', function () {
        $favicon = getFavicon('https://www.youtube.com/watch?v=dQw4w9WgXcQ');

        $this->assertStringContainsString('https://www.google.com/s2/favicons?domain=www.youtube.com&sz=128', $favicon);
    });
});

Conclusion


Helper functions can be very useful when you need to reuse some code in multiple views. Another way to get a similar result is to use Blade directives, which can provide more complex functionality for other use cases.