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

View Laravel Package

marko/view

marko/view is the view layer for the Marko PHP framework, offering template loading, layout and partial composition, and a clean API for passing data from controllers to rendered HTML output while keeping presentation logic simple and framework-native.

View on GitHub
Deep Wiki
Context7

Getting Started

marko/view is a contracts-only package: it ships interfaces and value objects, not a working template engine. You almost never install it directly — it arrives as a transitive dependency of a concrete renderer (e.g. a Blade/Twig/Plates adapter for Marko) or of marko/framework itself. Your first move is therefore to read the interfaces before reading any implementation: open the package's src/ directory and note the shape of the view factory, the view instance, and any renderer/engine contract. That shape is the contract every Marko view implementation must satisfy, so it is the fastest way to understand how rendering is wired into the container.

Your first real use case is almost always one of two things: (1) type-hinting against the contract in your own services so your code is engine-agnostic, or (2) wrapping a third-party engine you already use (Twig, Blade via jenssegers/blade, etc.) behind the provided interfaces when no Marko adapter exists. Start by binding the concrete implementation in a service provider, then resolve and render one template end-to-end before touching anything else. If the package exposes a ViewFactory-style contract, get that resolving from the container first — everything else builds on it.

Because the repo is a read-only split ([READ-ONLY]), file issues and PRs against marko-php/marko, not here. Watch the main repo's release tags to know when the contract surface changes.

Implementation Patterns

Type-hint the interface, resolve the implementation. The whole point of this package is that your application code should depend on ViewFactoryInterface (or whatever the equivalent is named) and never on a concrete engine. Constructor-inject the factory into controllers, mailers, or other services; let Marko's container resolve the concrete binding you configured.

Adapter/wrapper pattern for third-party engines. When you need to plug in Twig, Blade, Latte, or a hand-rolled engine, implement the package's engine/renderer contract and delegate to the real engine internally. Keep the adapter thin: translate Marko's render call into the engine's render(), map the returned string back, and let exceptions bubble or wrap them in whatever view exception the package defines. This keeps the rest of your app ignorant of the engine choice and lets you swap engines later without touching call sites.

Factory + instance split. Most Marko view contracts mirror a two-tier design: a factory that knows where templates live and how to locate them, and a per-render view instance that holds data and knows how to render itself. Follow that split in your own code — resolve the factory once (often a singleton), create view instances per render, and avoid caching view instances across requests since they carry bound data.

Testing with the contract. Because this package has essentially no runtime logic, mocking it is trivial. In unit tests, bind a fake implementation of the factory interface that returns a stub view whose render() returns a canned string. This is the cleanest way to assert that a controller rendered the right template with the right data without spinning up a real engine.

Composition over inheritance when extending. If you need shared behaviour across several adapters (e.g. escaping, path resolution, caching), wrap decorators around the contract rather than subclassing a concrete engine. The contract-first package is designed for exactly this — decorating is safe, subclassing couples you to an engine.

Gotchas and Tips

  • It does nothing on its own. A common mistake is installing marko/view standalone and expecting view('foo') to work. It will not — you need a concrete engine plus a service-provider binding. Check composer.lock to confirm which adapter you actually pulled in.
  • Version-lock alignment matters. As a contracts package its major version must match the consumer (the framework and any adapter). Mixing a marko/view minor that predates an interface addition with an adapter that implements the newer interface will fail at container resolution — usually with a "cannot instantiate interface" or a fatal "class must implement method" error. Pin the adapter and this package together in composer.json if you support multiple versions.
  • Interface changes are breaking even in minors in practice, because any class implementing the interface breaks. Before upgrading, diff the interface files against the version you currently resolve. Since PRs live in the main marko-php/marko repo, watch that repo's changelog rather than this one.
  • Debugging "no view engine bound" errors: the resolution path goes container → factory contract → concrete binding. If resolution fails, check (a) your provider is registered in config/app.php or equivalent, (b) the binding key matches what the factory interface resolves to, and (c) you haven't accidentally bind()-ed a scoped singleton and lost it between requests.
  • Extension point: exception types. If the package defines view-specific exceptions (e.g. a template-not-found type), catch those rather than a generic \Exception. They carry the template name and are the fastest path to diagnosing a stray path or a typo'd view.
  • Keep your view-data shape explicit. The contract usually accepts an array of data; don't pass objects that rely on __toString unless the engine contract guarantees it. Passing a DTO and converting at the adapter boundary is more portable if you ever change engines.
  • Vendor it, don't fork it. Given the zero-star, low-traffic status of this split, the realistic path for changes is to open an issue in marko-php/marko rather than patch locally — local patches will be silently overwritten on the next composer update.
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.
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
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console