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 Contact Form & Sending Email Testing For POST Data

redirect() with Slim 3.0

redirect() is no longer a helper function in the upgrade Slim 3.0. We must now make use of PSR-7's withHeader('Location', 'new-uri') method on the request object. Also, you must use this syntax on the request object to gain access to the field values of your form: $this->request->getParsedBody()[$index]

Notice that getParsedBody() returns an array. You can use extract() on this array to create variables named after the keys found within the array, and values are assigned accordingly. PHP docs does not recommend doing this in our case, however, because our values are not secure; they are input by the user. I didn't understand fully why this complicates things, but it's good to know.

Here is my post() code for this lesson:

<?php

$app->post('/contact', function (Request $request, Response $response, array $args){
  $body = $this->request->getParsedBody();
// I chose to only call the getParsedBody() once, 
// but you could also go $name = $this->request->getParsedBody()["name"]
  $name = $body["name"];
  $email = $body["email"];
  $msg = $body["msg"];
  if(!empty($name) && !empty($email) && !empty($msg)){

  } else {
  //  message the user that there was a problem
 //  Note: 'Location' refers to the current URI and 'contact' refers to my contact URL that I set with 
 // ->setName('contact') at the end of my get() method for the Contact page. ->setName() is the new syntax 
 //  for ->name()
    return $this->response->withStatus(200)->withHeader('Location', '/contact');
  }
});
?>
Tim Knight
Tim Knight
28,888 Points

This is great to know Antonio, seriously... thank you so much for sharing this.

No problem. It was a struggle. Take a look at my post in the previous video, as well. I'm a newb, so figuring this stuff out proves that anyone can do it. I can't get my local server to send out an email in the coming lessons. I'm using Apache 2.4 on a Windows 10 laptop. Also, using Slim 3.0 and PHP 7. I keep getting a Slim Error, with no specifics other than 500. I've set my php.ini sendmail_from value, etc., etc. I just don't know enough to troubleshoot this.

This is a link to my comment in the previous lesson: https://teamtreehouse.com/community/slim-30-code-for-this-lesson

Tim Knight
Tim Knight
28,888 Points

I'm still pretty new with PHP myself... normally focus on Rails and I can't say I'd be much help on Windows setup as a Mac user. What you've done definitely helps many of us though. Mail has always been weird for me with PHP. Are you using SwiftMailer?

I am. It must be something to do with my php.ini or Apache settings. I get a "Slim Error" but I don't think the error has to do with my code, as it's SwiftMailer code that we're using rather than Slim 3.0 to set up our mail. Not sure what the problem is.

I've debugged up to the $result = $mailer->send($message); It's definitely that line that triggers the error. My form input values are all properly assigned to their appropriate variables as verified by 'var_dumping' each of them.

Tim Knight
Tim Knight
28,888 Points

I'll try to get something setup using Slim 3.0 and see what kind of errors I come across.

I came across this awesome/useful Swiftmailer Logger plugin at http://swiftmailer.org/docs/plugins.html The logger gave me this when I sent a mail: ++Starting Swift_SmtpTransport

I assume that this is in fact not an error at all. It's working, but my localhost configs must not be set correctly. Here is how to make use of this plugin:

<?php
// Tells us how to send the email
// I'm using a local Apache 2.4 server run with PHP 7. I'm also using Slim 3.0.
// I'm using a free mailing service called Mailgun because Apache apparently
// can't send mail on its own. The code, excluding the logger setup, is recommended
// by Mailgun, and is found in their blog.
// Notice that you can chain, just like in jQuery.
  $transport = Swift_SmtpTransport::newInstance('smtp.mailgun.org', 25)
    ->setUsername('postmaster@my_domain')
    ->setPassword('my_password')
    ;

  // Create the Mailer using your created Transport
  $mailer = Swift_Mailer::newInstance($transport);
  $logger = new \Swift_Plugins_Loggers_EchoLogger();
  $mailer->registerPlugin(new \Swift_Plugins_LoggerPlugin($logger));

  $message = Swift_Message::newInstance()
    ->setSubject('Email From Our Website')
    ->setFrom(array(
    $cleanEmail => $cleanName
  ))
    ->setTo(array('me@me.com'))
    ->setBody($cleanMsg);
  if(!$mailer->send($message, $errors)) {
    echo "Error: " . $logger->dump();
  } else {
    $result = $mailer->send($message);
  }
?>
Tim Knight
Tim Knight
28,888 Points

I think you're probably right on in terms of it just being a local configuration issue, but this is really helpful.

Got it to work! Mailgun apparently has issues with port 25. Changed it to port 587, as recommended by Mailgun, and I can now successfully send mail from my local server with the code above! Phew. That took 3 days.

Tim Knight
Tim Knight
28,888 Points

3 days though... not so bad for some new things. Well done!

Antonio - I have a related question about redirects from later in the videos when we're trying to redirect after we've set up our mail... can you have a look?

https://teamtreehouse.com/community/redirect-after-email-slim-3

4 Answers

FULLY WORKING CODE......

if ( !empty($name) && !empty($email) && !empty($msg) ) {

} else {
     return $response->withStatus(301)->withHeader('Location', '/composertest/contact');
}

I'm using a local server and had to set up my own mail server. My code wasn't the problem.

Devin Gray
Devin Gray
39,261 Points

I did it slightly differently, but I'm glad I figured it out before coming to the forum for help. If you don't like creating a project for every new PHP site you make, like me, it can be a pain to put the whole directory name as the location. So i made the current URI into a variable and pointed the location to that variable. It does the same thing, but it won't break when I migrate the site. But this post even helped me find some errors with my code. I love treehouse!

<?php

$app->post('/contact', function ($request, $response, $args) {
  $body = $this->request->getParsedBody();
  $name = $body['name'];
  $email =$body['email'];
  $msg = $body['msg'];
  $uri = $request->getUri();

  if(!empty($name) && !empty($email) && !empty($msg)) {

  } else {
    //message the user that there was a problem
    return $response->withHeader('Location', $uri);
  }
});
Alexander Grishchun
Alexander Grishchun
360 Points

Hi, guys. I can not understand one thing. If i have 2 different forms on my site. Where in my index.php i need to indicate, from witch form Slim must grub and post data? Maybe it "action" parameter?

Aleksandr Antropov
Aleksandr Antropov
6,458 Points

Can do like this also

<?php
else {
    //message the user that there was a problem
    return $res->withRedirect('/contact');
}