API Project - Part 7 - Login Controller
Login Controller
In this step, we'll be using sessions and cookies, so you should have read chapter 12 by now.
Look at the routes we defined (in index.php) and notice there are two that use a LoginController, which we'll create right now.
Add a file named LoginController.inc.php class in the controllers folder and add this code to it:
<?php
include_once("Controller.inc.php");
include_once(__DIR__ . "/../models/User.inc.php");
include_once(__DIR__ . "/../dataaccess/UserDataAccess.inc.php");
class LoginController extends Controller{
function __construct($link){
parent::__construct($link);
}
public function handleLogin(){
$da = new UserDataAccess($this->link);
switch($_SERVER['REQUEST_METHOD']){
case "POST":
$data = $this->getJSONRequestBody();
//print_r($data);die(); // this just shows you the data that was sent in the POST request
// TODO: add code to handle POST request here
case "OPTIONS":
// AJAX CALLS WILL OFTEN SEND AN OPTIONS REQUEST BEFORE A PUT OR DELETE
// TO SEE IF THE PUT/DELETE WILL BE ALLOWED
header("Access-Control-Allow-Methods: POST");
$this->sendStatusHeader(200);
die();
break;
default:
// set a 400 header (invalid request)
$this->sendStatusHeader(400);
die();
}
}
public function handleLogout(){
// destroy the session cookie
if (isset( $_COOKIE[session_name()])){
setcookie( session_name(), "", time()-3600, "/" );
}
//empty the $_SESSION array
$_SESSION = array();
//destroy the session on the server
session_destroy();
$this->sendStatusHeader(200);
}
}
Note that session_start() is called in the config file, which creates a session on the server and allows us to use the $_SESSION super global array.
PHP uses cookies to keep track of a user's session id, but I learned (the hard way) that some types of AJAX calls don't include cookies in the headers. This will complicate things for us. So we'll send the session id in our own custom header.
Open a browser and navigate to localhost/api/login (You should get a 400 error coming from the handleLogin() method of the Login controller because it does not respond to GET requests).
Note that the LoginController instantiates a UserDataAccess object, which can now authenticate users.
In the LoginController class, replace the TODO comment with this code:
try{
if($user = $da->login($data['email'], $data['password'])){
// encode the user obj to json string
$json = json_encode($user);
// create a new session id (this is recommended whenever a user logs in)
session_regenerate_id();
// OPTIONAL: send the session id in the x-id header
// set some session variables for the user who has just logged in
$_SESSION['authenticated'] = "yes";
$_SESSION['user_id'] = $user->id;
$_SESSION['user_first_name'] = $user->firstName;
$_SESSION['user_role_id'] = $user->roleId;
$this->setContentType("json");
$this->sendStatusHeader(200);
echo($json);
die();
}else{
$this->sendStatusHeader(401, "Invalid login or password");
die();
}
}catch(Exception $e){
$this->sendStatusHeader(400, $e->getMessage());
die();
}
This code is wrapped in a Try/Catch block because our data access class will throw an exception if a SQL query fails.
To try out the login functionality, load this test page in the browser: http://localhost/api/tests/LoginControllerTests.html Make sure to look that the request and response information in the Network tab of the browsers developer tools. You should set a Set-Cookie header sent in the response when you login. It should contain the PHPSESSID cookie which is set to the ID of the session.
Once the cookie is set by the server, the browser should include a Cookie header for each subsquent request to the server. You can look for it in the request headers by clicking the Log Out button.