Blade Templating
TinyMVC provides a fast, lightweight laravel like Blade templating system with additional conveniences for layouts, components, and data sharing.
Basic Usage
Rendering Views
// In controllers
return view('welcome', ['name' => 'John']);
// with context
$user = User::findOrFail($id);
$posts = Post::where('user_id', $id)->get();
return view('welcome', compact('user', 'posts'));
Template Structure
views/
├── layouts/
│ └── app.blade.php # Main layout
├── components/
│ └── alert.blade.php # Reusable components
└── pages/
├── home.blade.php # Page templates
└── profile.blade.php
Spark CLI
Use the Spark CLI to generate views, and components.
php spark make:view welcome
php spark make:component alert
Template Features
Passing Data
// Controller
return view('profile', [
'user' => $user,
'title' => 'User Profile'
]);
// Template (profile.blade.php)
<h1>{{ $title }}</h1>
<p>Welcome, {{ $user->name }}></p>
Layouts
// Using layout
return view('pages.home');
// Page template (pages/home.blade.php)
@extends('layouts.app')
@section('content')
<section>
<h1>Home</h1>
<p>Welcome to the home page!</p>
<section/>
@endsection
// Layout template (layouts/app.blade.php)
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
@yield('content')
</body>
</html>
Components
// In template
<x-alert type="success" message="Updated!" />
// Component (components/alert.blade.php)
<div class="alert alert-{{ $type }}">
{{ $message }}
</div>
// Component with slot and dynamic parameters
<x-user-card :$user :profileUrl="route('profile', ['username' => $user->username])">
// user html slot content
</x-user-card>
// Component (components/user-card.blade.php)
<div class="user-card">
<a href="{{ $profileUrl }}">
<h2>{{ $user->name }}</h2>
{!! $slot !!}
</a><
</div>
Automatic Context
These variables are always available in templates:
$app // Application instance
$request // Current Request object
$session // Session object
$errors // Validation errors
$view // Current View instance
View Methods
// Share a context variable
@share('user', $user)
// Check for data in other child template
@isset($user)
@endisset
// Include template partials
@include('partials.header')
Advanced Patterns
View Composers & Custom directives
// Share or Compose to View
class AppServiceProvider
{
public function boot()
{
// Share context globally to view
View::share([
'categories' => Category::all(),
'stats' => SiteStats::get()
]);
// Set Composers to specific views
View::composer('partials.nav', function ($view) {
$view->share('friends', User::friends(auth()->id()));
});
// Add a custom directive
view()->directive('datetime', function ($expression) {
return "<?php echo carbon($expression)->diffForHumans(); ?>";
});
}
}
Error Handling
// Access all validation errors
@errors('email')
<li>{{ $message }}</li>
@enderrors
// Access a specific validation error
@error('email')
<div class="error">{{ $message }}</div>
@enderror
// Alternative, Access a specific validation error
@if ($errors->has('email'))
<div class="error">{{ $errors->first('email') }}</div>
@endif
// Access validation errors
@if ($errors->hasAny())
<div class="alert alert-danger">{{ $errors }}</div>
@endif
Full Example
// Controller
public function show($id)
{
return view('products.show', [
'product' => Product::find($id),
'related' => Product::related($id)
]);
}
// Template (products/show.blade.php)
@extends('layouts.store')
@section('content')
@include('partials.product-header')
<div class="product-details">
<h1>{{ $product->name }}</h1>
<x-price :price="$product->price" />
</div>
@endsection
@if (!empty($related))
<h2>Related Products</h2>
@include('partials.product-grid', ['products' => $related])
@endif
// Layout (layouts/store.blade.php)
<!DOCTYPE html>
<html>
<head>
<title>{{ $title ?? 'Store' }}</title>
</head>
<body>
@include('partials.nav')
<main>
@yield('content')
</main>
@include('partials.footer')
</body>
</html>
Available Blade Directives
This Blade-like template engine supports the following directives and syntax:
Directive | Description | Usage Example |
---|---|---|
{{ $var }} |
Echoes escaped content (HTML entities converted). | {{ $name }} |
{!! $var !!} |
Echoes unescaped content (raw HTML output). | {!! $html !!} |
@php ... @endphp |
Executes raw PHP code inside the template. |
@php $count = 5; @endphp |
@json($var) | Echo JSON-encoded content. | const users = @json($users) |
@extends('layout') |
Specifies a parent view to extend. | @extends('layouts.main') |
@section('name') / @endsection |
Defines a section for layout injection. |
@section('title') My Page @endsection |
@section('name', 'value') |
Defines a section inline. | @section('title', 'My Page') |
@yield('section') |
Outputs a section’s content. | @yield('content') |
@yield('section', 'default') |
Outputs section content with a default value. | @yield('title', 'Default') |
@show |
Ends section and outputs it immediately. |
@section('sidebar') Sidebar content @show |
@include('view') |
Includes another view file. | @include('partials.header') |
@includeIf('view') |
Includes view if it exists. | @includeIf('optional.view') |
@includeWhen(condition, 'view', [data]) |
Includes view only when condition is true. | @includeWhen($user, 'profile', ['user' => $user]) |
@includeUnless(condition, 'view') |
Includes view unless condition is true. | @includeUnless($user, 'guest') |
@hasSection('view') |
Checks if a section exists. |
@hasSection('sidebar') Sidebar content is available. @else No sidebar content. @endif |
@sectionMissing('view') |
Checks if a section is missing. |
@sectionMissing('sidebar') No sidebar content. @endif |
<x-name /> |
Self-closing component tag. | <x-alert type="success" /> |
<x-name>...</x-name> |
Component with content slot. |
<x-alert type="error"> Error message </x-alert> |
:attribute |
Passes a PHP variable or expression to a component attribute. | <x-alert :message="$error" /> |
@if(condition) / @endif |
Conditional block. |
@if($user) Hello, {{ $user->name }} @endif |
@elseif(condition) |
Else-if condition in an @if block. |
@elseif($admin) |
@else |
Else branch for conditionals. | @else |
@unless(condition) / @endunless |
Executes block unless condition is true. |
@unless($loggedIn) Please log in. @endunless |
@isset($var) / @endisset |
Executes block if variable is set. |
@isset($records) Records found! @endisset |
@empty($var) / @endempty |
Executes block if variable is empty. |
@empty($records) No records found. @endempty |
@for(...) / @endfor |
Classic for loop. |
@for($i = 0; $i < 10; $i++) {{ $i }} @endfor |
@foreach(...) / @endforeach |
Loops through each item. |
@foreach($users as $user) {{ $user->name }} @endforeach |
@while(condition) / @endwhile |
While loop. |
@while($count < 10) Count: {{ $count++ }} @endwhile |
@continue / @break |
Loop control statements. |
@foreach($items as $item) @if($item->skip) @continue @endif {{ $item }} @endforeach |
@switch($var) / @endswitch |
Switch statement. |
@switch($role) @case('admin') Admin panel @break @default User panel @endswitch |
@case(value) |
Case within a switch. | @case('admin') |
@default |
Default case in a switch. | @default |
@verbatim ... @endverbatim |
Outputs uncompiled content (useful for showing Blade syntax). |
@verbatim {{ This will not be compiled }} @endverbatim |
@csrf |
Outputs a hidden CSRF token input. | @csrf |
@method('PUT') |
Specifies HTTP method for form spoofing. | @method('PATCH') |
@auth ... @endauth |
Shows content only if user is authenticated. |
@auth Welcome back! @endauth |
@guest ... @endguest |
Shows content only if user is a guest. |
@guest Please log in. @endguest |
@can($ability) / @endcan |
Checks if a user has a specific ability. |
@can('edit-articles') You can edit articles. @endcan |
@cannot($ability) / @endcannot |
Checks if a user does not have a specific ability. |
@cannot('edit-articles') You cannot edit articles. @endcannot |
@vite($args) |
Includes Vite assets. |
@vite('app.jsx') |
@errors('field') |
Displays validation errors for a specific field. |
@errors('email') {{ $message }} @enderrors |
Best Practices
- Keep templates focused on presentation only
- Use components for reusable UI elements
- Pass only necessary data to views
- Store complex logic in view composers
- Use layouts for consistent page structures