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

Migration Bundle Laravel Package

okvpn/migration-bundle

A Symfony bundle for managing database migrations through configurable paths and console commands. It helps teams version schema changes, apply them consistently across environments, and keep migration workflows organized in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bridge and Twig together, then publish the config:

composer require rcrowe/twigbridge:^2.1
php artisan vendor:publish --provider="TwigBridge\ServiceProvider"

Twig 3.x is supported as of v2.1.2 (this patch relaxes the version constraint and fixes the class/interface references). If you are on Twig 3, confirm Composer actually resolved it — composer show twig/twig — because a stale composer.lock from a Twig 2 install will silently keep you on 2.x where the fix is irrelevant.

Order of operations for a first use case:

  1. Open config/twigbridge.php first — it is the whole mental model of the package. The enabled, twig.options, twig.extensions, and extensions keys are what you will actually touch.
  2. Enable the extension ('enabled' => true), then create resources/views/hello.twig and hit it with return view('hello', ['name' => 'Ada']);. The package registers the .twig extension with the view finder, so no route or controller changes are needed.
  3. Verify the environment resolves: php artisan tinker → Twig::getEnvironment()->getVersion(). If this throws, your autoload or config cache is stale, not your template.

The first real use case is almost always a legacy Twig codebase (Symfony or standalone) being ported into Laravel, or a Laravel app adding Twig for a team that already knows it. Both mean Blade and Twig will coexist in the same app — that is supported, but see the gotchas.

Implementation Patterns

Mixed Blade/Twig rendering. Both extensions register independently. A pragmatic split that works well: Blade for layouts and anything using Laravel's directive ecosystem (@csrf, @auth, @vite), Twig for content-heavy partials where designers own the markup. Share data across both with view()->share(); it flows into Twig automatically because the package proxies through the same view factory.

Bridging Laravel helpers into Twig. Do not scatter TwigFunction definitions in random providers. Add one extension class and register it in config/twigbridge.php under extensions:

'extensions' => [
    App\Twig\LaravelHelpers::class,
],

In it, wrap csrf_field(), route(), asset(), config(), and auth()->user() — these are the four or five functions that make Twig feel native and stop designers from asking you for a view()->share() every sprint.

Per-environment options. Twig's own options live under twig.options. Set debug => env('APP_DEBUG'), strict_variables => env('APP_DEBUG') (strict in dev to catch typos, loose in prod to avoid blank pages), and cache => storage_path('framework/views/twig') only in production. auto_reload should be off outside local — with it on, you are recompiling on every request.

Custom loaders and namespaces. Register Twig namespaces via twig.paths, which is the clean way to let a design system live outside resources/views (e.g. vendor/design-system/views addressed as @design/button.twig). This mirrors Blade's View::addNamespace but goes through the package config rather than a provider.

Testing. Assert against the rendered string rather than the view name, because Twig exceptions surface as Twig\Error\RuntimeError and are easy to mistake for a 500. $this->get('/page')->assertSee('expected output') catches both compile and runtime failures in one shot; a assertViewHas style assertion will not tell you the template compiled.

Gotchas and Tips

  • Twig 3 renamed everything namespace-wise. The v2.1.2 fix matters because Twig 3 dropped the Twig_ class prefix. If you have custom extensions written against Twig_Extension, Twig_SimpleFunction, or Twig_SimpleFilter, they now throw "class not found" while the package itself works fine. Migrate to Twig\Extension\AbstractExtension, Twig\TwigFunction, and Twig\TwigFilter — the call signatures are unchanged, so it is a rename, not a rewrite.
  • Twig 3 removed the {% spaceless %} tag. This is the most common silent breakage on upgrade; templates that used it will now fail to compile. Replace with {% apply spaceless %} or just drop it — modern browsers rarely need it.
  • The filter tag's signature changed in Twig 3 (arrow-functions via => are now the documented form). Old {% filter upper %} still works; custom filter-callback forms may not.
  • Blade directives do not work in .twig files. @csrf, @vite, @livewire are Blade compiler artefacts. You must provide Twig functions for each. This is the single biggest source of "why is my form broken" reports on a mixed project.
  • Cached config will lie to you. config:cache freezes twigbridge.php; registering a new extension in a provider and seeing no effect is almost always this. Run php artisan config:clear before debugging extension registration.
  • Twig's cache is separate from Laravel's. php artisan view:clear does not touch Twig's compiled cache if you pointed twig.options.cache at a custom directory. Wire that directory into your deploy script or just use the default and let view:clear handle it.
  • strict_variables changes exception types. With it off, a missing variable renders as empty string and you get a confusing downstream bug; with it on, you get a clear error. Keep it on in local and CI, off in production unless your templates are already strict-clean.
  • Extension points: the TwigBridge\Extension base class supports runtime-lazy loading, which is worth using for extensions that touch the DB or container — eagerly booting them on every request (including queue workers that never render a view) is a real cost. Also note Twig::getEnvironment() is a singleton; mutating it at runtime in a middleware affects every subsequent render in that request.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons