Using assets #1 - create assets

An asset in Yii is a file that may be referenced in a web page. It can be a css file, a javascript file, an image or video file, etc. Assets are located in web-accessible directories and are directly served by web servers.

It is often preferable to manage assets programmatically. For example, when you use the widget in a page, it will automatically include the required css and javascript files, instead of asking you to manually find these files and include them. And when you upgrade the widget to a new version, it will automatically use the new version of the asset files. In this tutorial, we will describe the powerful asset management capability provided in Yii.

Asset Bundles.

Yii manages assets in the unit of asset bundle. An asset bundle is simply a collection of assets located in a directory. When you register an asset bundle in a view, it will include the css and javaScript files in the bundle in the rendered Web page.

Defining Asset Bundles.

Asset bundles are specified as PHP classes extending from AssetBundle::class. The name of a bundle is simply its corresponding fully qualified PHP class name (without the leading backslash). An asset bundle class should be autoloadable. It usually specifies where the assets are located, what css and javaScript files the bundle contains, and how the bundle depends on other bundles.

Let’s review this example, to use bootstrap5 in our app template.

file: src/Asset/Bootstrap5Asset.php

<?php

declare(strict_types=1);

namespace App\Asset;

use Yiisoft\Assets\AssetBundle;
use Yiisoft\Files\PathMatcher\PathMatcher;

final class Bootstrap5Asset extends AssetBundle
{
    public string|null $basePath = '@assets';
    public string|null $baseUrl = '@assetsUrl';
    public string|null $sourcePath = '@npm/bootstrap/dist';
    public array $css = ['css/bootstrap.css'];
    public array $js = ['js/bootstrap.bundle.js'];

    public function __construct()
    {
        $pathMatcher = new PathMatcher();

        // We define only the files to import with PathMatcher in this way,
        // we avoid importing the whole package unnecessarily.
        $this->publishOptions = [
            'filter' => $pathMatcher->only(
                '**css/bootstrap.css',
                '**css/bootstrap.css.map',
                '**js/bootstrap.bundle.js',
                '**js/bootstrap.bundle.js.map',
            ),
        ];
    }
}

In the above code we can observe the following:

  • basePath: The web public directory that contains the asset files in this bundle.
  • baseUrl: The base URL for the relative asset files listed in $js and $css.
  • sourcePath: The directory that contains the source asset files for this asset bundle.
  • css: List of CSS files that this bundle contains.
  • js: List of JavaScript files that this bundle contains.
  • publishOptions: The options to be passed to \Yiisoft\Assets\AssetPublisher::publish()
    when the asset bundle is being published.

Now suppose we want to define the assets using bootstrap5 CDN.

file: src/Asset/Bootstrap5CdnAsset.php

<?php

declare(strict_types=1);

namespace App\Asset\Bootstrap5;

use Yiisoft\Assets\AssetBundle;

final class Bootstrap5CdnAsset extends AssetBundle
{
    public bool $cdn = true;
    public array $css = [
        'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css',
    ];
    public array $cssOptions = [
        'integrity' => 'sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD',
        'crossorigin' => 'anonymous',
    ];
    public array $js = [
        'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css',
    ];
    public array $jsOptions = [
        'integrity' => 'sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN',
        'crossorigin' => 'anonymous',
    ];
}

In the above code we can observe the following:

  • cdn: Indicates if we are going to use CDN exclusively.
  • cssOptions: The options that will be passed to \Yiisoft\View\WebView::setCssFiles().
  • jsOptions: The options that will be passed to \Yiisoft\View\WebView::setJsFiles().

Now let’s define the asset for bootstrap5 Icons.

file: src/Asset/Bootstrap5IconsAsset.php

<?php

declare(strict_types=1);

namespace App\Asset\Bootstrap5;

use Yiisoft\Assets\AssetBundle;
use Yiisoft\Files\PathMatcher\PathMatcher;

final class Bootstrap5IconsAsset extends AssetBundle
{
    public string|null $basePath = '@assets';
    public string|null $baseUrl = '@assetsUrl';
    public string|null $sourcePath = '@npm/bootstrap-icons';
    public array $css = ['font/bootstrap-icons.css'];

    public function __construct()
    {
        $pathMatcher = new PathMatcher();

        // We define only the files to import with PathMatcher in this way,
        // we avoid importing the whole package unnecessarily.
        $this->publishOptions = [
            'filter' => $pathMatcher->only(
                '**/font/bootstrap-icons.css',
                '**/font/fonts/*',
                '**/bootstrap-icons.svg',
            ),
        ];
    }
}

Now let’s define a custom js for form custom validations with bootstrap5.

file: ./resources/asset/Bootstrap5Validation.js

// Example starter JavaScript for disabling form submissions if there are invalid fields
(function () {
    'use strict'

    // Fetch all the forms we want to apply custom Bootstrap validation styles to
    var forms = document.querySelectorAll('.needs-validation')

    // Loop over them and prevent submission
    Array.prototype.slice.call(forms)
      .forEach(function (form) {
        form.addEventListener('submit', function (event) {
          if (!form.checkValidity()) {
            event.preventDefault()
            event.stopPropagation()
          }

          form.classList.add('was-validated')
        }, false)
      })
  })()
file: src/Asset/Bootstrap5ValidationAsset.php

<?php

declare(strict_types=1);

namespace App\Asset\Bootstrap5;

use Yiisoft\Assets\AssetBundle;
use Yiisoft\Files\PathMatcher\PathMatcher;

final class Bootstrap5ValidationAsset extends AssetBundle
{
    public string|null $basePath = '@assets';
    public string|null $baseUrl = '@assetsUrl';
    public string|null $sourcePath = '@resources';
    public array $js = ['assets/bootstrap5Validation.js'];
    public array $depends = [Bootstrap5Asset::class];

    public function __construct()
    {
        $pathMatcher = new PathMatcher();

        // We define only the files to import with PathMatcher in this way,
        // we avoid importing the whole package unnecessarily.
        $this->publishOptions = [
            'filter' => $pathMatcher->only(
                '**/assets/bootstrap5Validation.js',
            ),
        ];
    }
}

In the above code we can observe the following:

  • depends: List of bundle class names that this bundle depends on. Register dependencies first, then register the current asset.

In this post today we learned how to create our assets, using local assets, CDN, and customs assets, in the next post we will see how to register them in the view, and how to use SASS to customize our assets and then compress.

If you want to review all the options you can define in an AssetBundle see the link below.

Wilmer Arámbula.
Twitter follow

2 Likes