skip to Main Content

I’m building my own custom login page for wordress. The login form seems to work, however I would like to be able to customize the error message more specifically.

When the login credentials are incorrect and you log in, the error message appears only after the page has reloaded. What I would like to do is show the error message without reloading the page.

I searched on stackoverflow and wordpress reference but couldn’t find a solution for my case. Anyone have a suggestion on how I might achieve my goal?

Thanks for any replies, I appreciate any help.

Update 2

I thank the users who helped me with their answers, they were very helpful and I really appreciate it. I literally spent all day on this problem, I finally achieved my goal. The ajax request works and the message is displayed as I wanted. I had to go through a lot of things several times. However I leave the updated code for anyone who needs help.

My custom_login_page.php file
This contains the html structure, the form and the script that executes the ajax requests. Put the file in your active child theme. In my case I called the custom_login_page.php file. For this to be read by wordpress you need to create a new page and select it as a template.

enter image description here

<?php

// Template Name: Custom Login Page

?>

<?php get_header(); ?>

  <div class="container_main">
    <?php if (is_user_logged_in()) { 
      ?><span>Sei gia loggato</span><?php // If the user is logged in, it shows the message below
    } else { // otherwise, if the user is not logged in, it shows the login form
      ?>
        <form id="login" action="login" method="post">
          <!-- Message error --> 
          <p class="status"></p> 
          
          <!-- Username --> 
          <label for="username">Username</label>
          <input id="username" type="text" name="username">

          <!-- Password -->
          <label for="password">Password</label>
          <input id="password" type="password" name="password">

          <!-- Link Recover -->
          <a class="lost" href="<?php echo wp_lostpassword_url(); ?>">Lost your password?</a>

          <!-- Submit Button -->
          <input class="submit_button" type="submit" value="Login" name="submit">
          
          <?php wp_nonce_field( 'ajax-login-nonce', 'security' ); ?>
        </form>
      <?php
    } ?>
  </div> 

<?php get_footer(); ?>

<script>
jQuery(document).ready(function($) {
  // Perform AJAX login on form submit
  $('form#login').on('submit', function(e){
      $('form#login p.status').show().text(ajax_login_object.loadingmessage);
      $.ajax({
          type: 'POST',
          dataType: 'json',
          url: ajax_login_object.ajaxurl,
          data: { 
              'action': 'ajaxlogin', //calls wp_ajax_nopriv_ajaxlogin
              'username': $('form#login #username').val(), 
              'password': $('form#login #password').val(), 
              'security': $('form#login #security').val() },
          success: function(data){
              $('form#login p.status').text(data.message);
              if (data.loggedin == true){
                  document.location.href = ajax_login_object.redirecturl;
              }
          }
      });
      e.preventDefault();
  });
});
</script>

My functions.php file
In functions.php I put the functions linked to the form and some redirects useful when doing logine logout.

/* Redirect Custom Login Page */
function redirect_custom_login_page() {
  wp_redirect(site_url() . "/login");
  exit();
}
add_action("wp_logout", "redirect_custom_login_page");


/* Redirect wp-admin & wp-login php */
add_action("init","fn_redirect_wp_admin");
function fn_redirect_wp_admin(){
    global $pagenow;
    if($pagenow=="wp-login.php" && $_GET['action'] !="logout"){
        wp_redirect(site_url()."/login");
        exit();
    }
}

/* Ajax Form Login */
function ajax_login_init(){

    wp_register_script('ajax-login-script', get_template_directory_uri() . '/ajax-login-script.js', array('jquery') ); 
    wp_enqueue_script('ajax-login-script');

    wp_localize_script( 'ajax-login-script', 'ajax_login_object', array( 
         'ajaxurl' => admin_url( 'admin-ajax.php' ),
         'redirecturl' => home_url(),
         'loadingmessage' => __('Sending user info, please wait...')
    ));

    // Enable the user with no privileges to run ajax_login() in AJAX
    add_action( 'wp_ajax_nopriv_ajaxlogin', 'ajax_login' );
}

// Execute the action only if the user isn't logged in
if (!is_user_logged_in()) {
    add_action('init', 'ajax_login_init');
}

function ajax_login(){

    // First check the nonce, if it fails the function will break
    check_ajax_referer( 'ajax-login-nonce', 'security' );

    // Nonce is checked, get the POST data and sign user on
    $info = array();
    $info['user_login'] = $_POST['username'];
    $info['user_password'] = $_POST['password'];
    $info['remember'] = true;

    $user_signon = wp_signon( $info, false );
    if ( is_wp_error($user_signon) ){
        echo json_encode(array('loggedin'=>false, 'message'=>__('Wrong username or password.')));
    } else {
        echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...')));
    }

    die();
}

2

Answers


  1. What you want isn’t achievable using PHP. As quick explanation, PHP is a server side scriptiong language, which means that only the server can execute your code. So whenever you press Login is has to go to the server (doing a request) and then you’ll get back the new HTML from your server.

    How to do this

    Is quite an investment but if you really want to learn or build this you should look into Javascript AJAX requests. In a nutshell, AJAX is how you communicate with your server without any page reload.

    Alternative

    You could also try to use some plugins that try to do this. I have no experience with them but here’s one that claims to do exactly what you want: https://nl.wordpress.org/plugins/login-with-ajax/

    If that one doesn’t fit your needs, you can at least continue searching using the term AJAX.

    I hope this helps 🙂

    TLDR

    With PHP, you can’t. Use an AJAX WordPress plugin or build a custom solution using Javascript and AJAX.

    Login or Signup to reply.
  2. Introduction

    I will briefly describe how HTML forms work, why your page is reloading and how you can communicate with the server without reloading your page, finally, how you can update your page based on this communication.

    How HTML forms work

    When you create a form tag and a structure into it, with a button of submit type inside of it, specifying an action (or using the default), then, upon clicking on the button mentioned earlier, your form is submitted. On submitting your form, all elements inside the form, having a name attribute (i.e. name="somename") is picked up and a request will be sent to the specified action (defaulting to the same page), where the form data will be represented as key-value pairs, the keys being the names of your form elements and the values being the values of the elements.

    Upon form submit, your browser will send a request to the target of the form. The action of the form (if valid) will pick up the request, handle it and respond to your browser.

    When the browser receives this response, it will display it as the content of the page. The users experience this behavior as a page reload. You are bothered with this behavior, as you described in your question and you would prefer to have a less obtrusive, smoother behavior. This is possible with AJAX requests.

    AJAX

    AJAX requests are well-documented, so, if you are unfamiliar with them – which surely is the case -, then I advise to read the content of the link I have given you above and gain some experience with AJAX. If you get stuck with it, let me know your blocker, but, for now, I will assume that the tutorials clarify the matter for you and in a reasonable amount of time you will successfully learn how to tackle them.

    You can also communicate with your server (without page reload) with push notifications or websockets, but since this is a request-response use-case, I strongly advise the use of AJAX. Since AJAX stands for Asynchronous Javascript and XML, the asynchronous part suggests that you are calling an asynchronous function that you do not wait for, that is, your request is being sent to the server and there is an event to handle the server response, upon which you can specify function(s) to be executed, known as the callback(s).

    If you are going to have an AJAX request, then you do not necessarily need the form and the submit button is definitely not needed, instead, you could use an input type="button" with a click event handler that will pick up the data and send the request.

    How to handle server responses

    The simplest way to handle the requests is to just take the (HTML) response and refresh your page content for the regions you want to update (without page reload, of course). But this is not necessarily ideal.

    If your structure does not change, but your content does, then it makes much more sense to change your server code to just send the content as JSON (Javascript Object Notation) and update only the content of your page. This approach ensures that your server does not have to send very large, superfluous responses to your browser if it’s unnecessary. Instead, it just sends the data, reducing the load of your server’s networking and, as a result, making your server more scalable. But this means that your browser will have to update the content itself, which is no longer automatic and you need to code the behavior in a client-side language, such as Javascript.

    How you should proceed

    Since all this is obviously new to you, I advise you to start with the simplest approach, to have some success that will boost your morale, that is, at first stage, send the request as AJAX, the server should only respond with the inner HTML of the body tag, rather than the whole HTML and you could do a

    document.body.innerHTML = response;
    

    in your callback.

    The reasonable expectation is that your page is not reloaded by the browser, but it is refreshed. If you reach this stage, then you might decide that it is good-enough for you, or you can decide to improve it, change the server-side to respond to the AJAX request with a JSON and implement some client-side functions to handle the request and refresh the content.

    I of course advise the latter, but you of course have the liberty of choice here.

    Now, let’s understand what a request method is.

    A GET request is a request defined by a URL (Unified Resource Locator) and the parameters are passed as GET parameters, that is, inside the URL, after the ? mark, like

    https://www.yourpage.com?yourparameter=yourvalue&yoursecondparameter=yoursecondvalue

    A POST request is a request where POST parameters can also be defined. In PHP you have neat ways to determine the request type, see this excellent page: Detecting request type in PHP (GET, POST, PUT or DELETE)

    Now, when you load the page for the first time, a GET request is being send. Once the form is submitted (via AJAX), you need to specify that you are sending a POST request and then the server will know that it will need to send only the data (rather than the HTML) as a response.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search