Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm struggling to understand how I should achieve a decent error-handler at frontend (serverside). The code is written in functions.php in a specific theme (if that matters). Down below a custom post type named pupil is created upon submit.

$pupil = new Pupil();
add_shortcode('wppb-register', array($pupil, 'frontEndRegistration'));

//Check if visitor is trying to save a new pupil
$pupil->checkFrontEndRegistration();

In the pupil-class I show (return) this content (form):

//Show public register-form
public function frontEndRegistration($atts, $content="", $errors = null) {   
     $class_errors = array();

    if (is_array($errors) && !empty($errors)) {

        foreach($errors as $key=>$err) {
            if ($err === true) {
                $class_errors[$key] = ' error';
            }
        }           
    }
    $content .= '
    <form id="adduser" name="adduser" method="post" action="">' .
            '<table class="form-table"><tbody><tr><td colspan="2">'.$this->getRelatedCoursesPupil(null, array('args' => array('fetchContent' => 'returncontent')))
    .  '</td></tr>
    <tr>
        <th><label for="email">Förnamn*</label></th>
        <td><input name="first_name" id="first_name" value="" class="regular-text' . $class_errors['first_name'] . '" type="text"></td>
    </tr>
    <tr>
        <th><label for="email">Efternamn*</label></th>
        <td><input name="last_name" id="last_name" value="" class="regular-text' . $class_errors['last_name'] . '" type="text"></td>
    </tr>        
    <tr>
        <th><label for="age">Ålder*</label></th>
        <td><input name="age" id="age" value="" class="regular-text" type="text"></td>
    </tr>          <tr>
        <th><label for="email">E-post</label></th>
        <td><input name="email" id="email" value="" class="regular-text" type="text"></td>
    </tr>
    <tr>
        <th><label for="homephone">Telefon hem*</label></th>
        <td><input name="homephone" id="homephone" value="" class="regular-text" type="text"></td>
    </tr>

    <tr>
        <th><label for="cellphone">Mobiltelefon*</label></th>
        <td><input name="cellphone" id="cellphone" value="" class="regular-text" type="text"></td>
    </tr>
    <tr>
        <th><label for="adress">Adress</label></th>
        <td><input name="adress" id="adress" value="" class="regular-text" type="text"></td>
    </tr>
    <tr>
        <th><label for="postnr">Postnr</label></th>
        <td><input name="postnr" id="postnr" value="" class="regular-text" type="text"></td>
    </tr>
    <tr>
        <th><label for="ort">Ort</label></th>
        <td><input name="ort" id="ort" value="" class="regular-text" type="text"></td>
    </tr>
    <tr>
        <th><label for="description">Övrigt</label></th>
        <td><textarea name="description" id="description" class="description"></textarea></td>
    </tr>    
    <tr><td>
    <input type="hidden" name="action" value="newpupil-frontend" />
    ' . wp_nonce_field( 'newpupil-frontend', 'newpupil-frontend') . 

    '</td></tr></tbody>
    </table>
    <input type="submit" value="OK" name="addusersub" id="addusersub" />
    </form>
    ';

    return $content;
}

Here I'm doing the actual checking before saving it to database.

//Save pupil
public function checkFrontEndRegistration() {

        if( 'POST' == $_SERVER['REQUEST_METHOD'] && !empty( $_POST['action'] ) &&  $_POST['action'] == "newpupil-frontend") {

            //Required fields
            $errors = array();
            if (!isset($_POST['first_name']) || strlen($_POST['first_name']) == 0) {
                $errors['first_name'] = true;
            }
            if (!isset($_POST['last_name']) || strlen($_POST['last_name']) == 0) {
                $errors['last_name'] = true;
            }
            if (!isset($_POST['age']) || strlen($_POST['age'] == 0)) {
                $errors['age'] = true;
            }         
            if (!isset($_POST['homephone']) || strlen($_POST['homephone']) == 0) {
                $errors['homephone'] = true;
            } 
            if (!isset($_POST['cellphone']) || strlen($_POST['cellphone']) == 0) {
                 $errors['cellphone'] = true;
            }           

            //Add new pupil-cpt into post-table when there are no errors
            if (empty($errors)) {
                //Remove hook temporarily
                remove_action( 'save_post' , 'postsubmitted');

                $pupil = array(
                    'post_title'    => 'unregistered',
                    'post_status'   => 'private',           // Choose: publish, preview, future, draft, etc.
                    'post_type' => 'pupil',
                    'post_author' => 5500                   
                );
                //save the new post and return its ID
                $post_id = wp_insert_post($pupil); 

                //Save everything relevant for this new pupil
                saveform_db($post_id, $_POST, true);        //True says that it's frontend-saving

                //Rehook temporarily removed hook
                add_action( 'save_post' , 'postsubmitted');
            }
            else {
                throw new Exception('Pupils must be entered');
                //$this->frontEndRegistration('', '', $errors);
            }

        }

    }

