PHPackages                             lalaz/web - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. lalaz/web

ActiveLibrary[Templating &amp; Views](/categories/templating)

lalaz/web
=========

Views, templates, sessions, CSRF protection, and rendering utilities.

v1.0.0-rc.2(5mo ago)03MITPHPPHP ^8.3

Since Dec 11Pushed 5mo agoCompare

[ Source](https://github.com/lalaz-foundation/web)[ Packagist](https://packagist.org/packages/lalaz/web)[ RSS](/packages/lalaz-web/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (3)Versions (3)Used By (0)

Lalaz Web
=========

[](#lalaz-web)

Views, templates, sessions, CSRF protection, components, and rendering utilities for the Lalaz Framework.

Installation
------------

[](#installation)

```
composer require lalaz/web
```

Features
--------

[](#features)

- **View Responses** - Return-based view rendering with fluent API
- **Template Engines** - Twig integration out of the box
- **Components** - Reusable UI components with props
- **View Composers** - Automatic data injection into views
- **CSRF Protection** - Built-in CSRF token handling
- **Session Management** - Secure session handling with fingerprinting
- **Flash Messages** - Easy flash message management
- **Form Validation UX** - Old input and error bag support
- **Method Spoofing** - PUT/PATCH/DELETE support via `_method` field
- **Form Helpers** - Auto-generated form HTML with validation integration

Quick Start
-----------

[](#quick-start)

### View Responses

[](#view-responses)

Return views from your controllers:

```
use function view;

class UserController
{
    public function index(): ViewResponse
    {
        return view('users/index', ['users' => User::all()]);
    }

    public function show(int $id): ViewResponse
    {
        return view('users/show', ['user' => User::find($id)])
            ->layout('layouts/admin');
    }
}
```

### Redirects with Flash Data

[](#redirects-with-flash-data)

```
use function redirect;
use function back;

class UserController
{
    public function store(Request $request): RedirectResponse
    {
        $validator = new Validator($request->post());

        if (!$validator->validate(['email' => 'required|email'])) {
            return back()
                ->withInput()
                ->withErrors($validator->errors());
        }

        User::create($request->post());

        return redirect('/users')
            ->with('success', 'User created successfully!');
    }
}
```

### Components

[](#components)

Create reusable components:

```
// app/View/Components/Alert.php
namespace App\View\Components;

use Lalaz\Web\View\Components\Component;

class Alert extends Component
{
    public function __construct(
        public string $type = 'info',
        public string $message = ''
    ) {}

    public function render(): string
    {
        return 'components/alert'; // Template path
    }
}
```

Use in Twig templates:

```
{{ component('alert', { type: 'success', message: 'Done!' }) }}
```

### View Composers

[](#view-composers)

Inject data into views automatically:

```
// app/View/Composers/NavigationComposer.php
namespace App\View\Composers;

use Lalaz\Web\View\Composer;

class NavigationComposer extends Composer
{
    protected array $views = ['layouts/*', 'partials/navigation'];

    public function compose(array &$data): void
    {
        $data['navigation'] = $this->getNavigationItems();
    }
}
```

### Old Input &amp; Validation Errors

[](#old-input--validation-errors)

In your Twig templates:

```

    {{ csrfField() | raw }}

    {% if hasErrors() %}

                {% for msg in allErrors() %}
                    {{ msg }}
                {% endfor %}

    {% endif %}

        Email

        {% if hasError('email') %}
            {{ error('email') }}
        {% endif %}

    Submit

```

### Method Spoofing

[](#method-spoofing)

HTML forms only support GET and POST. Use method spoofing to send PUT, PATCH, or DELETE requests:

**1. Register the middleware (in your bootstrap or routes):**

```
use Lalaz\Web\Http\Middlewares\MethodSpoofingMiddleware;

$router->middleware(MethodSpoofingMiddleware::class);
```

**2. Use in forms:**

```
{# Manual hidden field #}

    {{ csrfField() | raw }}
    {{ methodField('DELETE') | raw }}
    Delete User

{# Or using formOpen helper (auto-adds method field) #}
{{ formOpen('/users/5', 'DELETE') | raw }}
    Delete User
{{ formClose() | raw }}
```

The middleware also supports the `X-HTTP-Method-Override` header for API clients.

### Form Helpers

[](#form-helpers)

Generate form HTML with automatic old input and error integration:

```
{{ formOpen('/users', 'POST', { class: 'form', id: 'user-form' }) | raw }}

    {{ inputText('name', { label: 'Full Name', required: true, placeholder: 'John Doe' }) | raw }}

    {{ inputEmail('email', { label: 'Email Address', required: true }) | raw }}

    {{ inputPassword('password', { label: 'Password', required: true }) | raw }}

    {{ textarea('bio', { label: 'Biography', rows: 4 }) | raw }}

    {{ select('country', { label: 'Country', placeholder: 'Select a country' }, {
        us: 'United States',
        uk: 'United Kingdom',
        ca: 'Canada'
    }) | raw }}

    {{ checkbox('newsletter', { label: 'Subscribe to newsletter' }) | raw }}

    {{ submitButton('Create User') | raw }}

{{ formClose() | raw }}
```

**Edit forms with PUT method:**

```
{{ formOpen('/users/5', 'PUT') | raw }}
    {{ inputText('name', { label: 'Name', value: user.name }) | raw }}
    {{ inputEmail('email', { label: 'Email', value: user.email }) | raw }}
    {{ submitButton('Update') | raw }}
{{ formClose() | raw }}
```

Form helpers automatically:

- Populate fields with old input after validation failures
- Add error CSS classes to invalid fields
- Display error messages below fields
- Handle method spoofing for PUT/PATCH/DELETE

Template Functions
------------------

[](#template-functions)

Available in Twig templates:

FunctionDescription`view('template', data)`Render a view`partial('template', data)`Render partial (no layout)`redirect(url)`Create redirect response`back()`Redirect to previous URL`old('field', default)`Get old input value`error('field')`Get first error for field`fieldErrors('field')`Get all errors for field`hasError('field')`Check if field has errors`hasErrors()`Check if any errors exist`allErrors()`Get all error messages`errorBag()`Get ErrorBag instance`csrfToken()`Get CSRF token value`csrfField()`Render CSRF hidden input`methodField('PUT')`Render method spoofing hidden input`formOpen(action, method, attrs)`Open form tag with CSRF`formClose()`Close form tag`inputText(name, options)`Text input with label/error`inputEmail(name, options)`Email input with label/error`inputPassword(name, options)`Password input with label/error`inputNumber(name, options)`Number input with label/error`inputHidden(name, value)`Hidden input field`textarea(name, options)`Textarea with label/error`select(name, options, choices)`Select dropdown with label/error`checkbox(name, options)`Checkbox with label`radio(name, value, options)`Radio button with label`submitButton(text, options)`Submit button`asset('path')`Resolve Vite asset path`route('name')`Generate route URL`component('name', props)`Render a component`showFlashMessage('key')`Display flash messageCLI Commands
------------

[](#cli-commands)

Generate boilerplate with craft commands:

```
# Create a view template
php lalaz craft:view users/index

# Create a component
php lalaz craft:component Alert --props="type,message"

# Create a view composer
php lalaz craft:composer NavigationComposer --views="layouts/*"
```

API Reference
-------------

[](#api-reference)

### ViewResponse

[](#viewresponse)

```
$response = view('template', $data, $statusCode)
    ->layout('layouts/main')
    ->with('key', 'value')
    ->header('X-Custom', 'value')
    ->status(201);
```

### RedirectResponse

[](#redirectresponse)

```
$response = redirect('/url')
    ->withInput()                      // Flash all input
    ->withInput(['email', 'name'])     // Flash specific fields
    ->withInputExcept(['password'])    // Flash except fields
    ->withErrors($errors)              // Flash validation errors
    ->with('key', 'value')             // Flash custom data
    ->status(301);                     // Change status code
```

### ErrorBag

[](#errorbag)

```
$bag = ErrorBag::fromArray($validatorErrors);

$bag->has('email');           // Check if field has errors
$bag->has();                  // Check if any errors
$bag->first('email');         // First error for field
$bag->first();                // First error overall
$bag->get('email');           // All errors for field
$bag->all();                  // All errors as flat array
$bag->count();                // Total error count
$bag->isEmpty();              // Check if empty
$bag->keys();                 // Field names with errors
$bag->toArray();              // Convert to array
```

### FormBuilder

[](#formbuilder)

Use directly in PHP or via Twig helpers:

```
use Lalaz\Web\View\Form\FormBuilder;

$form = new FormBuilder();

// Method spoofing field
$form->method('DELETE');  //

// CSRF field
$form->csrf($token);      //

// Open/close form
$form->open('/users', 'POST', ['class' => 'form']);
$form->close();

// Input fields
$form->text('name', ['label' => 'Name', 'required' => true]);
$form->email('email', ['label' => 'Email']);
$form->password('password', ['label' => 'Password']);
$form->number('age', ['label' => 'Age', 'min' => 0, 'max' => 120]);
$form->hidden('user_id', 123);
$form->textarea('bio', ['label' => 'Bio', 'rows' => 5]);

// Select dropdown
$form->select('country', [
    'label' => 'Country',
    'placeholder' => 'Choose...'
], [
    'us' => 'United States',
    'uk' => 'United Kingdom'
]);

// Checkboxes and radios
$form->checkbox('agree', ['label' => 'I agree to terms']);
$form->radio('plan', 'basic', ['label' => 'Basic Plan']);
$form->radio('plan', 'premium', ['label' => 'Premium Plan']);

// Buttons
$form->submit('Save');
$form->button('Cancel', ['type' => 'button', 'class' => 'btn-secondary']);
```

**Input Options:**

OptionDescription`label`Label text`required`Show required indicator`placeholder`Input placeholder text`class`CSS class for wrapper`inputClass`CSS class for input element`value`Default value (overridden by old input)`id`Custom ID (defaults to name)`min`, `max`, `step`Number input constraints`rows`Textarea rows### MethodSpoofingMiddleware

[](#methodspoofingmiddleware)

```
use Lalaz\Web\Http\Middlewares\MethodSpoofingMiddleware;

// Global middleware
$router->middleware(MethodSpoofingMiddleware::class);

// Or per-route group
$router->group(['middleware' => MethodSpoofingMiddleware::class], function ($router) {
    $router->put('/users/:id', [UserController::class, 'update']);
    $router->delete('/users/:id', [UserController::class, 'destroy']);
});
```

Supports:

- Hidden `_method` form field
- `X-HTTP-Method-Override` header
- Allowed methods: PUT, PATCH, DELETE

License
-------

[](#license)

MIT

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance72

Regular maintenance activity

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

2

Last Release

155d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1656ce2106f240db55a76bb5213ef5da4007532661adf4ef89e44eefe7e79112?d=identicon)[lalaz](/maintainers/lalaz)

---

Top Contributors

[![gregserrao](https://avatars.githubusercontent.com/u/1245169?v=4)](https://github.com/gregserrao "gregserrao (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/lalaz-web/health.svg)

```
[![Health](https://phpackages.com/badges/lalaz-web/health.svg)](https://phpackages.com/packages/lalaz-web)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[whitecube/nova-flexible-content

Flexible Content &amp; Repeater Fields for Laravel Nova.

8053.0M25](/packages/whitecube-nova-flexible-content)[mopa/bootstrap-bundle

Easy integration of twitters bootstrap into symfony2

7042.9M33](/packages/mopa-bootstrap-bundle)[limenius/react-bundle

Client and Server-side react rendering in a Symfony Bundle

3871.2M](/packages/limenius-react-bundle)[nicmart/string-template

StringTemplate is a very simple string template engine for php. I've written it to have a thing like sprintf, but with named and nested substutions.

2101.7M30](/packages/nicmart-string-template)[symfony/ux-icons

Renders local and remote SVG icons in your Twig templates.

555.8M69](/packages/symfony-ux-icons)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
