2
votes

Hello I am fairly new to developing with PHP and Twig and have encountered a problem when updating global variables in twig. I though it would be nice to have a flash / error message global variable that I could display to a user if they have entered incorrect input (ex. a login screen).

At the moment I am using the session in php for this flash message. When the flash message is updated it should also be updated in Twig. But it does not update until I reload the page. At this point the flash message may be changed. I thought the problem may have been in PHP so I echoed the flash variable in my code before the Twig template was rendered and the flash variable was updated in that respective echo statement. I want to stress that Twig does update the flash message, but it does not until the page is loaded again. So it never has the current flash message.

I have written a short program to demonstrate this. If the user presses button "one" then the flash message should be "message one" and if they press button "two" the flash message should be "message two". I have included both an echo of the flash message in php and the flash message in the Twig template.

index.php

<?php
session_start();

require_once '../PhotoBlog/utilities/twig/vendor/autoload.php';

$loader = new Twig_Loader_Filesystem('view');
$twig = new Twig_Environment($loader, array('cache' => false));
$twig->addGlobal('session', $_SESSION);

if (isset($_GET["test_one"])) {
    $_SESSION["flash"] = "message one";
}else if(isset($_GET["test_two"])) {
    $_SESSION["flash"] = "message two";
}
echo "PHP says: ".$_SESSION["flash"]."<br><br>";

echo $twig->render('index.html');


?>

index.html

<form action="index.php" method="GET">
    <input type="submit" name="test_one" value="one">
    <input type="submit" name="test_two" value="two">
</form>

<p>Twig says: {{ session.flash }}</p>

Ideally the messages should match each other but the Twig message always prints the previous message.

But Twig will always output the second to last submission. I can't seem to get my head around this. I have looked through the Twig docs and through stackoverflow and haven't found any solutions. I turned caching off so I think I have ruled that out but maybe I am missing something here.

1

1 Answers

0
votes

Array's are passed by value by default in PHP, unless otherwise specified in the signature of the method (function addGlobal($key, $value) vs function addGlobal($key, &$value) {}).

If you really wanted to update the flash messages you'd need to switch up to an object to solve this.

<?php

class Foo {
    protected $array = [];

    public function addGlobal($key, $value) {
        $this->array[$key] = $value;
        return $this;
    }

    public function getGlobal($key) {
        return $this->array[$key] ?? null;
    }
}

class Bar {
    protected $value;

    public function setValue($value) {
        $this->value = $value;
        return $this;
    }

    public function getValue() {
        return $this->value;
    }
}

$foo = new Foo();
$bar = new Bar();

$bar->setValue('foobar');
$array = [ 'bar' => 'foobar', ];

$foo->addGlobal('array', $array);
$foo->addGlobal('object', $bar);

$array['bar'] = 'bar';
$bar->setValue('bar');

var_dump($foo->getGlobal('object')->getValue()); /** Output: bar **/
var_dump($foo->getGlobal('array')['bar']); /** Output: foobar **/

demo