Jump to content

$files->render() don't set $vars?


LAPS
 Share

Recommended Posts

Hi there,

I'm working on an email message template and would like to render a custom one to be sent.

I tried to use $files->render() this way

// rendering file e.g. a template file or a hook statement in ready.php
$body = $files->render('emails/myfile', array(
  'myVar1' => $var1,
  'myVar2' => $var2,
  ...
));

but $vars seems to be not accessible from within the rendered file. That is, $vars seems to be not set:

// rendered file emails/myfile.php
$myVar1 = $vars['myVar1']; // is not set
$myVar2 = $vars['myVar2']; // is not set
... // is not set

How can I get the $vars so to properly render the custom message template for sending the email?

 

Notes:

  • By using $files->include() the $vars is accessible but I cannot use this method because I should retrieve the output $body as a return value for sending the email later. So, I'm still looking to render the custom message using $files->render().
  • This thread is someway related to this one.
Link to comment
Share on other sites

@Robin S OK for $myVar1 and $myVar2 (string variables) ? ... but it seems do not work when I pass a PW Page ?

// rendering file
$myPage = $pages->get(12345);
$body = $files->render('emails/myfile', array(
  'myPageVar' => $myPage
));
// rendered file emails/myfile.php
isset($myPageVar); // returns false

Strange ?

Link to comment
Share on other sites

  • 5 months later...

Had the same issue as @LAPS, ie $vars not accessible in the rendered template. Fixed by including an empty array for $options, ie:

<?php

$vars = [
    'items' => $items,
    'homepage' => pages(1),
    'category' => $category
];
echo $files->render('inc/item-detail',$vars,[]);

 

Link to comment
Share on other sites

  • 2 years later...
On 8/21/2020 at 10:10 AM, psy said:

Had the same issue as @LAPS, ie $vars not accessible in the rendered template. Fixed by including an empty array for $options, ie:

<?php

$vars = [
    'items' => $items,
    'homepage' => pages(1),
    'category' => $category
];
echo $files->render('inc/item-detail',$vars,[]);

 

I just tried this and $vars is still null inside the render file, even when sending $options. Also $options is null.

I am using this to render files (views) inside a module. So the render files sit inside /site/modules/myModule/views. I am rendering those with $this->files->render('/full/path/to/viewFile', [...], []);

Can't find anything in the docs on how to retrieve $vars here. I need to pass them on to another render file.

With ReflectionMethod, we can get all the parameter names passed to $files->render(). But not the values passed to that instance of the method.

$f = new ReflectionMethod(wire('files'), 'render');
bd($f->getParameters());

If anybody knows how to get $vars inside the render files, would be much appreciated 🙂 

Link to comment
Share on other sites

16 minutes ago, gebeer said:

$vars is still null inside the render file

It’s not going to be in $vars. Instead, every key of the dictionary becomes a global variable, so psy’s example would introduce the variables $items, $homepage and $category to your template file.

Link to comment
Share on other sites

1 hour ago, Jan Romero said:

It’s not going to be in $vars. Instead, every key of the dictionary becomes a global variable, so psy’s example would introduce the variables $items, $homepage and $category to your template file.

Thanks. I'm aware of that. But I'm looking for a way to get the $vars variable like it was sent to the render method so I can pass it on easily. Imagine you pass a $vars array with 10 items to render(). Then from the render file that you passed them to you want to take $vars and pass it on to another partial with the render() method. ATM you have to write each one out again in the new render() call. That is tedious and it would be much easier if we could just grab $vars and pass it on.

Link to comment
Share on other sites

I see. I suppose the easiest way would be to just nest a single array in $vars and only ever use that.

A more generic solution could involve hooking before TemplateFile::render: https://github.com/processwire/processwire/blob/6ff498f503db118d5b6c190b35bd937b38b80a77/wire/core/TemplateFile.php#L305

You could add something like

$this->addHookBefore('TemplateFile::render', function(HookEvent $e) {
    $tpl = $e->object;
    $tpl->data('passedVars', array_diff_key($tpl->getArray(), wire()->fuel->getArray()));
});

That should make the passed variables available as usual and additionally inside an array called $passedVars. I don’t think you’re going to get around the whole array_diff_key business at that point, unfortunately? The way passing vars to a file works in the core seems to immediately conflate those vars with the general globals. It happens even before render() is called, for instance here: https://github.com/processwire/processwire/blob/6ff498f503db118d5b6c190b35bd937b38b80a77/wire/core/WireFileTools.php#L1478.

Link to comment
Share on other sites

9 hours ago, gebeer said:

Can't find anything in the docs on how to retrieve $vars here. I need to pass them on to another render file.

If I understand correctly you should be able to just put this on top of the rendered view:

$vars = get_defined_vars();

...and then you can pass those $vars to the next ->render() call.

We don't have a PW/API way all the time. Sometimes there's still a PHP way of doing it 😄 

Link to comment
Share on other sites

On 4/28/2023 at 3:18 AM, bernhard said:

If I understand correctly you should be able to just put this on top of the rendered view:

$vars = get_defined_vars();

...and then you can pass those $vars to the next ->render() call.

We don't have a PW/API way all the time. Sometimes there's still a PHP way of doing it 😄 

Thanks for the suggestion. This is throwing all kinds of errors. If I want to bd($vars), I get:


User Error
Exception: Method RockMigrations::getModuleInfo does not exist or is not callable in this context (in /var/www/html/wire/core/Wire.php line 563)

#0 /var/www/html/wire/core/Wire.php(419): ProcessWire\Wire->___callUnknown('getModuleInfo', Array)
#1 /var/www/html/wire/core/WireHooks.php(952): ProcessWire\Wire->_callMethod('___callUnknown', Array)
#2 /var/www/html/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks(Object(ProcessWire\RockMigrations), 'callUnknown', Array)
#3 /var/www/html/wire/core/Wire.php(487): ProcessWire\Wire->__call('callUnknown', Array)
#4 /var/www/html/site/modules/RockMigrations/RockMigrations.module.php(4560): ProcessWire\Wire->__call('getModuleInfo', Array)
#5 /var/www/html/site/modules/TracyDebugger/tracy-2.9.x/src/Tracy/Dumper/Describer.php(295): ProcessWire\RockMigrations->__debugInfo()

With print_r($vars) I get:


Fatal Error
__debuginfo() must return an array

Related to RockMigrations::__debugInfo(). Seems like this method is interfering with print_r().

After uninstalling Tracy I finally got to outputting var_dump($vars). Still throwing a Warning about RockMigrations::__debugInfo().
$vars contains all defined vars including fuel which contains wire and so on. So this is not feasable for the simple purpose of passing on some vars.

What I finally did, is putting all vars that I need to pass on into an array $arr, then passing $arr to the render file. In the render file I can retrieve it with $arr and pass it on. Sometimes solutions are so simple. But the other day it was getting late already. Braindead just around the corner 🙂


 

Link to comment
Share on other sites

6 hours ago, gebeer said:

Still throwing a Warning about RockMigrations::__debugInfo()

The error that you are seeing comes from RockMigrations and not from get_defined_vars() - sorry for that. It has been fixed in the dev branch here already: https://github.com/baumrock/RockMigrations/commit/3ab756003e697f5fb2af0e2357094613464bd901#diff-f2f9bf51d98ac65f5b9abedff5f904a71b54b3ba563b1756756a37c5e9852635L4326

The problem was that ->getInfo()['version'] did not work anymore since I split the module info into it's own file to support PHP8 requirement.

I'll merge everything into main soon 🙂 

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

You could actually pass an array which contains all other content like

<?php

$vars = [
  'items' => $items,
  'homepage' => pages(1),
  'category' => $category
];

echo $files->render('path/to/file.inc', [
  'vars' => $vars,
]);

and then use that to pass on. To still have the convenience of global variables, you can use

<?php

extract($vars);

in the template file to be rendered. My code is untested though!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...