pug-php / pug

Pug template engine for PHP
https://www.phug-lang.com
MIT License
387 stars 42 forks source link

Undefined variable fatal error appears on quoted Vue.js variable #224

Closed radiocity closed 5 years ago

radiocity commented 5 years ago

Hello,

I encountered an issue with the following code:

+button()(@click.prevent = "$modal.show('contact_us')") Contact us

I expected to get:

<button class="button" @click.prevent="$modal.show('contact_us')">Contact us</button>

But I actually get:

Undefined variable: modal on line X, offset Y
More info ``` ## /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(8034) #0 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(8034): Phug\Util\SandBox->Phug\Util\{closure}(8, 'Undefined varia...', '/home/username...', 8034, Array) #1 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(780): Phug\Renderer\Adapter\EvalAdapter->{closure}(Array) #2 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(8067): Phug\Renderer\Adapter\EvalAdapter->{closure}(true, Array, Array, Array, Object(Closure)) #3 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(831): Phug\Renderer\Adapter\EvalAdapter->{closure}(Array) #4 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(8068): Phug\Renderer\Adapter\EvalAdapter->{closure}(true, Array, Array, Array, Object(Closure)) #5 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(723): Phug\Renderer\Adapter\EvalAdapter->{closure}(Array) #6 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12) : eval()'d code(8069): Phug\Renderer\Adapter\EvalAdapter->{closure}(true, Array, Array, Array, Object(Closure)) #7 /vendor/phug/renderer/src/Phug/Renderer/Adapter/EvalAdapter.php(12): eval() #8 /vendor/phug/renderer/src/Phug/Renderer/AbstractAdapter.php(41): Phug\Renderer\Adapter\EvalAdapter->display('Phug\Renderer\{closure}() #10 /vendor/phug/renderer/src/Phug/Renderer/Partial/AdapterTrait.php(100): Phug\Util\SandBox->__construct(Object(Closure), NULL) #11 /vendor/phug/renderer/src/Phug/Renderer/AbstractAdapter.php(29): Phug\Renderer->getNewSandBox(Object(Closure)) #12 /vendor/phug/renderer/src/Phug/Renderer/AbstractAdapter.php(42): Phug\Renderer\AbstractAdapter->captureBuffer(Object(Closure)) #13 /vendor/phug/renderer/src/Phug/Renderer/Partial/AdapterTrait.php(141): Phug\Renderer\AbstractAdapter->render('Phug\Renderer\Partial\{closure}() #15 /vendor/phug/renderer/src/Phug/Renderer/Partial/AdapterTrait.php(100): Phug\Util\SandBox->__construct(Object(Closure), NULL) #16 /vendor/phug/renderer/src/Phug/Renderer/Partial/AdapterTrait.php(142): Phug\Renderer->getNewSandBox(Object(Closure)) #17 /vendor/phug/renderer/src/Phug/Renderer/Partial/AdapterTrait.php(208): Phug\Renderer->getSandboxCall('callAdapter('render', 'organizatio...', NULL, Object(Closure), Array) #19 /vendor/pug-php/pug/src/Pug/Engine/Renderer.php(35): Phug\Renderer->renderFile('organizatio...', Array) #20 /vendor/pug-php/pug/src/Pug/Engine/Renderer.php(99): Pug\Engine\Renderer->renderFileWithPhp('organizatio...', Array) #21 [internal function]: Pug\Engine\Renderer->Pug\Engine\{closure}() #22 /vendor/pug-php/pug/src/Pug/Engine/Renderer.php(106): call_user_func(Object(Closure)) #23 /cms/application/classes/Controller/Admin/Menu.php(224): Pug\Engine\Renderer->renderFile('organizatio...', Array) #24 /cms/application/classes/Controller/Admin/Menu.php(230): Controller_Admin_Menu->renderPugTemplate('organizatio...') #25 /cms/application/classes/Controller/Admin/Menu.php(326): Controller_Admin_Menu->clearPugContent('organizatio...') #26 /cms/system/classes/Framework/Controller.php(84): Controller_Admin_Menu->action_update() #27 [internal function]: Framework_Controller->execute() #28 /cms/system/classes/Framework/Request/Client/Internal.php(97): ReflectionMethod->invoke(Object(Controller_Admin_Menu)) #29 /cms/system/classes/Framework/Request/Client.php(114): Framework_Request_Client_Internal->execute_request(Object(Request), Object(Response)) #30 /cms/system/classes/Framework/Request.php(986): Framework_Request_Client->execute(Object(Request)) #31 /cms/init.php(38): Framework_Request->execute() #32 /public_html/index.php(2): include_once('/home/username...') #33 {main} ```

Workaround

| <button class="button" @click.prevent="$modal.show('contact_us')">Contact us</button>

or

+button()(@click.prevent = "\$modal.show('contact_us')") Contact us

Thanks!

kylekatarnls commented 5 years ago

