In this section, we'll look at having the following output displayed on our screen:
Follow these steps to build CRUD for user management:
app/Models/User.php.
get_users() – returns all users ordered by username $data = $this->db->select('username from users where username = :username', [':username' => $username]); return (isset($data[0]->username) ? $data[0]->username : null); }
Users
Controller in app/Controllers.
Create Users.php.
User
Model:use SystemBaseController; use AppHelpersSession; use AppHelpersUrl; use AppModelsUser; class Users extends BaseController {
$user
and a __construct
method. Then, check if the user is logged in, and if not, redirect them to the login page.$this->user = new User()
protected $user; public function __construct() { parent::__construct(); if (! Session::get('logged_in')) { Url::redirect('/admin/login'); } $this->user = new User(); }
index
method. This will call get_users()
and load a view and pass in the users object:public function index() { $users = $this->user->get_users(); $title = 'Users'; $this->view->render('admin/users/index', compact('users', 'title')); }
app/views/admin/users/index.php.
foreach($users as $user)
htmlentities().
This converts all tags into their HTML counterparts, meaning if any code had been injected into the database, it would simply be printed as text, making it useless:<?php include(APPDIR.'views/layouts/header.php'); include(APPDIR.'views/layouts/nav.php'); …… </table> </div> <?php include(APPDIR.'views/layouts/footer.php');?>
href
value. This is to pass the ID to the URL.Add User
button that points to /users/add.
Let's create this. In your Users
Controller, create a new method called add():
public function add() { $errors = []; $title = 'Add User'; $this->view->render('admin/users/add', compact('errors', 'title')); }
app/views/admin/users
called add.php.
post
.username
, email
, password,
and confirm password
. Make sure each input has a name.(isset($_POST['username']) ? $_POST['username'] : '')
This says if the $_POST['username']
is set, then print it, otherwise print an empty string:
<?php include(APPDIR.'views/layouts/header.php'); include(APPDIR.'views/layouts/nav.php'); include(APPDIR.'views/layouts/errors.php'); …….. </form> <?php include(APPDIR.'views/layouts/footer.php');?>
/users/add
. This needs handling in the add
method of the Users
Controller.if (isset($_POST['submit'])) {
$username = (isset($_POST['username']) ? $_POST['username'] : null); $email = (isset($_POST['email']) ? $_POST['email'] : null); $password = (isset($_POST['password']) ? $_POST['password'] : null); $password_confirm = (isset($_POST['password_confirm']) ? $_POST['password_confirm'] : null);
username
is more than 3 characters in length:if (strlen($username) < 3) { $errors[] = 'Username is too short'; }
$username
exists already in the database by passing $username
to a get_user_username($username)
method on the Model. If the results are the same as $username,
then it already exists, so create an error:else { if ($username == $this->user->get_user_username($username)){ $errors[] = 'Username address is already in use'; } }
filter_var
and FILTER_VALIDATE_EMAIL.
If this does not return true, create an error.username,
check if the $email
exists in the database already:if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] = 'Please enter a valid email address'; } else { if ($email == $this->user->get_user_email($email)){ $errors[] = 'Email address is already in use'; } }
$password
matches $password_confirm
or creates an error. Otherwise, check that the password is more than 3 characters in length:if ($password != $password_confirm) { $errors[] = 'Passwords do not match'; } elseif (strlen($password) < 3) { $errors[] = 'Password is too short'; }
$data array
containing the data to be inserted into the database.$this->insert($data)
and set a message before redirecting back to /users:if (count($errors) == 0) { $data = [ 'username' => $username, 'email' => $email, 'password' => password_hash($password, PASSWORD_BCRYPT) ]; $this->user->insert($data); Session::set('success', 'User created'); Url::redirect('/users'); }
The full method looks like this:
public function add() { $errors = []; ……. $title = 'Add User'; $this->view->render('admin/users/add', compact('errors', 'title')); }
/users/edit/1.
The number at the end is the ID of the user.edit($id)
that accepts a parameter called $id.
$id
is a number, otherwise redirect back to /users
.$this>user->get_user($id)
and pass in the ID to the users
Model method. This will return a user
object or null
if the record is not found.$user
is equal to null,
redirect to a 404
page. Otherwise, set up an $errors
array, $title,
and load the view, passing in user, errors, and title to compact():
public function edit($id) { if (! is_numeric($id)) { Url::redirect('/users'); } $user = $this->user->get_user($id); if ($user == null) { Url::redirect('/404'); } $errors = []; $title = 'Edit User'; $this->view->render('admin/users/edit', compact('user', 'errors', 'title')); }
app/views/admin/users
called edit.php
:This is almost identical to the add.php
view. The main difference is in the username and email inputs. They are pre-populated with the user object:
<input class="form-control" id="username" type="text" name="username" value="<?=$user->username;?>" required />
The <?=$user->username;?>
is the user object in action using ->
after $user.
You specify what column you want out of it.
It's important that you do not pre-populate the password fields; they should only be filled in when the user wants to change the password. As such, put a message to inform the user that they should enter the password only if they want to change their existing password:
For full code snippet, refer to Lesson 7.php
file in the code files folder.
<?php include(APPDIR.'views/layouts/header.php'); include(APPDIR.'views/layouts/nav.php'); include(APPDIR.'views/layouts/errors.php'); …… </form> <?php include(APPDIR.'views/layouts/footer.php');?>
add()
method, check for the form submission, collect the form data, and perfect the form validation.if (isset($_POST['submit'])) { $username = (isset($_POST['username']) ? $_POST['username'] : null); …… $errors[] = 'Password is too short'; } }
if (count($errors) == 0) {
$data
array to update the user's record. This time, only the username and email are provided:$data = [ 'username' => $username, 'email' => $email ];
$data
array:if ($password != null) { $data['password'] = password_hash($password, PASSWORD_BCRYPT); }
$id
. Run the update()
and set a message and redirect to the users page:$where = ['id' => $id]; $this->user->update($data, $where); Session::set('success', 'User updated'); Url::redirect('/users');
The full update
method looks like this:
public function edit($id) { if (! is_numeric($id)) { …… } $title = 'Edit User'; $this->view->render('admin/users/edit', compact('user', 'errors', 'title')); }
$id
as part of the URL in the format of /users/delete/2.
delete($id).
$id
is numeric and check if the $id
matches the session $_SESSION['user_id'],
otherwise kill the page. You don't want to allow a user to delete their own record.$this->user->get_user($id)
and check if the $user
object is not equal to null.
Otherwise, redirect to a 404
page.$where
array that says where the $id
matches the ID in the database. Note we do not use a $data
array. In this case, we only pass a $where
. This is because you cannot select columns, only a row, so the $data
would be pointless./users:
public function delete($id) { if (! is_numeric($id)) { Url::redirect('/users'); } if (Session::get('user_id') == $id) { die('You cannot delete yourself.'); } $user = $this->user->get_user($id); if ($user == null) { Url::redirect('/404'); } $where = ['id' => $user->id]; $this->user->delete($where); Session::set('success', 'User deleted'); Url::redirect('/users'); }
php –S localhost:8000 –t webroot
http://localhost:8000/users,
click on Add User
, and
fill in the form./users
and see the new user, along with a confirmation message.Edit
next to the user you want to edit. You will then be presented with the edit form with the username and email filled in. Pressing submit will take you back to the users page.delete
will delete the user right away (providing the user is not you) with no confirmation. Let's fix that!delete
, a confirmation window should be displayed. If OK is clicked, then the delete URL will be called, and if cancel is clicked, nothing will happen.app/views/admin/users/index.php
and place this JavaScript before the footer.php
code block:<script language="JavaScript" type="text/javascript"> function del(id, title) { if (confirm("Are you sure you want to delete '" + title + "'?")) { window.location.href = '/users/delete/' + id; } } </script>
username.
When the confirm()
passes a window.location.href,
it will run, redirecting the page to the delete URL before passing in the ID var
to the end of the URL.<a href="/users/delete/<?=$row->id;?>" class="btn btn-xs btn-danger">Delete</a>
Replace it with:
<a href="javascript:del('<?=$row->id;?>','<?=$row->username;?>')" class="btn btn-xs btn-danger">Delete</a>
This calls javascript:del(),
which triggers the confirmation popup and passes in the user's ID
and username
.
Method
and Controller
and ensure that the database table is ready to accept them.index
view, the student can select information of their choosing to help identify the user in the table.