Form Submitting Error with get_template_part()

I have come across an interesting problem regarding the get_template_part() .

I have created a theme options page (named sitewideSettings.php)

Read More

normally I would include this in functions.php like so:

include(TEMPLATEPATH."sitewideSettings.php");

which works fine.

But now I am trying to use get_template_part();

get_template_part('sitewideSettings');

which is also working fine except that when clicking ‘update’ to update the settings I get an error message: “Are you sure you want to do this? Please try again”.

“Please try again” links back to the theme options page and clicking update takes you back to the error message which takes you back to Theme options and round and round we go.

Nothing else has changed other than the use of get_template_part();

Anyone else come across this problem? How did you get around it? I am sure its something simple and obvious, but exactly what it is totally escapes me.

(Its not a nonce issue as a nonce is created in both instances)

Related posts

Leave a Reply

5 comments

  1. I know you say it’s not a nonce issue, but it clearly is. That notice is the default ‘This nonce didn’t check out’ message. I don’t know exactly why the nonce is failing, but that is what is happening.

    I would double check how your nonces are created and checked. If you’re using wp_nonce_field() make sure both action values and argument values are the same. Also, double check spelling of variables, or any scope-related issues that could be causing the nonce to fail.

    EDIT

    Following up on your insistence that it’s not a nonce issue (which it is. The nonce issue is caused by a scope issue), here’s what’s probably happened. Included/required files are executed in the scope in which they’re included. My guess is you’re using a variable to build either the nonce action or the nonce name. Because get_template_part() includes the template file in the scope of that function, it’s no longer being executed in the scope of your admin page’s display callback. You either need to globalize those variables in all locations, or you need to use constants instead of variables.

  2. Please do not use get_template_part() in the Admin / Backend. It has been designed for template use (displaying the theme, please see codex), so this is intended to be used for templates and template-parts within themes:

    Function Reference/get template part

    Load a template part into a template
    (other than header, sidebar, footer).
    Makes it easy for a theme to reuse
    sections of code in an easy to
    overload way for child themes.

    The function does actually includes general source code as well, but what you experience (as John pointed out) might be related to scope. As I do not know your code, I can not say for sure, if that is the exact cause of the issue you’re facing (variable scope), so I tend to keep it simple in my answer:

    The function is just not desgined to replace as standard php code include, for example to write an admin page.

    So just do not use it if for your admin page unless you really know what you are doing.


    Update:

    If you want to load a php file into the global scope while looking in the child and parent theme directory, you can make use of a function that does the search for the file for you: locate_template():

    Retrieve the name of the highest priority template file that exists.

    Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which inherit from a parent theme can just overload one file.

    For your given example include include(TEMPLATEPATH."sitewideSettings.php"); this can be written as:

    include(locate_template('sitewideSettings.php'));
    

    This allows you to control where and how the file is included (include/_once; require/_cone) and it prevents you to have the scope issue in your example which breaks the NONCE mechanism.


    The “Please try again” message is there because wp-admin is not able to verify the request, more specifically the so called nonce. There can be two reasons for that: There is none in the request (e.g. the form does not provide any or it does not get’s transferred or read by the admin code) or the nonce is invalid. Nonces always represent a chain of actions, and if that chain is broken, you’ll get that message. But the message does not tells you where that chain is broken.

    Those error messages in the admin are not always very informative and can be even misleading (Related: #14060). To find out what happens here, it’s most effective to debug that on the system where the error appears as it can be quite specific which part of the chain is broken.

    Please see the codex on how to create Admin Pages for your Theme or Plugin for more in-depth information about nonces, admin pages etc. . It’s not possible for the Admin request to validate the nonce for some reason.

  3. Hard to make a guess, it’s whole ladder of functions. get_template_part() calls locate_template() which calls load_template() which does require.

    I suggest you try these from bottom to top to determine if it is get_template_part() exactly or some function in between.

  4. This is a more detailed explanation of the first answer – i.e. “scope is you’re problem”

    My simple visualisation of get_template_part is like this:

    function get_template_part($slug) {
      require("$slug.php");
    }
    

    So if you have the following in sitewideSettings.php:

    <?php
    echo $nonce;
    ?>
    

    Template with include:

    <?php
    $nonce = 'xxx';
    include('sitewideSettings.php');
    ?>
    

    Gets translated (by PHP) into:

    <?php
    $nonce = 'xxx';
    echo $nonce;
    ?>
    

    Template with get_template_part:

    <?php
    $nonce = 'xxx';
    get_template_part('sitewideSettings');
    ?>
    

    Gets translated into:

    <?php
    $nonce = 'xxx';
    get_template_part(
      echo $nonce;
    );
    ?>
    

    So now anything in the template part is wrapped inside a function and any variables you have in your template part need a global on them.

    Thus to get it to work you need a global in the sitewideSettings.php, which would get translated into:

    <?php
    $nonce = 'xxx';
    get_template_part(
      global $nonce;
      echo $nonce;
    );
    ?>