oosaulenko/looly-gutenberg
Laravel package for handling Gutenberg editor blocks: parse, render, and manage WordPress block content inside PHP applications, with helpers for block markup and serialized block data. Small, low-adoption project with limited maintenance activity.
config/app.php..twig extension settings.return view('dashboard', [
'user' => $user, // Eloquent model, DTO, or value object
]);
dashboard.twig, access the object directly:<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
As of 1.0.9, you can pass objects into Twig templates instead of pre-converting them to arrays. That is the first thing to verify after upgrading: pass an Eloquent model or a simple DTO and confirm property/getter access works as expected.
Where to look first:
Pass domain objects directly from controllers. Instead of mapping models to arrays, pass the model or DTO:
return view('posts.show', ['post' => $post]);
<h1>{{ post.title }}</h1>
<time>{{ post.published_at|date('Y-m-d') }}</time>
Use Twig’s normal attribute resolution for models and DTOs. Twig will resolve {{ user.name }} through array access, public properties, name(), getName(), isName(), or hasName(). Prefer public getters or accessors so templates stay readable and testable.
Loop over collections of objects. This is a common day-to-day use case now that objects are supported:
{% for post in posts %}
<a href="{{ route('posts.show', post.id) }}">{{ post.title }}</a>
{% endfor %}
Share common objects with view composers or View::share. For example, share the authenticated user or navigation data once, then access it as an object in Twig:
View::share('currentUser', auth()->user());
{% if currentUser %}
<span>{{ currentUser.display_name }}</span>
{% endif %}
Use attribute() for dynamic property names. If a template needs to read a field chosen at runtime:
{{ attribute(user, fieldName) }}
Keep Laravel integration in PHP, not Twig. Policies, validation, route generation, and eager loading belong in controllers, form requests, middleware, or view composers. Twig should mostly render data that is already prepared.
Use includes and components with objects. Pass the same object into partials:
{% include 'partials/user-card.twig' with { user: user } only %}
Test views with real objects. Feature tests that assert rendered Twig output are more valuable after this change because object access now follows Twig’s attribute resolution rules. Include at least one test that passes a model or DTO with getters.
Twig only calls public members. Private/protected properties and methods are not accessible. Use public getters/accessors or expose explicit methods such as displayName(). If you rely on __get, verify that Twig’s __isset/attribute checks behave as expected.
Object support does not mean unrestricted object access. Twig resolves attributes in a defined order: array key, property, method, getX, isX, hasX. A method that exists but is expensive or has side effects can be called from a template. Avoid exposing setters or dangerous methods; prefer read-only DTOs or carefully designed models.
Watch for lazy loading and N+1 queries. {{ post.author.name }} can trigger a database query if author was not eager loaded. Eager load relationships in the controller exactly as you would for Blade:
$posts = Post::with('author')->get();
Strict variables change failure behavior. If strict_variables is enabled, accessing a missing object property throws an error. If it is disabled, Twig may return null silently. Confirm the setting in the package config and test templates with missing optional fields.
Array syntax and object syntax are not interchangeable. Existing templates may use {{ user['name'] }}, which works for arrays but not necessarily for objects. After 1.0.9, standardize on {{ user.name }} for objects. Audit templates if you previously passed arrays and now pass models.
Date and Carbon objects need formatting. Twig will not automatically format Carbon instances the way Blade might. Use a filter:
{{ user.created_at|date('Y-m-d H:i') }}
Be mindful of timezone configuration and nullable dates.
Debugging object access. Enable Twig’s debug extension in local environments and use {{ dump(user) }} to inspect what the template actually receives. If dump is unavailable, check the package’s debug/config options rather than adding dd() inside Twig.
Be careful with cached responses and serialized view data. Objects passed into templates must be serializable if you cache rendered responses or view data. Closures, resources, and some service objects are not safe to cache.
Upgrade path from pre-1.0.9 code. If you previously used a view composer, middleware, or presenter to convert models into arrays, you can often remove that layer now. Do it incrementally: pass the object alongside the existing array first, compare output, then simplify.
Extension points remain the same. Custom Twig extensions, functions, filters, and global variables are still registered through the package’s config or service provider. Object support only affects attribute resolution; it does not change how extensions are added.
Security and escaping. Twig autoescaping still applies, but exposing objects means more methods may be callable from templates. Review templates that render user-controlled data, and avoid calling methods with side effects from Twig.
How can I help you explore Laravel packages today?