Skip to content

07 Advanced Features

Rumen Damyanov edited this page Jul 29, 2025 · 1 revision

Advanced Features

This guide covers advanced features and techniques for the php-assets package.

Wildcard Asset Loading

Load multiple assets using wildcard patterns:

<?php

use Rumenx\Assets\Asset;

// Load all CSS files from a directory
Asset::add('css/components/*.css');

// Load specific versioned files
Asset::add('js/jquery/jquery-*.min.js');
Asset::add('css/bootstrap/bootstrap-*.min.css');

// Load from CDN with wildcards (limited support)
Asset::add('https://cdn.example.com/libs/jquery-*.min.js');

Inline Scripts and Styles

Add inline JavaScript and CSS:

<?php

use Rumenx\Assets\Asset;

// Add inline JavaScript
$script = '
$(document).ready(function() {
    console.log("Document ready!");
});
';
Asset::addScript($script, 'ready');

// Add inline CSS
$style = '
body {
    background-color: #f0f0f0;
}
.highlight {
    background-color: yellow;
}
';
Asset::addStyle($style);

// Output inline scripts and styles
echo Asset::styles();           // Inline CSS
echo Asset::scripts('ready');   // jQuery ready scripts
echo Asset::scripts('footer');  // Footer scripts

Raw Output Methods

Get assets without HTML wrapper tags:

<?php

use Rumenx\Assets\Asset;

Asset::add('css/app.css');
Asset::add('css/components.css');
Asset::add('js/app.js');
Asset::add('js/utils.js');

// Raw CSS output (no <link> tags)
$cssFiles = Asset::cssRaw('\n');
echo $cssFiles;
// Output: css/app.css
//         css/components.css

// Raw JS output (no <script> tags)
$jsFiles = Asset::jsRaw('\n');
echo $jsFiles;
// Output: js/app.js
//         js/utils.js

// Custom processing
$assets = explode('\n', Asset::cssRaw('\n'));
foreach ($assets as $asset) {
    echo '<link rel="preload" href="' . $asset . '" as="style">' . "\n";
}

Custom Asset Types

Handle custom file types and extensions:

<?php

use Rumenx\Assets\Asset;

// Add custom extension handling
Asset::add('styles/theme.scss');   // SCSS files
Asset::add('scripts/app.ts');      // TypeScript files
Asset::add('data/config.json');    // JSON files

// The package will handle unknown extensions gracefully
// You can process them in your build pipeline

Asset Ordering and Dependencies

Advanced asset ordering and dependency management:

<?php

use Rumenx\Assets\Asset;

// Define dependency chain
Asset::add('js/jquery.min.js');              // Base dependency
Asset::addAfter('js/bootstrap.min.js', 'js/jquery.min.js');  // Depends on jQuery
Asset::addAfter('js/app.js', 'js/bootstrap.min.js');         // Depends on Bootstrap

// Complex ordering
Asset::addFirst('js/polyfills.js');          // Must load first
Asset::add('js/vendor.js');                  // Standard loading
Asset::addBefore('js/config.js', 'js/app.js'); // Config before app
Asset::add('js/app.js');                     // Main application
Asset::addAfter('js/analytics.js', 'js/app.js'); // Analytics last

// Final order: polyfills → vendor → jquery → bootstrap → config → app → analytics

Conditional Asset Loading

Load assets based on conditions:

<?php

use Rumenx\Assets\Asset;

// Browser-specific assets
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
if (strpos($userAgent, 'MSIE') !== false) {
    Asset::add('css/ie-fixes.css');
    Asset::add('js/ie-polyfills.js');
}

// Mobile-specific assets
if (wp_is_mobile()) { // WordPress function example
    Asset::add('css/mobile.css');
    Asset::add('js/touch.js');
}

// Feature detection
if (class_exists('SomeFeature')) {
    Asset::add('css/feature.css');
    Asset::add('js/feature.js');
}

// Route-based loading
$currentRoute = $_SERVER['REQUEST_URI'] ?? '';
if (strpos($currentRoute, '/admin') === 0) {
    Asset::add('css/admin.css');
    Asset::add('js/admin.js');
}

Asset Minification Integration

Integrate with minification tools:

<?php

use Rumenx\Assets\Asset;

