Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Html Laravel Package

illuminate/html

HTML and Form helpers for Laravel, offering convenient Blade methods for building forms, inputs, links, and other HTML elements. This legacy package was part of Laravel 5 but is no longer maintained; for newer projects use Laravel Collective HTML or native Blade components.

Deep Wiki
Context7

Getting Started

First, check whether you should be here at all. illuminate/html is archived and read-only. It was the Laravel 4 HTML/Form builder, extracted into its own package for Laravel 5.0 and then abandoned in favour of laravelcollective/html. It is not maintained, gets no security fixes, and does not support Laravel 5.1+. The only legitimate reasons to install it are: you're on Laravel 4.x (it's already in vendor/), or you're maintaining a Laravel 5.0 app that hasn't migrated yet.

Install (Laravel 5.0 only):

composer require "illuminate/html": "~5.0"

Register it — there is no package auto-discovery in this era, so edit config/app.php:

'providers' => [
    // ...
    'Illuminate\Html\HtmlServiceProvider',
],

'aliases' => [
    // ...
    'Form' => 'Illuminate\Html\FormFacade',
    'Html' => 'Illuminate\Html\HtmlFacade',
],

Verify it's wired before writing any views:

php artisan tinker
>>> Form::text('name')
=> "<input name=\"name\" type=\"text\">"

If that throws Class 'Form' not found, your alias or provider is wrong — fix that before debugging anything else.

Where to look first. The entire API is two readable files:

  • vendor/illuminate/html/FormBuilder.php — form opening, model binding, every input type, macros
  • vendor/illuminate/html/HtmlBuilder.php — links, images, scripts, styles, lists

Skim the public methods; the package has no config file, no service layer, and no hidden behaviour. What you see is what you get.

First real use case. A create/edit form with CSRF and method spoofing handled for you:

{!! Form::open(['route' => 'posts.store']) !!}
    {!! Form::label('title', 'Title') !!}
    {!! Form::text('title', null, ['class' => 'form-control']) !!}
    {!! Form::submit('Save', ['class' => 'btn btn-primary']) !!}
{!! Form::close() !!}

Form::open emits the _token hidden field automatically when a session is available. That is the single biggest reason teams used this package — it's the reason to keep it, and the reason its removal from core was disruptive.

Implementation Patterns

Method spoofing table. HTML forms only do GET/POST, so Form::open maps framework verbs to hidden _method inputs:

You write Emitted
Form::open(['route' => 'x']) method="POST"
['method' => 'PUT'] POST + _method=PUT
['method' => 'DELETE'] POST + _method=DELETE
['method' => 'GET'] GET, no token

Anything else is silently treated as POST — a common source of "why is my PATCH route 405ing".

Model binding is the workhorse pattern. Form::model() binds an Eloquent model so every field pre-fills itself, and also falls back to old() input after a failed validation redirect:

{!! Form::model($post, ['route' => ['posts.update', $post->id], 'method' => 'PUT']) !!}
    {!! Form::text('title') !!}                    {{-- old('title') ?: $post->title --}}
    {!! Form::textarea('body', null, ['rows' => 5]) !!}
    {!! Form::select('status', $statuses, null, ['placeholder' => 'Choose…']) !!}
    {!! Form::checkbox('published', 1, null) !!}
{!! Form::close() !!}

Precedence is: session flash old() → bound model attribute → explicit default argument. Knowing that ladder explains almost every "the form shows the wrong value" bug report.

Wrap repeated controls in macros. Register them once in a service provider's boot() (not a controller, not a view):

Form::macro('bsText', function ($name, $label, $value = null, $attrs = []) {
    $attrs = array_merge(['class' => 'form-control'], $attrs);
    return '<div class="form-group">'
        . Form::label($name, $label)
        . Form::text($name, $value, $attrs)
        . Form::getError($name)   // or your own $errors->first() call
        . '</div>';
});

Macros execute with the builder as $this context, so you can call Form::text() inside them. This is the intended extension point and it scales well for design systems.

