Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

PHP Building Websites with PHP Slim Basics & Twig Templates Layouts with Twig

Passing value from index.php to a TWIG file

I'm trying to pass values to my TWIG pages so that if a user forgets to input a value into a particular form input field, an error message shows up in that field. For example(keep in mind that I'm using Slim 3.0 syntax, so some code may differ from the lesson's):

<?php
$app->post('/', function (Request $request, Response $response, array $args){
  $body = $this->request->getParsedBody();
  $name = $body["name"];
  $email = $body["email"];
  $msg = $body["msg"];
  if(!empty($name) && !empty($email) && !empty($msg)){
    $cleanName = filter_var($name, FILTER_SANITIZE_STRING);
    $cleanEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
    $cleanMsg = filter_var($msg, FILTER_SANITIZE_STRING);
  } else {
   if(empty($name)){
       $nameErr = "You must enter a value here";
    }
     return $this->response->withStatus(301)->withHeader('Location', '/#contact');
  }
?>

And on my contact page:

<input class="form__input" type="text" name="name" value="{{ nameErr }}" />

At the moment, the $nameErr value is not passed to my contact page if the user does not enter a name.

Sergey Vrenev
Sergey Vrenev
28,778 Points

I'm here with the same problem. I'm trying to implement flash messages with new slim-flash provider. I can var_dump variable with this flash message in index.php, but i can't understand how to pass variable to twig template. Maybe someone has an answer for us? Thx for help anyway.

<?php 
$app->get('/', function ($req, $res, $args) {
  // Get flash messages from request
  $messages = $this->flash->getMessages();
  var_dump($messages[test][0]); // I have result under mane page, but how pass it to the div

  // Render home twig template
  return $this->view->render($res, "/pages/home.twig");
})->setName('home'); 
?>

4 Answers

Okay, so after peeking under the hood of the Twig-view helper, I noticed that you can pass an array called data through methods like fetch() and render(). (Keep in mind that I'm using Slim 3.0, so these can only be called on the view class, like $this->view->render()). I tried some simple code to pass an error message to an input field in my form. My PHP code looks like this:

<?php
$home_get = $app->get('/', function (Request $request, Response $response, array $args) {
  $args['errName'] = "This is an error.";
  return $this->view->render($response, 'main.twig', $args);
?>

My Twig code looks like this:

<fieldset class="form__fieldset">
      <label class="form__headline--sec">Name</label>
      <input class="form__input" type="text" name="name" value="{{ errName }}"/>
      <label class="form__headline--sec">Email Address</label>
      <input class="form__input" type="text" name="email" />
      <label class="form__headline--sec">Message</label>
      <textarea class="form__input form__textarea" name="msg"></textarea>
      <input id="submit" class="form__button" type="submit" name="send" value="Send" />
    </fieldset>

Notice that I used Twig's syntax to echo the value of errName as the value of my name input field. It worked. I still haven't tried this with POST, yet. With Slim 3.0 you must redirect with PSR-7's withHeader(). I don't know how to pass variables through the header. Perhaps this is done automatically? I'll let you know.

Add tried using

<?php
$app->post('/', function (Request $request, Response $response, array $args){
  $body = $this->request->getParsedBody();
  $name = $body["name"];
  $email = $body["email"];
  $msg = $body["msg"];
  if(!empty($name) && !empty($email) && !empty($msg)){
    $cleanName = filter_var($name, FILTER_SANITIZE_STRING);
    $cleanEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
    $cleanMsg = filter_var($msg, FILTER_SANITIZE_STRING);
  } 
  else {
    //  message the user that there was a problem
    $args['errName'] = "A field was empty";
    return $this->response->withStatus(301)->withHeader('Location', '/#contact');
  }
}
?>

to no avail.

However, this works:

<?php
$app->post('/', function (Request $request, Response $response, array $args){
  $body = $this->request->getParsedBody();
  $name = $body["name"];
  $email = $body["email"];
  $msg = $body["msg"];
  if(!empty($name) && !empty($email) && !empty($msg)){
    $cleanName = filter_var($name, FILTER_SANITIZE_STRING);
    $cleanEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
    $cleanMsg = filter_var($msg, FILTER_SANITIZE_STRING);
  } 
  else {
    //  message the user that there was a problem
    $args['errName'] = "A field was empty";
    return $this->view->render($response, 'main.twig', $args);
  }
}
?>

But I'm sure this isn't best practices.

Sergey Vrenev
Sergey Vrenev
28,778 Points

Flash messages could help you to reach what you want and it works with render method. To implement flash messages first of all you have to install slim/flash (https://github.com/slimphp/Slim-Flash) because slim3 doesn't have it out of the box. In my index.php i have session_start() by default. Then you need to register the flash provider in dependencies(if you are using slim skeleton like i do) or in index.php like in the lesson. And then let's say we want to send email from our site and give user a feedback, so using swift_mailer we do this:

<?php
$app->post('/', function (Request $req, Response $res, array $args) {
  // Parse all variables
  $body = $this->request->getParsedBody();

  $transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');

  // Create the Mailer using your created Transport
  $mailer = Swift_Mailer::newInstance($transport);

  // Create a message
  $message = Swift_Message::newInstance()
    // Give the message a subject
    ->setSubject($body['subject'])
    // Set the From address with an associative array
    ->setFrom(array($body['email'] => $body['name']))
    // Set the To addresses with an associative array
    ->setTo(array('123@gmail.com'))
    // Give it a body
    ->setBody($body['msg']);

  // Send the message
  $result = $mailer->send($message);

  // If result is true, redirect to home page with flash message
  if ($result > 0) {
    // Set flash message for next request
    $this->flash->addMessage('flash1', 'Your email was sent, thank you!');
    $this->flash->addMessage('flash2', 'Your message is on the way!');

    // Redirect
    return $this->response->withStatus(302)->withHeader('Location', '/');
  }
});
?>

And in get route for our home page we do this:

<?php
$app->get('/', function ($req, $res, array $flash_messages) {
  // Get flash messages from request
  $flash_messages = $this->flash->getMessages();

  // Render home twig template
  return $this->view->render($res, "/pages/home.twig", $flash_messages);
})->setName('home');
?>

$flash_messages now contains array of all messages in this session and you can pass it to home.twig with their names or with if/for loops and so on so forth.

  <p> {{ flash1 }} </p> <p> {{ flash2 }} </p>

Perfect. Excellent. I'll give this a shot. Just what I was looking for. Thanks.

I was onto something when I came across this problem in Stackflow: http://stackoverflow.com/questions/871858/php-pass-variable-to-next-page

But I couldn't quite understand why my _SESSION variables would always display regardless of whether or not there was an error and whether or not I disabled them after rendering a Twig file in my browser. I think Flash messaging was indeed the key in its implementation of _SESSION. Interesting stuff. Thanks for the help.

Sergey Vrenev
Sergey Vrenev
28,778 Points

Thanks for your help too, i think that's how junior and master developers work in real world, we can be proud of ourselves i think. Flash messages are used in Rails, PHP, Python, for logging, feedback and much more, i think they are very useful in all projects... Meet you in this forum again )

I continue to get this error when I try to echo messages[whatever] in my Twig file: Notice: Array to string conversion in C:\Apache24\htdocs\vendor\twig\twig\lib\Twig\Environment.php(403) : eval()'d code on line 115 Array

Line 115 refers to the cache. I was wondering how you configured your Twig-view and whether you set cache=>false, like I did.

I var_dump(message['success']), for example, and get the correct response. However, {{ success }} displays the error. This most likely means that my Twig configurations are faulty.

Okay, I figured out what my problem was, and it has nothing to do with my Twig configuration, but rather my understanding of what I was actually doing by creating something like:

$this->flash->addMessage('flash1', 'Your email was sent, thank you!');

I thought the 'flash1' was the key, and the 'Your email was sent, thank you.!' was the value, so I could access the value of 'flash1' with $message['flash1']. However, 'flash1' is actually an array, and the long string is the value of flash1[0]. So to echo that string I had to do this:

{{ flash1[0] }}

If I go: $this->flash->addMessage('flash1', 'Your email was sent, thank you!'); $this->flash->addMessage('flash1', 'Another message!');

Then I can echo these messages with {{ flash1[0] }} and {{ flash1[1] }}

Sergey Vrenev
Sergey Vrenev
28,778 Points

Yes, you are right, could not answer to you, because was busy, but you figured this out ). I want to figure out, whether we can replace flash messages' keys from 0,1,2 to words, something like this:
$this->flash->addMessage('flash' - array, 'success' - key, 'abcde' - message). To make things like this:

{% if flash is not empty %}
    {% for key, msg in flash %}
      <h1> {{ key }} </h1>
      <h2> {{ msg }} </h2>
    {% endfor %}
  {% endif %}
Sergey Vrenev
Sergey Vrenev
28,778 Points

Hm, yes,it really works with static text (nice work!), but i still don't understand how to implement this method to flash messages )

We have:

<?php
if ($result >= 0) {
    // Set flash message for next request
    $this->flash->addMessage('test', 'This is a message');

    // Redirect
    return $this->response->withStatus(302)->withHeader('Location', '/');
  }

// and then 

// Route for home
$app->get('/', function ($req, $res, array $args) {
  // Get flash messages from request
  $messages = $this->flash->getMessages(); // $messages variable now contains array of flash messages
  // And now i can't understand how this $messages array pass to twig

  // Render home twig template
  return $this->view->render($res, "/pages/home.twig", $args);
})->setName('home'); ?>

I'm feeling myself soooo stupid...

Sergey Vrenev
Sergey Vrenev
28,778 Points

Okey Antonio, thanks to you, i think i found the solution. Some experiments and i will write it here.

Please do. I'd like to be able to pass $args through a redirect to my form of a single page website I'm constructing. I don't think this can be done with render().