class AssetMinifier
{
    public static function configure()
    {
        $env = Asset::getEnvironment();

        if ($env === 'production') {
            // Prefer minified versions
            Asset::add('css/app.min.css');
            Asset::add('js/app.min.js');
        } else {
            // Use development versions
            Asset::add('css/app.css');
            Asset::add('js/app.js');
        }
    }

    public static function buildMinified()
    {
        // This would integrate with your build process
        // Example: Gulp, Webpack, etc.

        $cssFiles = Asset::cssRaw('\n');
        $jsFiles = Asset::jsRaw('\n');

        // Process with your minifier
        // Save as .min.css and .min.js versions
    }
}

Asset Preloading

Generate preload hints for better performance:

<?php

use Rumenx\Assets\Asset;

class AssetPreloader
{
    public static function generatePreloadHints()
    {
        $cssFiles = explode('\n', Asset::cssRaw('\n'));
        $jsFiles = explode('\n', Asset::jsRaw('\n'));

        $preloads = '';

        // Critical CSS preloads
        foreach ($cssFiles as $css) {
            if (!empty($css)) {
                $preloads .= '<link rel="preload" href="' . $css . '" as="style">' . "\n";
            }
        }

        // Important JS preloads
        foreach ($jsFiles as $js) {
            if (!empty($js) && strpos($js, 'critical') !== false) {
                $preloads .= '<link rel="preload" href="' . $js . '" as="script">' . "\n";
            }
        }

        return $preloads;
    }
}

// Usage
Asset::add('css/critical.css');
Asset::add('css/app.css');
Asset::add('js/critical.js');
Asset::add('js/app.js');

echo AssetPreloader::generatePreloadHints();

Performance Monitoring

Monitor asset loading performance:

<?php

use Rumenx\Assets\Asset;

class AssetMonitor
{
    private static $loadTimes = [];

    public static function startTimer($asset)
    {
        self::$loadTimes[$asset] = microtime(true);
    }

    public static function endTimer($asset)
    {
        if (isset(self::$loadTimes[$asset])) {
            $duration = microtime(true) - self::$loadTimes[$asset];
            error_log("Asset {$asset} loaded in {$duration}s");
        }
    }

    public static function generateReport()
    {
        $cssCount = count(explode('\n', Asset::cssRaw('\n')));
        $jsCount = count(explode('\n', Asset::jsRaw('\n')));

        return [
            'css_files' => $cssCount,
            'js_files' => $jsCount,
            'total_assets' => $cssCount + $jsCount,
            'environment' => Asset::getEnvironment(),
        ];
    }
}

Security Considerations

Implement security best practices:

<?php

use Rumenx\Assets\Asset;

class SecureAssets
{
    private static $allowedDomains = [
        'cdn.example.com',
        'assets.example.com',
        'static.example.com'
    ];

    public static function validateAssetUrl($url)
    {
        // Validate external URLs
        if (filter_var($url, FILTER_VALIDATE_URL)) {
            $domain = parse_url($url, PHP_URL_HOST);
            return in_array($domain, self::$allowedDomains);
        }

        // Local files should not contain dangerous patterns
        if (strpos($url, '..') !== false || strpos($url, '<') !== false) {
            return false;
        }

        return true;
    }

    public static function addSecureAsset($url, $group = null)
    {
        if (self::validateAssetUrl($url)) {
            Asset::add($url, $group);
        } else {
            error_log("Rejected unsafe asset URL: {$url}");
        }
    }
}

// Usage
SecureAssets::addSecureAsset('css/app.css');
SecureAssets::addSecureAsset('https://cdn.example.com/lib.js');

Integration with Build Tools

Example integration with popular build tools:

<?php

use Rumenx\Assets\Asset;

// Webpack integration
class WebpackIntegration
{
    public static function loadManifest()
    {
        $manifest = json_decode(file_get_contents('public/dist/manifest.json'), true);

        foreach ($manifest as $original => $compiled) {
            Asset::add($compiled);
        }
    }
}

// Vite integration
class ViteIntegration
{
    public static function loadAssets()
    {
        if (Asset::getEnvironment() === 'development') {
            // Vite dev server
            Asset::add('http://localhost:3000/@vite/client');
            Asset::add('http://localhost:3000/src/main.js');
        } else {
            // Production build
            $manifest = json_decode(file_get_contents('public/dist/manifest.json'), true);
            Asset::add('dist/' . $manifest['src/main.js']['file']);
            Asset::add('dist/' . $manifest['src/main.css']['file']);
        }
    }
}

Related Examples

Clone this wiki locally