lelyfoto/twig-instanceof
Twig extension that adds an instanceof test, letting templates check whether a value is an instance of a given class or interface. Lightweight and easy to register for cleaner, type-aware Twig conditionals.
Architecture fit — conditional, and the condition is usually not met. This is a Twig extension, not a Laravel package. v1.3 does not change that. Laravel's view layer is Blade; Twig only appears in a Laravel codebase through a third-party bridge (rcrowe/twigbridge being the common one) or as legacy code from a Symfony/Craft/Slim/Drupal origin. If the target application is Blade-first, the entire value proposition collapses: Blade compiles to PHP, so @if ($model instanceof \App\Models\User) already works with zero dependencies. Adopt Twig and this package only if Twig is already a fixed constraint. The release notes reinforce which ecosystem this package actually serves — both merged PRs are Symfony-track, not Laravel-track.
Even inside a Twig app, the design is questionable. instanceof in a template moves type dispatch out of PHP and into the view layer. Templates become coupled to fully-qualified class names that no static analysis, IDE, or refactor tool will track; a namespace rename produces a silent false rather than an error. Preferred patterns are a view model/DTO exposing a boolean ($view->isUser), a domain-level discriminator string, or a purpose-named Twig test (is_admin_user). This package exposes the raw mechanism instead of the domain concept. Nothing in v1.3 addresses this.
Integration feasibility — mechanically trivial, strategically thin. The surface area is one extension class plus one expression node. Registration is a single line in config/twigbridge.php's extensions array, or a service provider resolving the Twig environment and calling addExtension(). No service provider, config file, facade, migration, or framework coupling is shipped — good for portability, but it means there is still zero integration guidance and no Laravel-idiomatic entry point to inherit. v1.3 added no docs, no examples, and no Laravel-specific surface.
Technical risk — unchanged in kind, modestly improved in maintenance signal.
Twig\Node\Node / Twig\Node\Expression\AbstractExpression remain the most brittle kind; Twig has repeatedly changed compile() signatures and internals across 3.x minors, and Twig 4 will break node-level extensions outright. The "Add a return type to Fix deprecated message" PR is a genuine positive signal: it indicates the node code is being touched to track upstream deprecations rather than left to rot, and it implies the codebase is on modern PHP (return-type declarations imply PHP 8.x targeting). But a single deprecation fix is not a compatibility matrix, and there is still no evidence of Twig 4 readiness or a CI matrix. The legacy Twig_Extension question from the prior assessment is now more likely to resolve favourably, since Symfony 8 implies Twig\Extension\AbstractExtension — confirm in the spike rather than assume.Twig\Sandbox\SecurityPolicy; if this registers as a raw node rather than a named test, it may bypass the allowed-tests allowlist. String-driven class resolution can also invoke the autoloader and surface class names in exception messages rendered to users. v1.3 does not address this, and the release notes give no indication the maintainer considers it.null handling, interface and parent-class matching, and proxy objects (Doctrine proxies, lazy ghosts) where instanceof against the base class succeeds but against a sibling subclass does not. Still undocumented in the release notes; still to be discovered in the spike.Key questions for the maintainer spike (revised for v1.3)
{% if x is instanceof('App\\Models\\User') %} or operator form? Class-string only, or does it accept a constant()/::class-equivalent?instanceof semantics (interfaces and parents yes, null no error)?SecurityPolicy::setAllowedTests) or as a bare expression node?Stack fit. Direct and correct for standalone Twig, Symfony, Slim, Craft CMS, Drupal, Bolt. v1.3 extends the Symfony reach to Symfony 8, which is the strongest argument yet that this is a Symfony-ecosystem artifact. For Laravel: still only viable via rcrowe/twigbridge or an equivalent bridge, with manual registration. For a Blade-based Laravel app the recommendation remains a firm no — do not introduce Twig to obtain an operator Blade already has natively.
Migration path. Unchanged. Existing Twig-on-Laravel: add the extension class to the extensions array in config/twigbridge.php, run php artisan config:clear, then php artisan view:clear (twigbridge caches compiled templates under storage/framework/views; a stale compiled template will not pick up the new node). Smoke-test one template that renders both branches of the conditional. No schema, data, or route migration; no downtime. If upgrading v1.2 → v1.3 in place, treat it as a no-op deploy but re-run the view-cache clear anyway, since the return-type change touches the compiled path.
Recommended alternative path. Unchanged and still preferred: implement an internal InstanceOfTest extends TwigTest in application code — roughly 25 lines — register it locally, and add one PHPUnit feature test asserting both the true and false branches. This removes the third-party dependency, keeps the sandbox allowlist explicit and auditable, and lets you add domain-named tests alongside it so templates stop referencing FQCNs. Second-best: vendor or fork the package into a private namespace so a Twig upgrade cannot strand you. v1.3 does not move the needle enough to promote "take the dependency" above either option.
Compatibility. Run composer why twig/twig to see the constraint twigbridge already pins; confirm the extension's v1.3 constraints intersect rather than widen it. The Symfony 8 PR may have loosened symfony/* to ^8.0 while leaving Twig unchanged — verify independently, since Symfony version and Twig version are not the same axis. Confirm the class namespace (Twig\Extension\AbstractExtension vs the legacy Twig_Extension); v1.3 makes Twig 3 support near-certain but still not formally stated. Pin Twig and the extension to exact versions in composer.json.
Sequencing
Maintenance. Near-zero runtime maintenance, disproportionate governance overhead for the value delivered. The package has no framework-facing config surface, so Laravel upgrades cannot break it — a genuine plus that v1.3 preserves. The risk remains entirely on the Twig side, and the v1.3 return-type fix is the first hard evidence that someone is watching that side. That lowers the probability of silent decay without eliminating it. The fork burden still lands on you the moment Twig ships a breaking minor. Vendoring converts an unbounded dependency risk into a bounded, readable ~100-line internal asset.
Support. No vendor, no SLA, GitHub issues as the only channel, one maintainer plus two one-time contributors. v1.3 improves the optics of support — two merged external PRs in one release is the healthiest signal this repo has produced — but not the substance: neither contributor has commit rights or a track record, and neither PR was a security or correctness fix. Internal documentation and a named owner remain mandatory even for a trivial adoption. Budget the "one engineer reads the whole file" cost explicitly rather than assuming it is free.
Scaling. Negligible and unchanged. instanceof is an opcode-level O(1) check. Two caveats: class-string resolution at render time can touch the Composer classmap/autoloader on first use per process (warm it, or the cost is trivial anyway); and compiled Twig templates are plain PHP, so OPcache applies normally. There is no per-render allocation or memory concern at any realistic template volume. The real scaling limit is template readability and reviewability, not this operator.
Failure modes
composer update. Lock-file review before adopting v1.3.false. The conditional quietly falls to the else branch. This is the most dangerous mode: no error, data-dependent, near-invisible in code review. v1.3 does not touch it. This alone justifies moving to domain-named booleans or tests.Ramp-up. About an hour for a developer already fluent in Twig's compile/cache model; roughly half a day for a Blade-only team, who must first internalize that Twig compiles and caches to disk. Reviewer ramp-up still exceeds author ramp-up: every FQCN in a template is an untracked coupling that a reviewer must mentally diff against the PHP model layer on every change. Nothing in v1.3 reduces that.
Overall recommendation (revised for v1.3). Conditional no-go for a Blade-based Laravel application — unchanged, and the release notes make the mismatch clearer by confirming the package's centre of gravity is Symfony. Conditional go only where Twig is already fixed: prefer an internal ~25-line Twig test or a vendored fork over the Composer dependency. If the dependency is taken, take v1.3 over v1.2 (the return-type fix and Symfony 8 support are strictly improvements), pin it exactly, review the composer lock diff, and gate it behind a CI compatibility test covering both Twig and Symfony bumps. The release upgrades the package from "sample to vendor" to "sample worth watching"; it does not upgrade it to "dependency to trust."
How can I help you explore Laravel packages today?