It works fine, but I can't figure out how to show the errors when user hasn't typed in required fields.

Instead of throw new Exception(Pupils must be entered); I want to show the same frontendRegistrationform() but with the errors that are set when there are no value in the required fields.

I guess I oould use sessions, but is there any better way?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

This is a pretty basic solution. First I am assuming that you are not saving the data/form, and just returning to the same page.. In your $formContent you would do something like this.

<?php
$formContent = '
    ....
    <tr>
        <th><label for="email">Förnamn*</label></th>
        <td><input name="first_name" id="first_name" value="" class="regular-text' . $class_errors['first_name'] . '" type="text">'
    . ( array_key_exists( 'first_name', $class_errors ) ? "<br/>You must enter your first name." : "" ) . '</td>
    </tr>";

If you wanted to access the errors on the form itself, I would personally recommend doing the error checking through JavaScript. This way, you can actually prevent the page from submitting, rather than submitting, cancelling, and redirecting back. With jQuery, it would be something like:

$('form').submit(function(event){
    var $form = $(this);

    // if any empty fields with the required class are found
    if ($form.find('input.required:empty').length) {
        event.preventDefault(); // cancel form submission
        $form.find('input.required:empty').after('<p class="error">This field is required');
    }
});

Obviously you could customize each field's message by reading the label attached to that input, or putting individual checks on each field. You can also work in some custom validation here, like Phone number validation, email, etc.

That's my preferred method.

For the PHP side, you should be able to store your error classes either on a class variable, or a global variable. Since the post.php page points back to itself, there is no redirection between your form submission checking, and re-rendering the page. You should be able to store the errors in a class variable and use it within both functions.

Very high level:

class myFormStuff {
    protected $error_classes;

    // happens first, on init most likely
    function checkFrontEndRegistration(){
        $this->error_classes['first_name'] = "Dude, where's your name at?";
    }

    // Happens way later in the page reload, when rendering the form
    function frontEndRegistration() {

        if ( array_key_exists( 'first_name', $this->error_classes ) ) {
            echo '<p class="error">' . $this->error_classes['first_name'] . '</p>';
        }
    }
}
share|improve this answer
    
How do I pass the actual errors from checkFrontEndRegistration() to the frontEndRegistration() ? It's a correct assumption, by the way. –  bestprogrammerintheworld Mar 17 at 14:59
    
Adding to my answer.. –  Eric Holmes Mar 17 at 15:31
    
Thanks for your extended answer. I am actually doing that check in jQuery. But for safety I must have server-side validation as well. But I still didn't get the answer on my actual question :-) (How do I pass the actual errors from checkFrontEndRegistration() to the frontEndRegistration() ? (I mean class_errors would just be an empty array if there are nothing in array $errors that is specified) –  bestprogrammerintheworld Mar 17 at 16:36
    
Good call - best practice should be to handle it on both ends. Extended answer 2.0 - in short, post.php points to itself, and handles the error checking early in the page load. so you can access your data later on :). Check it. –  Eric Holmes Mar 17 at 18:03
    
aah. Thanks a lot for sorting that out! :-) –  bestprogrammerintheworld Mar 17 at 18:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.