Asset helpers in layouts:

{!! Html::style('css/app.css') !!}
{!! Html::style('css/app.css', ['media' => 'print']) !!}
{!! Html::script('js/app.js') !!}
{!! Html::linkRoute('posts.show', $post->title, [$post->id], ['class' => 'link']) !!}

Pair with a Blade layout partial, not raw HTML in controllers. The package returns strings; keep it in views and use {!! !!} (Laravel 5) or {{ }} (Laravel 4, where the builder is marked safe). Mixing these two syntaxes across a 4→5 upgrade is a classic source of double-escaped or raw-output bugs.

Testing. There's no test helper surface; assert on rendered HTML. $this->call('GET', '/posts/create')->assertSee('name="title"') is usually enough, and it survives a later swap to Collective without rewriting assertions.

Gotchas and Tips

The package is dead — budget for the migration. The fork is laravelcollective/html, which is namespace-compatible in spirit but not in code: Illuminate\Html\FormFacade becomes Collective\Html\FormFacade. The swap is mostly a find-and-replace in config/app.php plus composer, and the form API is intact. Do it before you add features, not after. Staying on illuminate/html past Laravel 5.0 means pinned framework versions and no CSRF/middleware compat fixes.

"Class 'Form' not found" is nearly always a missing alias, or a cached config (php artisan config:clear). On Laravel 5.5+ people assume auto-discovery will handle it — it won't, this predates that feature.

CSRF on stateless routes. Form::open injects the token unconditionally when a session store exists. If you're building an API endpoint or a form on a route excluded from VerifyCsrfToken, you'll get a token that's never validated, or — worse — an empty _token if the session isn't started. Pass ['url' => ..., 'method' => 'POST'] and omit the token deliberately by building the tag manually when you genuinely don't want it.

old() beats your model, always. After a failed update, Form::model shows the submitted value, not the DB value, which is correct but surprises people writing feature tests. If you need the model value during a repopulation test, flush the session or withInput().

Checkbox hidden-input ordering. The builder emits <input type="hidden" name="x" value="0"> before the checkbox so unchecked boxes still post a falsy value. If you hand-roll the markup alongside Form::checkbox, you'll get duplicate x keys and PHP will take the last one — usually 1 even when unchecked.

Form::select uses loose comparison for the selected value. 0, '0', null, and false can all collide. If your option keys are numeric-ish IDs mixed with an empty-string placeholder, test the 0/'0' case explicitly; it's the most common silent bug in this package.

Escaping asymmetry. Form::text escapes the value; Html::link escapes the title but not the URL. Don't assume everything is escaped — if you pass user input as the URL argument you must sanitise it yourself.

Macros must be registered before the builder is resolved. The provider binds html and form as singletons. Registering a macro in a controller action that runs after a view already rendered the builder may appear to do nothing. Put Form::macro() calls in a boot() method of a provider that loads early, and remember macros are global for the request — namespace their names (bsText, not text) or you'll shadow core methods confusingly.

Debugging checklist, in order: does Form::text('x') work in tinker → is the field name correct in the rendered source (name="title" not name="Title") → is _token present → is _method present and capitalised → is old() returning what you expect (dd(session()->all())) → does the bound model actually have the attribute ($post->getAttributes()). The package never fails loudly; it renders empty strings and lets the request fail later, so always inspect the HTML.

Don't use it as a general HTML DSL. It's a form builder with a few asset helpers bolted on. Building tables, navs, or page structure with Html::ul()/Html::attributes() is more code than typing the tag, and it makes the later migration to Collective (or to plain Blade components) harder.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
vento/laravel-airbrake
wfeller/laravel-batch
maco-studios/mage-os-installer
busarm/armie
siberfx/laravel-logger
kfteam1991/dcat-admin
dashed/dashed-laposta
dashed/dashed-ecommerce-montaportal
dashed/dashed-ecommerce-etsy
neohq/string-blade-compiler
log1x/acf-composer
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager