users controller


Everything's set up then. Now, let's create a database table named users with some columns defined.

DATABASE TABLE

CREATE TABLE users(
id integer unsigned PRIMARY KEY AUTO_INCREMENT,
username varchar(255) not null,    
email varchar(255) UNIQUE not null,
password varchar(255),
usertype ENUM('user','admin'),
uploads varchar(255),
status tinyint DEFAULT 0,
created_at timestamp
);	

PARENT CONTROLLER

The database table has been created and we are good to create required forms and their controllers but right before that let's create one parent controller that refactors the methods defined in database model. Let's name it model itself.

<?php
abstract class Model
{

	protected $table, $key, $field, $limit, $offset;
	private $_db;

	protected function __construct()
	{		
		$this->_db = Database::instantiate();
	}

	protected function save($data=array(),$key=null){
		
		if(empty($data)) throw new Exception("Columns and Values not set");

		if(!isset($key)){
			return $this->_db->insert($this->table,$data);	
		}

		return $this->_db->update($this->table,$data,$this->key.'=?',array($key));	
	}

	protected function get($id=""){
		
		if(empty($id)){
			
			if(!empty($this->limit)){
				return $this->_db->select($this->table,$this->field,'',array(),'LIMIT '.$this->limit.' OFFSET ' . $this->offset );	
			}
			return $this->_db->select($this->table,$this->field);
		}

		$result = $this->_db->select($this->table,$this->field,$this->key.'=?',array($id));
		
		if(count($result)){
			return $result[0];
		}
		return false;
	}

	protected function delete($id){
		return $this->_db->delete($this->table,$this->key.' = ?',array($id));
	}

	protected function multipleDelete($data){
		
		if(empty($data)) return false;
		$data = implode(',',$data);
		return $this->_db->delete($this->table,$this->key.' IN ('.$data.')');
	}

	protected function countRow(){
		return $this->_db->count($this->table);
	}

	public function getBy($criteria,$value=array(),$single=false){
		
		if(empty($criteria)) return false;

		$result = $this->_db->select($this->table,$this->field,$criteria,$value);

		if(empty($result)) return $result;
		
		if($single === true){
			return $result[0];
		}
		return $result;
	}
}	

We created all the variables that we need to work on the database here with default value null. We're manipulating the SQL queries from database here according to our need and making the work in controller files much easier. We instantiated the database connection also. Now, what we'll do is create child classes to this model class and continue out work there. But, before that let's create a form to add user.

FORM

Here's a basic form to add user details to the database.

<form method="POST" enctype="multipart/form-data"> <div class="col-sm-12"> <?= Validation::displayErrors('validationErrors'); ?> <?= displayMessage(); ?> </div> <div class="col-sm-6 form-group"> <?=token::input();?> <label>Username</label> <input type="text" name="username" class="form-control"> </div> <div class="col-sm-6 form-group"> <label>Email</label> <input type="email" name="email" class="form-control"> </div> <div class="col-sm-6 form-group"> <label>Password</label> <input type="password" name="password" class="form-control"> </div> <div class="col-sm-6 form-group"> <label>Confirm Password</label> <input type="password" name="cpassword" class="form-control"> </div> <div class="col-sm-6 form-group"> <label>User Type</label> <select name="usertype" class="form-control"> <option value="user">user</option> <option value="admin">admin</option> </select> </div> <div class="col-sm-6 form-group"> <label>Profile Picture</label> <input type="file" name="uploads" class="btn btn-default"> </div> <div class="col-sm-6 form-group"> <button type="submit" class="btn btn-success"><i class="fa fa-user-plus"></i> Register</button> </div> </form>

So, the form is created along with the csrf_token value added and validation errors and session messages already added. Now, we'll create a controller and call it on top of this file. Let's name that file User.php.

<?php
class User extends Model
{
	protected $table = "users";
	protected $key = "id";
	protected $field = "*";
	private $_validation = null;

