Post It

The title of this particular article is somewhat misleading as it has nothing to do with sending an email upon creating a new post in WordPress, but actually whenever the HTTP POST action has occurred.

Additionally, the methodology describing below isn’t relegated to just sending emails – it can be used when any data needs to be managed upon a POST request. This includes sending emails, serializing data to the database, evaluating information to be presented on the next page view, or whatever else.

Of course, one of the best ways to actually demonstrate how to do something is to give some practical example, so for all intents and possible, I’m going to show how to structure a project using the event-driven model of WordPress to send an email upon a POST request.

Send Data on POST

Before actually showing any code, the motivation for this whole post comes from the fact that I have seen – and written – code that doesn’t necessarily jive well with the way WordPress handles its events.

That is to say that the code works and it does what it’s supposed to, but it’s not clean, and there is not a separation of concerns as far as the logic is concerned. Remember: since WordPress is event-driven, we can hook into certain points of the WordPress lifecycle to make something happen.

Finally, note that this is how I generally picture organizing code in WordPress:

WordPress Code Organization

Functions call into WordPress and provide data for templates to render.

Note that templates serve as views that either call into functions.php or that render data that has been managed by functions that are hooked into events in functions.php.

How Not To Do It

So let’s say you want to send a custom email whenever a person fills out a form on a custom page template that you’ve created. For example, let’s say that the page is going to POST back to itself and then display a message whenever the process has completed.

Okay, so here’s one way to go about actually structuring a page template to send an email whenever the page posts to itself:

<?php get_header(); ?>
<?php my_theme_send_email(); ?>

	<div id="content">
		<form method="post" action="">
			<!-- TODO -->
			<input type="submit" name="submit" value="Send Email" />
			<input type="hidden" name="email-submission" value="1" />
		</form>
	</div><!-- /#content -->

<?php get_footer(); ?>

And then in functions.php you may have something like this:

function my_theme_send_email() {

	if ( isset( $_POST['email-submission'] ) && '1' == $_POST['email-submission'] ) {

		// Send the email...

	} // end if

} // end my_theme_send_email

For the most part, the code for sending the email isn’t all that wrong; however, the problem is actually within the page template. Note that right under the get_header() call, we’re calling the function my_theme_send_email().

This is one way that I have once written – and seen others write – similar code. And although this works, it’s not really the event-driven way to do things.

Do It With Events

The refactoring for this is actually really simple. Whenever a WordPress-based page loads, it will go down through the normal WordPress page lifecycle which means that we can take advantage of each of the available event that fires as WordPress is loading it’s pages.

To that end, we don’t need to have our page templates call into functions.php. Remember: they should primarily be used to display data.

So first, remove the function call in the page template:

<?php get_header(); ?>

	<div id="content">
		<form method="post" action="">
			<!-- TODO -->
			<input type="submit" name="submit" value="Send Email" />
			<input type="hidden" name="email-submission" value="1" />
		</form>
	</div><!-- /#content -->

<?php get_footer(); ?>

Then hook the function for sending the email into an action such as init (thanks to the comment by Danny):

function my_theme_send_email() {

	if ( isset( $_POST['email-submission'] ) && '1' == $_POST['email-submission'] ) {

		// Send the email...

	} // end if

} // end my_theme_send_email
add_action( 'init', 'my_theme_send_email' );

Notice that we’ve leaned out the page template, kept the function for sending the email the same, but we’ve hooked it into the init action.

This works because if the request is coming from a page other than the template, then the conditional won’t fire. If, however, a POST is made from the page template, then the function will fire, the conditional will pass, and then the email will be sent.

It’s All About Structure

The point of sharing all of this isn’t to show how to send an email with WordPress, clearly, nor is it how to build custom page templates.

It’s about how to properly structure projects and applications to take advantage of the design patterns that WordPress implements.

Category:
Articles
Tags:

Join the conversation! 40 Comments

  1. So… maybe I’m misunderstanding here, but the article seems to imply there is some WordPress based event that fires when a POST occurs. But it looks to me like it’s actually the wp_head action that fires (which happens on any page load, POST or not), and you are just using regular PHP to inspect the $_POST object (which also is a PHP construct).

    I’m not complaining or criticizing (I may even be flat out wrong, you’re smarter than me), I’m just trying to ascertain whether or not I’ve misunderstood something. There is a no WordPress-based POST event?

    • So… maybe I’m misunderstanding here, but the article seems to imply there is some WordPress based event that fires when a POST occurs.

      That’s a failure on my part to effectively communicate what I was trying to say, so that’s for bringing this up.

      I’m not at all saying that there’s an event that fires when a `POST` event occurs. I just mean that there’s a right way, within the context of WordPress, to interrogate the `POST` collection rather than writing a function call at the top of a template.

      Simply hook it into the `wp_head` action instead.

      you are just using regular PHP to inspect the $_POST object (which also is a PHP construct).

      Yep! There’s no WordPress API for providing an abstraction for doing this (and, fwiw, I don’t think there should be. It’s just be a wrapper function, anyway, you know?

      My main point was this: Don’t put function calls at the top of your templates. Hook them into the proper point in the WordPress page lifecycle.

      That’s the moral of the story ;).

      (I may even be flat out wrong, you’re smarter than me)

      False, sir!

  2. Hi Tom,
    working with events in WordPress is a solution. But I think it’s not 100% efficient in your example. I mean when you use the hook ‘wp_head’, your function ‘my_theme_send_email’ is fired for all front-end requests. It’s not that it will slow down the website or consumes the server’s ressources but WordPress is firing a function that should only be used in one page and not all of them.

    Maybe first check in ‘functions.php’ if we are handling in general a GET http request or a POST one and then only attach an action hook like ‘wp_head’. This way all GET requests don’t have to fire the ‘my_theme_send_email’ function. What do you think ?

    • I think this is more than far. Anything that we can do in order to maintain the separation concerns but not at the detriment of performance is key.

      So I say what you’ve proposed works fine and I’m a fan. The above example was really meant to show how to separate concerns a bit more than to make sure performance is key. But your suggestion makes it all the better.

      • wul… is running a function really all that performance consumptive? I mean, the difference between:

        runSmallFunction(){

        // do things with $_POST

        }
        if($_POST)runSmallFunction();

        vs.

        runSmallFunction(){

        if(!$_POST)return;

        // else do things with $_POST

        }
        runSmallFunction();

        • This is an old post — I’ve learned a lot since then. In terms of performance, I doubt it really causes that big of an impact.

          You live, you learn :).

          That’s part of what I wrote about earlier today.

  3. Hi Tom, thanks for the article. I have been using ‘wp_ajax_*’ technique for ‘POST’ request. Basically it uses the admin-ajax.php as the form’s action attribute. Can you tell me the fallback of using wp_ajax_* or wp_ajax_nopriv_*, compared to the one on this article?

    • If you’re using Ajax, then it’s a little bit different in this post because you’re basically setting up a request to go to the server side, retrieve the data, and pass it to a handler on the client side.

      That’s just the proper way to do it, so it sounds that based on what you’ve mentioned in your comment that you’re good to go :).

  4. Hey Tom,

    Why use wp_head for this, and not something like wp? Or are you just saying “use an action hook”?

    • `wp` should work just as well as `wp_head`. The point I was more or less trying to make was to use an action hook – I gave one example just because someone people’s mileage may vary based on what it is that they are trying to do.

      In this case, `wp` would work just as well :).

      • Yeah, I was just curious. I was thinking about this a month ago and looked at some other plugins to see how they did it. Gravity Forms, for example, hooks their form processing code on the wp hook (where I got that idea).

        To me, wp_head just feels like it should be used to output things into the head, while init or wp feel like the right place for application logic. But maybe I shouldn’t think so much about how WordPress hooks make me “feel” :)

        • But maybe I shouldn’t think so much about how WordPress hooks make me “feel”

          On the contrary!

          If you feel that there’s a better hook to use than one that’s suggested, look into it! The more experienced you get with development, the more accurate you’re going to be.

          Don’t stop ignoring that gut feeling :).

        • I concur with you, Josh! I know we’re nitpicking your concept, Tom =P

          I another good reason I like using wp instead of wp_head is it happens before any templates are loaded. So if there’s any important logic that needs to fire, it can before any of that occurs. It’s useful if you need to queue up some information before anything is displayed, ie you have a search form and its looking for specific posts or post types. You can hook into wp and do all your logic there.

          • I know we’re nitpicking your concept, Tom.

            Doesn’t my concern – as far as I’m concerned, this is half what blogging is all about :).

            We share our stuff and have others help us to discuss and make things better.

            It’s useful if you need to queue up some information before anything is displayed.

            Yes – this is probably my favorite reason, thus far, for actually using this hook instead.

    • I use wp_loaded, cause it’s the moment when WordPress ready to go, and you’re good to start working with it.

      Realistically you could use any hook, but I think you should use something earlier than wp_head… Just because wp_head may or may not be included in the theme (it should be! but if you can’t be sure some dummy forgot it).

  5. Hi Tom,

    ‘You’re totally right but I would suggest hooking into a hook that runs before any headers are sent. The ‘init’ hook is perfect for this.

    http://codex.wordpress.org/Plugin_API/Action_Reference/init

    Danny

  6. do you know bbpress… there’s a function to get user profile url
    bp_loggedin_user_domain()

    When this is called in my init hook to handle form submission, it returns null…. any idea? i suspect bp_loggedin_user_domain return value is not built properly at this point (init); maybe it’s too early?

    where can i hook my form submission callback then?

    • wp_init hook suggested by Shawn Wernig seems to be ok. bp_loggedin_user_domain() working now :) … is this the best hook to use for form submission?

  7. Great Article Tom, Thanks for sharing. Exactly what I was looking for!

  8. Hello!
    I’m really new to wp. I work with RoR and the lack of tools to treat forms and submissions has called my attention.
    I liked your post, it helped me get an idea of wp forms and submissions.
    I’d like to share what I did and see if that isn’t very naive.

    I used the plugin “PhP Code for Posts and Pages”, that lets you add a shortcode to a page.
    That plugin will input a php snippet in your page when its published.

    My snippet is the following:
    <?php
    echo '

    First name:
    Last name:

    ‘;

    if ( isset( $_POST[’email-submission’] ) && ‘1’ == $_POST[’email-submission’] ){
    echo “Post data1: “.$_POST[“FirstName”];
    echo “Post data2: “.$_POST[“LastName”];
    echo “Success!!!”;
    }
    ?>

    I just added the shortcode to the page and it worked.
    I think I should have put the form’s html in a template, but that’s just an example.
    I think this solution is quite encapsulated, but I’m very new to wp, so I can’t see the drawbacks of it.

    What do you think!?
    Thanks!

    PS: Sorry for code formatting..didn’t know how to do that. :(

  9. I’m trying to follow the proper method for handling events in wordpress but is it possible to have more than one ‘init’ action? I’m modifying a wordpress plugin and adding a second form to the shortcode page. Problem is that both forms seem to be processed by the same function. I know the problem might be because I have two ‘init’ actions but wondering how this should be handled.

    // **********

    // first form

    // **********

    add_shortcode(‘first-submit’, ‘cp_first_form’);

    function cp_first_form($atts, $content = null) {

    // html form

    }

    function cp_first_form_submit_post(){

    // code to process first form on submit

    }

    add_action(‘init’,’cp_first_form_submit_post’);

    // ***********

    // second form

    // ***********

    add_shortcode(‘second-submit’, ‘cp_second_form’);

    function cp_second_form($atts, $content = null) {

    // html form

    }

    function cp_second_form_submit_post(){

    // code to process second form on submit

    // strangely, it seems both forms get processed by this function after submit.

    }

    add_action(‘init’,’cp_second_form_submit_post’);

    • There’s nothing wrong with attaching multiple functions to the same handler (that is, there’s nothing wrong with having multiple functions attached to init).

      In order to properly handle the content of the forms, there are a couple of things to try:

      1. Try changing the priority of the functions
      2. Write two functions (one for the first form, one for the second form) and pass the data to each function based on the type of data it is

      I’m not sure Option 1 will actually work since everything is passed from a single form, but Option 2 should be fine for sniffing out what form information you’re dealing with then writing custom functions to properly handle each one.

      I hope this helps.

  10. Thanks alot helped me alot :D

  11. Hello, I just wanted to say thank you for this explanation. I was looking for good practices on how to send data in WordPress and found yours.

    You mentioned in one of your comments that you would now do it differently, what would you change then?

    Best regards,

    Julien

    • Honestly, it depends on the type of data, how it’s being sent, and what the circumstances are.

      For example, is it Ajax or not? Is it happening from the dashboard or from the front-end? Does the current user have permission to do so? Etc. Etc.

      There’d be a lot to cover :).

      • Alright thank you for your quick answer,

        So for example, for data sent from a form in the frontend that will be stored in the database and sent by email?

        • This is something that’d take longer than a comment to show how to do, but the gist of what you’re looking to do can be achieved by a number of different WordPress API functions such as [wp_mail]( https://codex.wordpress.org/Function_Reference/wp_mail).

          In terms of what you’re looking to do for saving it to the database, it depends on if you’re looking to save it to the post meta table, options table, etc. You’d then use the appropriate APIs for sanitizing the data and then writing it to the right database table.

          • Thank you again for your answer,

            I found your other post where you talk about how sending emails so I will have a look at it.

            For the data, I chose to create a custom post type and a new post of this type when clicking on the send button.

            • Then what you’re looking to do is to update the post meta data for a specific post (of that post type) when the user clicks send.

              The Codex has great articles on adding, updating, and deleting post meta data — Google for it and you should be good to go. I don’t really have the space in comments to walk through something like that.

  12. thanks alot for this article, this article is very helped me very much.

  13. Do have a tutorial on how to create a form and then save the post data to mysql ?

    • I don’t – I generally only provide WordPress-related content on this site.

      To do what you’d like you do, though, you’d need to:

      • Validate and sanitize the incoming form data
      • Return any errors, if they exist

      • Setup a connection to the MySQL database

      • Create the query to insert the information

      • Close the connection

      • Redirect to a page after it’s done

      Hope this helps!

  14. Hey Tom.Nice article.One thing I don’t understand or am not sure off is if you do add the above function to your init hook it will be processed everytime a page on your site is opened.Right?Assuming am right and what you want is to have this function loaded only once for your given page eg. contact-form page how would you achieve this. So far what I have noticed is using plugins ensures the code snippets in the plugins are loaded on every page request and the method above of adding the function to init hook does the same.Please correct me where I am wrong I am still on the WP learning curve.

    • This is an old post and I’ve changed quite a bit in the way that I present information since writing this, so I think your questions are completely valid (and I appreciate you asking me). I’ll do what I can to answer them:

      your init hook it will be processed everytime a page on your site is opened.Right?

      Yes, but it also assumes the hidden field has a value of ‘1’ whenever the page is loaded. This can be controlled by, say, JavaScript. If it doesn’t have that value, then the rest of the code won’t be processed.

      Assuming am right and what you want is to have this function loaded only once for your given page eg. contact-form page how would you achieve this.

      There’s nothing wrong with code being loaded more than once on a page, but I’d would do some additional checking with, say, nonce values and then duck out if the values aren’t set for the nonce nor are they set for the form.

      Please correct me where I am wrong I am still on the WP learning curve.

      You aren’t really wrong, but there’s not much you can do about preventing a function from firing on each page load, but you can control just how much of that function executes by evaluating the result of a conditional.

  15. I think it’s much better if you use the admin_post_nopriv hook instead.

    Then you’ll just have to post your public form as an unauthenticated user to admin_url(‘admin-post.php’) and specify an action parameter.

    For example, set action to ‘handle_form’ and then register a hook on admin_post_nopriv_handle_form and you can handle the form.

    No need for your “if ( isset( $_POST[’email-submission’] ) && ‘1’ == $_POST[’email-submission’] ) {“.

    Please see more info here:

    http://www.sitepoint.com/handling-post-requests-the-wordpress-way/

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.