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

Php Html Laravel Package

arcanedev/php-html

A lightweight PHP package for building HTML elements programmatically with a clean, fluent API. Create tags, attributes, and nested content without messy string concatenation, keeping markup generation readable, reusable, and easy to test in any PHP or Laravel project.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with composer require arcanedev/php-html, then confirm what you actually got before designing around it:

composer show arcanedev/php-html

Check the installed version, PHP constraint, and whether it pulls in illuminate/support. If a service provider/facade is auto-discovered in your Laravel version, you can use the facade; otherwise the static builder (Arcanedev\Html\Html) and element classes work standalone. The first place to look is the package src/ directory—particularly the element factory and the base Element class—because the README is thin and the available tag methods are easiest to enumerate from the code.

Your first use case should be a dynamic fragment that is awkward in Blade: a list built from a collection, a status badge, or an email digest. Smoke-test it in php artisan tinker or a throwaway route:

use Arcanedev\Html\Html;

return Html::div('Hello')->class('p-4');

Verify two things immediately: that text is escaped by default, and how the output renders when returned from a controller versus echoed in a Blade view. Once that behaves predictably, move on to composing fragments from arrays/collections, which is where this package earns its place.

Implementation Patterns

Wrap it in your own presenter/component layer. The package is a thin fluent builder, not an application architecture. Create small classes or methods such as Alert::success(string $message): string or MenuItem::render(array $item): Element that return rendered HTML. This gives you one place to swap the implementation later and keeps tag-building calls out of controllers.

Compose fragments from collections. The natural fit is data-driven markup:

$list = Html::ul()->children(
    collect($items)->map(fn ($item) => Html::li($item->label)->class('list-item'))
);

This is the pattern to use for menus, breadcrumbs, notification digests, invoice line items, and PDF templates generated with Dompdf—contexts where you are producing markup from PHP data rather than from a Blade template.

Use it for mailables and notifications. Build the body fragment in a mailable or a queued job and pass the rendered string into the view data. It is especially useful when the same fragment must be produced in a console command, a scheduled report, or a test without booting a view.

Blade interop. If the element implements Htmlable/Stringable, returning it directly from a view-model method avoids double escaping. If you echo it manually, use {!! $html !!}. For fragments, prefer passing a rendered string into the template and echoing it once, rather than sprinkling builder calls through Blade.

Conditional attributes. Build attribute arrays and pass them in one call where possible, and use explicit ternaries for classes rather than relying on null handling:

Html::a($url, $label)->attributes([
    'class' => $active ? 'nav-link active' : 'nav-link',
    'aria-current' => $active ? 'page' : null,
]);

Testing. Assert against rendered strings with assertSee(..., escape: false) or direct string comparison. Snapshot-style assertions are useful here because whitespace and self-closing tag style can shift between versions.

Integration tip: pick one concern for this package—typically dynamic fragments and emails—and leave page layout to Blade components. Mixing both for the same UI element creates two sources of truth.

Gotchas and Tips

  • Escaping boundaries. Text content and attributes are normally escaped, but raw-content methods (raw, html, or equivalent in your version) bypass it. Never feed request data or stored user content into those methods. Audit every call site that emits unescaped markup.
  • Blade double-escaping. A builder object echoed with {{ }} can be escaped into visible tags unless it implements Htmlable. When output looks like <div>, that is the cause—render to string and use {!! !!}, or return an HtmlString.
  • Void elements. img, br, input, hr, and meta should not receive content. Also check whether output is <br> or <br />; this breaks brittle snapshot tests and can matter for XML/XHTML pipelines.
  • Attribute quirks. Boolean attributes, null/false values, array-valued classes, and numeric attribute names are common sources of surprises. Verify each in tinker before relying on them, and prefer constructing the final attribute array yourself.
  • Dynamic tag names are unvalidated. If you build tags from variable input (Html::tag($name)), validate against an allowlist. Tag and attribute injection is still injection.
  • Low-maintenance dependency. With 16 stars and a single-maintainer release cadence, pin the version in composer.json and keep all usage behind your own wrapper. Compare against spatie/laravel-html or native Blade components before committing broadly; migration is trivial if the calls are centralized.
  • Compatibility checks. Confirm the package's PHP constraint against your runtime (especially on PHP 8.3/8.4) and run your test suite after upgrades. A 2024 release can lag behind current Laravel majors.
  • Debugging. Cast to string ((string) $element) or call the render method explicitly; dd() on the object shows the fluent state, not the final markup. Decode entities when comparing test output.
  • Config and extension. Do not expect a publishable config file or Blade directives. Extension is typically via subclassing the base element class or registering custom element types in a service provider; check whether a macro API exists in your installed version before designing around it.
  • Performance. Building large documents in tight loops is fine for emails and reports, but cache rendered fragments if they are regenerated on every request in a hot path.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource