Skip to content

fix: Template::render() accepts object for template parameters - #366

Open
jakduch wants to merge 21 commits into
nette:masterfrom
jakduch:fix/template-render-accept-object
Open

jakduch wants to merge 21 commits into
nette:masterfrom
jakduch:fix/template-render-accept-object

Conversation

@jakduch

@jakduch jakduch commented Mar 5, 2026

Copy link
Copy Markdown

Resolves #351

Summary

Latte\Engine::render() supports passing an object as template parameters (as documented in Latte type system docs), but Nette\Bridges\ApplicationLatte\Template::render() only accepted array, throwing a TypeError when an object was passed.

Changes

  • render() and renderToString() now accept object|array for $params
  • Added private paramsToArray() helper to convert objects via get_object_vars()
  • Fully backward compatible — existing array usage works unchanged

Usage

class CatalogTemplateParameters
{
    public function __construct(
        public string $lang,
        /** @var ProductEntity[] */
        public array $products,
        public Address $address,
    ) {}
}

// Now works in Controls:
$this->template->render(__DIR__ . '/template.latte', new CatalogTemplateParameters(
    lang: $settings->getLanguage(),
    products: $entityManager->getRepository('Product')->findAll(),
    address: $userAddress,
));

@jakduch
jakduch force-pushed the fix/template-render-accept-object branch from c3e51d8 to 6029c4e Compare March 5, 2026 15:26
@dg
dg force-pushed the master branch 2 times, most recently from b55f309 to bceeafa Compare June 1, 2026 21:02
@dg
dg force-pushed the master branch 3 times, most recently from 340942f to b670493 Compare June 29, 2026 19:09
dg added 19 commits July 14, 2026 05:21
Brings the {form}/{input}/{label} deprecation to {control} via the
shared TagParser::consumeCommaBeforeArguments() helper. Triggers
E_USER_DEPRECATED when a token follows the name (and optional :method)
without a separating comma, pointing to the offending column; the tag
still compiles. A trailing |modifier is not mistaken for arguments.
Two forward-compatible additions to the classic presenter form:

- The form owns its cross-origin state (private ?FetchSite
  $allowedOrigin + allowCrossOrigin()) instead of relying on the
  protected $crossOrigin inherited from Nette\Forms\Form. Forms 3.x
  declares that property untyped while 4.0 removes it, so no
  redeclaration can satisfy both; a differently named private property
  works with either version.
- createDefaultSource() returns null, which under forms 4.0 prevents
  the lazy default HttpSource from materializing (the form is anchored
  via the presenter). Under 3.x the method is unused; its return type
  references an interface that only exists in 4.0, which is safe
  because without a parent method there is no variance check.

The classic receiveHttpData()/isAnchored()/beforeRender() overrides
double as the documented BC seam of forms 4.0, so a single class works
with both major versions.
The form no longer overrides receiveHttpData(), isAnchored() and
beforeRender(); instead it overrides createDefaultSource() to return
null and sets the @internal FormSubmissionSource when anchored to
a presenter. The source detects submission via the 'submit' signal,
reads the application request and installs the hidden signal field in
its prepare() render hook; it resolves the presenter from the form
lazily, so a form re-anchored to another presenter keeps working. The
catch-up pass of setSubmissionSource() replaces the manual
loadHttpData() loop in validateParent().

The form owns its cross-origin state (private ?FetchSite $allowedOrigin
+ allowCrossOrigin()) independently of nette/forms; the same-origin
check intentionally stays in signalReceived(), where a failure is
reported via Presenter::detectedCsrf().

Requires nette/forms 4.0.
Persistent, action, render and signal parameters can be typed as a backed
enum. The URL carries the case value: link() unwraps BackedEnum instances
before the URL is built (http_build_query would otherwise decompose the
object into an array), and incoming scalars are losslessly converted back
via tryFrom(); an invalid value yields 4xx, not 500.
…e() for persistent parameters. [Closes nette/nette#703][Closes nette/nette#703][Closes nette#69]" (possible BC break)

This reverts commit cda17f4.

See https://forum.nette.org/cs/35528-stejne-pojmenovany-parametr-akce-presenteru-a-persistentni-odlisne-chovani-v-nette-2-0-oproti-aktualnimu#p221742

BC break: Property must be nullable, ie: #[Persistent] public ?int $foo
…#351)

Latte\Engine::render() supports passing an object as template parameters,
but Nette\Bridges\ApplicationLatte\Template::render() only accepted arrays.
This adds object|array union type to render() and renderToString().
@jakduch
jakduch force-pushed the fix/template-render-accept-object branch from 6029c4e to e1f6e1b Compare August 12, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nette\Bridges\ApplicationLatte\Template::render() does not accept object for template parameters

2 participants