	protected $validationRules = [
		'username' => [
			'required' => true,
			'minlength' => 3,
			'maxlength' => 20,
			'label' => 'Username', 
		],
		'email' => [
			'required' => true,
			'email' => true,
			'unique' => 'users.email',
			'label' => 'Email',
		],
		'password' => [
			'required' => true,
			'minlength' => 6,
			'label' => 'Password',
		],
		'cpassword' => [
			'required' => true,
			'matches' => 'password',
			'label' => 'Confirm Password',
		],
		'usertype' => [
			'required' => true,
			'label' => 'User Type',
		]
	];

	public function __construct()
	{	
		parent::__construct();
		$this->_validation = new Validation();
	}

	public function addUser()
	{
		$data['username'] = Request::post('username');
		$data['email'] = Request::post('email');
		$data['password'] = hash::make(Request::post('password'));
		$data['usertype'] = Request::post('usertype');
		
		try{
			$this->_validation->validate($this->validationRules);
			
			if($this->_validation->isValid()){
			
				$configs['upload_size'] = 2000000;
				$configs['upload_ext'] = 'jpg|jpeg|png|gif';
				$configs['upload_path'] = ROOT.'admin/Upload/Users/';
			
				Upload::initialize($configs);
			
				$filename = Upload::load($_FILES['uploads']);
			
				if($filename){
			
					$data['uploads'] = $filename;

					if($this->save($data)){
						session::put('success','User Created Successfully');
						return Redirect::to('admin/add-user');
					}
				}else{
					session::put('validationErrors',Upload::getErrors());
					return Redirect::to('admin/add-user/');
				}
			}else{
				session::put('validationErrors',$this->_validation->getErrors());
				return Redirect::to('admin/add-user/');
			}
		}catch(Exception $e){
			die($e->getMessage());
		}
	}	
}		

Here, we defined the tablename, primary key, columnname and validation rules. Instantiated the database using __construct from parent class and instantiated validation class as well. The data will be saved if everything goes right and the success message will be displayed. Since we have no other view files, we are redirecting the user to the same file as of now. It can be changed to the file having table displaying users later. The next case would possibly be upload error, that too, we've saved in upload validation errors. The other ones would be the form validation errors. In case of error in SQL query, the PDO exception will be displayed. All these block of codes will run only after this class is instantiated in the view file so we'll add the codes displayed below on top of the add-user.php i.e. the add user form file.

<?php 
if (Request::method() && token::check(Request::post('csrf_token'))){
	$obj = new User();	
	$obj -> addUser();
}
?>	

Here, the form values will be sent for further processing only in the case where the request method is post and csrf_token value sent from the form matches the value stored in session.

DISPLAY USER

Now, it's the turn to display registered users but before that let's create a method for the same in user.php.

public function getUser($id=""){
	return $this->get($id);
}	

If the parameter remains empty, all the data from the table will be returned and that's what we need. Just add these block of codes on top to call the specific method to retrieve all data.

<?php 
$obj = new User();	
$users = $obj->getUser();
?>

Here's an example of a display table.

<div class="col-sm-12">
	<?= displayMessage(); ?>
	<table class="table table-bordered table-striped table-hover">
		<thead>
			<tr>
				<th width="5%">S.N.</th>
				<th width="30%">Username</th>
				<th width="30%">Email</th>
				<th width="15%">Image</th>
				<th width="10%">Status</th>
				<th width="10%">Action</th>
			</tr>
		</thead>
		<tbody>
			<?php
			if(empty($users)){ ?>
			<td colspan="6">No Data Found <a href="main.php?page=addUser">Add Users</a></td>
			<?php }else{ ?>
			<?php foreach($users as $key => $user): ?>	
				<tr>
					<td><?= ++$key ?></td>
					<td><?= ucfirst($user->username)?></td>
					<td><?=$user->email?></td>
					<td><img src="<?=HTTP.'admin/Upload/Users/'.$user->uploads?>" width="40" height="40"></td>
					<td><?=$user->status?></td>
					<td>						
						<a href="#" class="btn btn-sm btn-danger"><i class="fa fa-trash"></i> Delete</a> 
					</td>
				</tr>
			<?php endforeach; ?>	
			<?php } ?>
		</tbody>
	</table>
</div>	

Now, the data will be displayed in the table but it'd be much convenient if we could change the user status from the display table rather than going to the update page. For that, we need to place a form in the column that displays the status of users instead of printing the value. Let's do it first then.

<td>
	<form method="post">
		
		<input type="hidden" name="_id" value="<?=$user->id?>">
		
		<?php if($user->status == 0): ?>
			<button type="submit" name="enable" class="btn btn-sm btn-primary">Enable</button>
		<?php else: ?>
			<button type="submit" name="disable" class="btn btn-sm btn-danger">Disable</button>	
		<?php endif; ?>
	
	</form>
</td>	

For that we sent the users id along with the status value and the button value. Now, add a new method in user controller file.

public function updateUserStatus(){
	
	$id = (int)Request::post('_id');
	
	if(empty($id)) return false;

	if(isset($_POST['disable'])){
		$data['status'] = 0;
		$message = 'User was disabled';
	}

	if(isset($_POST['enable'])){
		$data['status'] = 1;	
		$message = 'User was enabled';
	}

	if($this->save($data,$id)){
		session::put('success',$message);
		return Redirect::to('admin/users');
	}
}	

If the disable button is clicked user will be disabled and vice-versa. Finally, the data will be sent to save function in Model along with the id and that'll activate the SQL to update data, hence, the data will be updated and the user redirected to the same page with success message. We need to call this method on top of the view page below the user class instance as shown below.

<?php 
$obj = new User();	
$users = $obj->getUser();

if(Request::method()){
	$obj->updateUserStatus();
}
?>	

We'll also add a link to delete the users form here but beore that we'll need a page that handles all the delete requests.

DELETE PAGE

<?php
require_once('../Configs.php');
require_once('Autoload/Autoload.php');

if(!empty(Request::get('u_id'))){
	$user = new User();
	$user->deleteUser();
}else{
	echo 'Id not set';
}

We'll require the main controller classes in this page to get connected to the database and include needed files. The delete request will be sent via get method so we need to define the action when the data id is not sent as well. I the id is sent then we'll instantiate the class as defined and process the defined method. To delete a user, we'll create a method in the user controller file named deleteUser() that is called in this file.

DELETE USER IMAGE

While deleting a user, we'll also delete the image stored in their database. So, let's add the link in display file to delete user.

<a href="delete.php?u_id=<?=$user->id?>" onclick="return confirm('Are you sure?')" class="btn btn-sm btn-danger"><i class="fa fa-trash"></i> Delete</a> 	

We can delete the user from data database connecting the database with delete function in the model but that won't delete the uer's image stored in some directory. So, let's process that one first.

private function deleteAssociate($id){

	if(empty($id)) return false;

		$user = $this->getUser($id);
		$img_name = $user->uploads;
		$img_path = ROOT.'admin/Upload/Users/'.$img_name;		

		return unlink($img_path);
}	

We'll retrieve the user's data using getUser() method that we created earlier. Then store it's image name and the path or the image in variables and run the unbuilt funtion unlink() to delete it and return the path value. Now, we can delete the user. For that, we'll create another method in user controller file that uses this deleteAssociate() method while deleting the user.

public function deleteUser()
{
	$id = (int)Request::get('u_id');
	if(empty($id)) return false;

	if ($this->deleteAssociate($id) && $this->delete($id)){
		session::put('success','User was deleted.');
		return Redirect::to('admin/displayuser/');
	}else{
		session::put('error','Unable to delete user');
		return Redirect::to('admin/displayuser/');
	}
}	

We retrieved the id and sent it to another funtion that deletes the image and then went on to delete the information from database. Finally, we stored message in session and redirected the user.