Installation Add the bundle via Composer in your Laravel project (though note this is a Symfony bundle, so integration requires a bridge or custom setup):
composer require dnl/mthaml-bundle
For Laravel, you’ll need to manually register the bundle in config/app.php under extra.bundles (if using Symfony components) or create a custom wrapper.
Basic Usage
Create a .haml file (e.g., resources/views/example.haml):
%html
%head
%title My Page
%body
%h1 Hello, HAML!
= "Dynamic content: " + $variable
Render it in a Laravel controller:
use DNL\MtHamlBundle\Engine\HamlEngine;
public function show()
{
$haml = new HamlEngine();
$content = $haml->render(file_get_contents(resource_path('views/example.haml')), [
'variable' => 'World'
]);
return response($content);
}
First Use Case Replace a single Blade template with HAML for a component (e.g., a modal or form) to reduce verbosity. Compare:
<div class="modal">...</div>.modalHybrid Templating Use HAML for complex UI components (e.g., dashboards) while keeping Blade for dynamic logic-heavy views. Example:
- $user = Auth::user()
%nav
%ul
- if ($user->isAdmin())
%li= link_to_route('admin.dashboard', 'Admin')
- else
%li= link_to_route('user.dashboard', 'User')
Partial Reuse
Extract reusable HAML snippets into partials (e.g., _card.haml):
%div.card{:class => "bg-#{$color}"}
%h3= $title
= $content
Include them in other views:
= render_partial('card', title: "Feature", content: "Lorem...", color: "blue")
Asset Pipeline Compile HAML alongside Laravel Mix:
// webpack.mix.js
mix.haml('resources/views', 'public/views');
Note: Requires custom Webpack loader setup (see Gotchas).
Form Handling Generate forms with HAML’s concise syntax:
= form_open(route('posts.store'))
= text_field('post', 'title', placeholder: 'Title')
= text_area('post', 'body')
= submit_tag('Publish')
Service Provider
Bind the HAML engine to Laravel’s view factory in AppServiceProvider:
public function register()
{
$this->app->extend('view', function ($view) {
$view->engineResolver()->register('haml', function () {
return new HamlEngine();
});
});
}
Now use .haml files directly in view() calls:
return view('example.haml', ['variable' => 'World']);
Blade-HAML Interop Embed Blade directives in HAML for dynamic logic:
- if (old('status') === 'draft')
.alert= __("Post is a draft")
Symfony Dependency
ContainerInterface.symfony/var-dumper for debugging.Caching Quirks
AppServiceProvider:
$view->addExtension('haml', new HamlExtension());
php artisan config:clear
Asset Paths
asset() helper won’t resolve Laravel’s mix-manifest.json. Use:
= asset('css/app.css') # Fails
= mix('css/app.css') # Use Laravel Mix helper
Indentation Sensitivity
haml-lint in your CI.Dynamic Content
-// BAD: Heavy logic in HAML
- $filtered = collect($items)->where(...)->sortBy(...)
-// GOOD: Pre-process in controller
$this->app->register(Symfony\Bundle\DebugBundle\DebugBundle::class);
{{ dump($variable) }} in HAML to inspect data (requires Blade-HAML interop).Custom Filters Extend HAML’s syntax with custom filters:
HamlEngine::addFilter('uppercase', function ($str) {
return strtoupper($str);
});
Usage:
= "hello".uppercase
Layouts
Use haml-layout gem (not bundled) for shared layouts:
-# resources/views/layouts/application.haml
!! 5
%html
%head= yield_head
%body= yield_body
Testing Mock the HAML engine in PHPUnit:
$this->app->instance(HamlEngine::class, Mockery::mock(HamlEngine::class));
How can I help you explore Laravel packages today?