Front End Login WordPress Plugin – Model View Controller (MVC) – Tutorial – Part One

Pages: 1 2 3

User Login

Time to put some meat on those bones.  To handle front end user login we will use a simple form, implemented with a shortcode.  We could then put this anywhere.  In our case we make a page called “sign-in”, and use a shortcode [ferl_login_form].

View

The shortcode results in the display of a form, so logically it belongs in the View class. We add a method “add_shortcodes()” to the class and call it from “init()”.  We then add the “login_form()” method.

	private function init() {
		add_action('init', array( $this, 'register_css' ) );
		add_action('wp_footer', array( $this, 'print_css' ) );
		$this->add_shortcodes();
	}

	private function add_shortcodes() {
		add_shortcode('ferl_login_form', array( $this,'login_form' ) );
	}

	public function login_form() {
		$this->load_css = true;
		$output = '';
		if(!is_user_logged_in()) {
			// set this to true so the CSS is loaded
			$this->load_css = true;
			$output = $this->login_form_view();
		} else {
			// show some logged in user info here and offer to logout
			$current_user = wp_get_current_user();
			$output = $this->logout_form_view($current_user);
		}
		return $output;
	}

Note that on line 17 and line 21 methods are called which produce the HTML for display.  Let’s take a look at login_form_view() first.

Notice the output buffer handling with ob_start() and ob_get_clean().  Also, the show_info_messages() and show_error_messages() before the form.  The form itself is pretty standard.  In the hidden fields we put the WordPress nonce, and the action parameters.  The logout_form_view() is simpler still.

<?php
  .....
	private function logout_form_view($current_user) {
		ob_start();
		?>

        You are currently signed in as "<span style="color:#0A0"><?= $current_user->user_login ?></span>"

		<form id="ferl_logout_form"  class="ferl_form" action="" method="post">
        	<fieldset>
                <input type="hidden" name="ferl_action" value="logout" />
                <input type="hidden" name="ferl_logout_nonce" value="<?php echo wp_create_nonce('ferl-logout-nonce'); ?>"/>
                <div>
                <input id="ferl_logout_submit" type="submit" value="Logout"/>
                </div>
        	</fieldset>
        </form>

		<?php
		return ob_get_clean();
	}

This is all we need in View to handle the user login.  When we navigate to the “Sign In” page, this is what we see:

login-form

login form

 

Controller

On submit, the browser sends  a POST request to the server.  Time for the Controller to spring into action.

<?php
  .....
	private function init() {
		/* pass request parameters to the model */
		$this->model->set_request_params($this->post_array, $this->get_array);

		/* handle the form posts */
		if (isset($this->post_array['ferl_action'])):
		switch ($this->post_array['ferl_action']):
			case "login":
				add_action( 'init', array( $this->model, 'login_user' ) );
			break;

			case "logout":
				add_action( 'init', array( $this->model, 'logout_user' ) );
			break;
		endswitch;
		endif; // $ferl_action
	}

The magic happens in lines 11 and 15, where the Model methods login_user() and logout_user() are setup to be executed.

Model

Time to look at the Model class.  So far our Model class is pretty empty.  It only has a constructor.  First we add some stubs to satisfy the requirements of the View class.  Then we add the login_user method stub. With those stubs in place, we can “submit” our login form, and no PHP errors or warnings will be generated.

<?php
namespace drmagu\front_end_registration_login;

class Model {
	private $post_array = array();
	private $get_array = array();

	public function __construct() {

	}

	/** allow the request data to be set **/
	public function set_request_params($post_array, $get_array) {
		$this->post_array = $post_array;
		$this->get_array = $get_array;
	}

	/** methods required by the View class **/
	public function get_error_codes() {
		return array();
	}

	public function get_info_codes() {
		return array();
	}

	public function get_error_message( $code ) {
		return "";
	}

	public function get_info_message( $code ) {
		return "";
	}

	public function get_username( ) {
		return "";
	}

	/** methods to handle form submissions **/
	public function login_user() {

	}
}

Model is where the heavy lifting takes place, aka the “Business Logic”.  The “Business” in this case is the WordPress environment.  We will start with the login_user() method.

It should be obvious that this method needs information from the submitted form.  This information is known to the controller, in the $controller->post_array.  It is also in the global $_POST variable, of course, but we will try to minimize our dependence on the use of global variables to pass information around.  So we created a method in Model set_request_params(), and allow the Controller to set those see above: line 5 in Controller  and lines 13-16 in Model.

The login_user method will check the entered data against the WordPress database.

A number of “errors”need to be checked for and reported back, such as empty username, empty password, wrong password etc.  To do this, we leverage the WordPress WP_Error class.  The constructor is augmented, and we need to allow WP_Error to be recognized by using the “use \WP_Error” statement at the top of the file.  We now can also “flesh out” the Model’s error reporting methods.

<?php
namespace drmagu\front_end_registration_login;
use \WP_Error;

class Model {
	private $wp_error;
	private $wp_info;
	private $post_array = array();
	private $get_array = array();

	public function __construct() {
		$this->wp_error = new WP_Error(null, null, null);
		$this->wp_info = new WP_Error(null, null, null);
	}

	/** allow the request data to be set **/
	public function set_request_params($post_array, $get_array) {
		$this->post_array = $post_array;
		$this->get_array = $get_array;
	}

	/** methods required by the View class **/
	public function get_error_codes() {
		return $this->wp_error->get_error_codes();
	}

	public function get_info_codes() {
		return $this->wp_info->get_error_codes();
	}

	public function get_error_message( $code ) {
		return $this->wp_error->get_error_message( $code );
	}

	public function get_info_message( $code ) {
		return $this->wp_info->get_error_message( $code );
	}
  .....

The login_user() method is listed below.

Notice the use of the wp_error_add() method in lines 11, 15, 21 and 27.  Line 37 allows for the setting of a redirect target on successful login.  In our example, we just go back to the “Sign In” page which will then display the “logout form”.

Here is the login form with an invalid password.

login bad password

When logged in, the “Sign In” page displays this.

 

logout

The logout_user() method is exceedingly simple.

	public function logout_user() {
		wp_logout();
	}

Upon logout, the user is redirected to the home page because of the LimitAdminAccess class (see higher).

MVC Login/Logout Done

And we now have a functional MVC implementation of Front End Login for WordPress.

In Part Two of this article, I will show how to extend this MVC plugin to handle Front End Registration, a Change Password form, and a “Oops I forgot my Password” handler.

Pages: 1 2 3

Leave a Reply

You must be logged in to post a comment.