I ran your code in [https://pug-demo.herokuapp.com/](https://pug-demo.herokuapp.com/?embed&engine=pug-php&input=mixin%20button%0A%20%20button.button%26attributes(attributes)%0A%20%20%20%20block%0A%2Bbutton()(%40click.prevent%20%3D%20%22%24modal.show(%27contact_us%27)%22)%20Contact%20us%0A&vars=) and get no errors:

mixin button
  a&attributes(attributes)
    block
+button()(@click.prevent = "$modal.show('contact_us')") Contact us

Outputs as expected:

<button @click.prevent="$modal.show('contact_us')" class="button">Contact us</button>

Please provide your mixin content, I think there is an error in it.

radiocity commented 5 years ago
mixin icon(name)
  if name
    icon(name = name)&attributes(attributes)

mixin button(href, caption)
  - var disabled = attributes.disabled ? true : null;
  - attributes.tabindex = disabled ? -1 : null
  - var cls = 'button'
  - var icon = attributes.icon ? attributes.icon : null;
  - attributes.icon = null;
  if href
    a(href=href class = cls disabled = disabled tabindex = tabindex)&attributes(attributes)
      +icon(icon).text-icon.text-icon-left
      if block
        block
  else
    button(class = cls disabled = disabled tabindex = tabindex)&attributes(attributes)
      +icon(icon).text-icon.text-icon-left
      if block
        block
kylekatarnls commented 5 years ago

Still no error when I test it: https://pug-demo.herokuapp.com/?embed&input=mixin%20icon(name)%0A%20%20if%20name%0A%20%20%20%20icon(name%20%3D%20name)%26attributes(attributes)%0A%0Amixin%20button(href%2C%20caption)%0A%20%20-%20var%20disabled%20%3D%20attributes.disabled%20%3F%20true%20%3A%20null%3B%0A%20%20-%20attributes.tabindex%20%3D%20disabled%20%3F%20-1%20%3A%20null%0A%20%20-%20var%20cls%20%3D%20%27button%27%0A%20%20-%20var%20icon%20%3D%20attributes.icon%20%3F%20attributes.icon%20%3A%20null%3B%0A%20%20-%20attributes.icon%20%3D%20null%3B%0A%20%20if%20href%0A%20%20%20%20a(href%3Dhref%20class%20%3D%20cls%20disabled%20%3D%20disabled%20tabindex%20%3D%20tabindex)%26attributes(attributes)%0A%20%20%20%20%20%20%2Bicon(icon).text-icon.text-icon-left%0A%20%20%20%20%20%20if%20block%0A%20%20%20%20%20%20%20%20block%0A%20%20else%0A%20%20%20%20button(class%20%3D%20cls%20disabled%20%3D%20disabled%20tabindex%20%3D%20tabindex)%26attributes(attributes)%0A%20%20%20%20%20%20%2Bicon(icon).text-icon.text-icon-left%0A%20%20%20%20%20%20if%20block%0A%20%20%20%20%20%20%20%20block%0A%0A%2Bbutton()(%40click.prevent%20%3D%20%22%24modal.show(%27contact_us%27)%22)%20Contact%20us%0A&vars=

Could you please show me how you render it? (The PHP code calling Pug and the options) and run composer update to be sure your on latest versions of pug dependencies.

radiocity commented 5 years ago
// ...
public function initPugEngine()
{
    $pug = new Pug([
        'cache' => false,
        'extension' => '.pug',
        'basedir' => DIR_PUG.'pages/',
        'expressionLanguage' => 'js'
    ]);
    $pug->share('Math', [
        'floor' => 'floor',
        'round' => 'floor',
        'random' => function () {
            return mt_rand() / mt_getrandmax();
        },
    ]);
    return $pug;
}

// ...
public function renderPug(Page $page)
{
    $this->pug = $this->initPugEngine();
    $content = $this->pug->renderFile($page->template, $this->data);
    return $content;
}
kylekatarnls commented 5 years ago

Hi, I try with this right now.

For the record: 'round' => 'floor', it should be 'round' if you want it to be equivalent to JS Math, then it's already in jsphpize, so you don't need to create anything to get basic Math functions working as in JS.

kylekatarnls commented 5 years ago

pug-test-mixin.zip

I used your PHP and Pug codes and as you can see in the attached zip by running index.php, $modal is correctly displayed.

I think some code re-execute the rendered template. Please provide a ZIP with a minimal example to reproduce the bug.

kylekatarnls commented 5 years ago

I'm closing this as not reproduced, but I will re-open if you provide a project example where it can be reproduced.

radiocity commented 5 years ago

@kylekatarnls, is it possible to share Math in \Pug\Optimizer::call('displayFile',...) ?

kylekatarnls commented 5 years ago

Yes, you can share anything as usual. By Math is not needed, it's already provided by js-phpize: https://github.com/pug-php/js-phpize/blob/master/src/JsPhpize/Compiler/Helpers/MathClass.h

radiocity commented 5 years ago

Do I need to turn js-phpize somehow? It doesnt work with Undefined variable: Math. If I do not use sharing image

kylekatarnls commented 5 years ago
mixin nav()
  - var random = Math.round(Math.random() * (35535 - 10) + 10)
  p=random

+nav()

This works on https://pug-demo.herokuapp.com/

I just tried with default settings of Pug\Optimizer:

<?php

include_once __DIR__ . '/vendor/autoload.php';

$environment = 'production';

$variables = [];

$options = [
    'debug'     => false,
    'cache_dir' => 'cache',
    'paths'     => [
        '.',
    ],
];

if ($environment === 'production') {
    \Pug\Optimizer::call('displayFile', ['view', $variables], $options);

    exit;
}

$options['debug'] = true;
$options['cache_dir'] = null;

Pug::displayFile('view', $variables, $options);

And I get <p>123456</p> too (with both $environment = 'dev'; and $environment = 'production';).

radiocity commented 5 years ago

I looked into lock file and found out composer installes old version of js-phpize/js-phpize And the reason is :

Package js-phpize/js-phpize at version ^2.0 has a PHP requirement incompatible 
with your PHP version (5.6.40)
kylekatarnls commented 5 years ago

PHP 5.6.40 is really old: https://www.php.net/supported-versions.php Even 7.1 is no longer actively supported.

With PHP 5.6.40, there are hundred of libraries you can't use at their last version. Any package from Symfony, Laravel, PHPUnit, The PHP league, Spatie, and so on.

You should really upgrade PHP rather than recode libraries parts.