Design Patterns, MVC

How does the PHP MVC works?

The MVC pattern is a software architecture that separates an application into three main logical components: the model, the view, and the controller. Each of these components are built to handle specific development aspects of an application.
MVC is one of the most frequently used industry-standard web development framework to create scalable and extensible projects.
MVC pattern isolates the application logic from the user interface layer and supports separation of concerns.
Here are the components of MVC pattern:

MVC

Why do we need to implement a PHP MVC?

Implementing MVC in PHP offers several advantages for web development:

Here is an example of a PHP MVC.

Creating the Directory Structure

The first step in creating an MVC application is to create the directory structure. The directory structure is the same for all MVC applications. The directory structure is shown in the following image.

MVC_Folder_Structure

The Public folder

The public folder contains the static file that can be seen by the user. The public folder contains the following files and directories.

PHP

<?php
#
Options -MultiViews
RewriteEngine On
RewriteBase /HERAFY/public
# Accept loading of actual -f files and -d directories
# It means that if the user type a valid file name or a valid directory name ==> just open it
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# If the user type a non-valid file name or a non-valid directory name
# Send everything else to the index page
# and save the rest in url
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
# Except for these
# RewriteCond $1 !^(config|core|css|js|robots\.txt)

?>

Result

.htaccess:

Htaccess is short for Hypertext Access. It is a configuration file used by Apache-based web servers.

Configuration files configure the initial settings of a program or, in this case, the server. This means that the .htaccess file can be used to make the server behave in a certain way. Each function is just a line of text, or code, which tells the server what to do. You can add or change functionality by adding or changing the code in the .htaccess file.

You can find more information on how to use an .htaccess file here.

PHP

<?php
require_once("../app/core/init.php");
$app = new \app\core\App;

?>

Result

index.php:

The index.php file is the entry point of the application. It loads the init.php file and creates an instance of the App class.

PHP

<?php
User-agent : *
Disallow: /admin/
Disallow: /ajax/

?>

Result

robot.txt:

The robot.txt file is used to tell the search engines which pages to index and which pages not to index.
User-agent does not allow the search engines to index the pages in the admin and ajax directories.
You can find more information on how to use a robot.txt file here.

assets:

The assets folder contains the CSS, JavaScript, and image files.
The CSS folder contains the CSS files.
The JavaScript folder contains the JavaScript files.
The images folder contains the image files.

Public_Folder

The App folder

The app folder contains the application code. The app folder contains the following files and directories.

App_Folder

Creating the PHP Router

The next step in creating an MVC application is to create the PHP router. The PHP router is used to route the requests to the appropriate controller.
The PHP router is created in the index.php file or as a separate class then called from index.php.

PHP

<?php
class App
{
//Default class, method and parameters
protected $controller = 'Home';
protected $method = 'index';
protected $params = [];
// A function that loads the controller when an App is instanciated in index.php ---> $app = new App;
public function __construct()
{
$url = $this->parseUrl();
if (isset($url[0])) {
//concatenation to get the full path and check if the controller exists
// which is in $url[0]
if (file_exists('../app/controllers/' . ucfirst($url[0]) . '.php')) {
//Replace with a new instance of this->controller
$this->controller = ucfirst($url[0]);
// remove it from the array
unset($url[0]);
} else {
//if there is no page then route to 404 error
//require ('../app/controllers/_404.php');
$this->controller = "_404";
}
}
require_once('../app/controllers/' . $this->controller . '.php');
$this->controller = new $this->controller;
//check if the method exists
if (isset($url[1])) {
if (method_exists($this->controller, $url[1])) {
$this->method = $url[1];
unset($url[1]);
}
}
//check if the array exists else return empty array
$this->params = $url ? array_values($url) : [];
// The next line will call a function specified by $this->method
// which is in the class $this->controller
// and give it a set of parameters specified by$this->params
call_user_func_array([$this->controller, $this->method], $this->params);
}
public function parseUrl()
{
//It will split the url using explode with / as parameter
if (isset($_GET['url'])) {
return $url = explode('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));
}
}
}
?>

Result

App.php:

The App class is used to route the requests to the appropriate controller. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The App class will route the request to the Home controller, the index method, and the 1 parameter.

The App class has the following properties.
controller: The controller name. For example, Home or About.
method: The method name. For example, index or show.
params: The parameters. For example, 1 or 2.

The App class has the following methods.

parseUrl: The parseUrl method is used to parse the URL. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The parseUrl method will return the following array.
Array ( [0] => home [1] => index [2] => 1 )

rtrim: The rtrim method is used to remove the trailing slash from the URL. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1/
The rtrim method will return the following URL.
http://localhost/HERAFY/public/home/index/1

filter_var: The filter_var method is used to filter the URL. The FILTER_SANITIZE_URL filter removes all illegal URL characters from a string.
explode: The explode method is used to split the URL into an array. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The explode method will return the following array.
Array ( [0] => home [1] => index [2] => 1 )

isset: The isset method is used to check if the URL is set. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The isset method will return true.

__construct: The constructor method.

ucfirst: The ucfirst method is used to convert the first character of the string to uppercase. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The ucfirst method will return the following string.
Home

file_exists: The file_exists method is used to check if the controller exists. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The file_exists method will check if the Home controller exists.

unset: The unset method is used to remove the controller from the array. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The unset method will remove the Home controller from the array.

require_once: The require_once method is used to load the controller. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The require_once method will load the Home controller.

method_exists: The method_exists method is used to check if the method exists. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/show/1
The method_exists method will check if the show method exists in the Home controller.
array_values: The array_values method is used to return all the values of an array. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/show/1
The array_values method will return the following array.
Array ( [0] => 1 )

call_user_func_array: The call_user_func_array method is used to call the method of the controller. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The call_user_func_array method will call the index method of the Home controller.

Creating the PHP Controller

The next step in creating an MVC application is to create the PHP controller. The PHP controller is used to handle the requests and load the views.
The PHP controller is created in the app/controllers folder.

The PHP controller has the following methods.
view: The view method is used to load the view.
model: The model method is used to load the model.

PHP

<?php
require_once('config.php');
class Controller
{
public function view($view, $My_Data = [])
{
if (!empty($My_Data)) {
extract($My_Data);
}
$FilePath = '../app/views/' . $view . '.view.php';
require_once($FilePath);
}
public function model($model)
{
$FilePath = './models/' . $model . '.php';
if (file_exists($FilePath)) {
require_once('./models/' . $model . '.php');
return new $model();
} else {
//if there is no page then route to 404 error
require('../app/views/404.view.php');
}
}
}
?>

Result

Controller.php:

The Controller class is used to handle the requests and load the views.

The Controller class has the following methods.

view: The view method is used to create the path to the view. It takes two parameters. The first parameter is the view name. The second parameter is the data that will be passed to the view. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The view method will load the Home view.

model: The model method is used to create the path to the model. It takes one parameter. The parameter is the model name. For example, if the user types the following URL in the browser.
http://localhost/HERAFY/public/home/index/1
The model method will load the Home model.

The Controller class is extended by all the controllers.
These controllers are in the app/controllers folder.
For example, the Home controller is in the app/controllers/Home.php file.
The Home controller extends the Controller class.

Controllers

PHP

<?php
// This is a controller
class Contact_Us extends app\core\Controller
{
public function index()
{
$this->view('Contact_Us');
}
}
?>

Result

Contact_Us.php:

The Contact_Us controller is used to handle the requests and load the views.
The Contact_Us controller extends the Controller class.
The Contact_Us controller has the following methods.
index: The index method is used to load the Contact_Us view.

PHP

<?php
// This is a controller
class _404 extends \app\core\Controller
{
public function index()
{
$this->view('404');
}
}
?>

Result

_404.php:

_404.php starts with an underscore because class names cannot start with a number.
The _404 controller is used to handle the requests and load the views.
The _404 controller extends the Controller class.
The _404 controller has the following methods.
index: The index method is used to load the 404 view.

Creating the Views

The app/views folder contains the view files. The view files are used to display the data.
For example, the Home view is in the app/views/Home.view.php file.
These are what the user sees when they visit the website.
They are requasted by the controller and then displayed to the user.
To summerize, the user type the URL in the browser, the URL is routed to the appropriate controller, the controller loads the view, and the view is displayed to the user.

PHP

<?php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Error 404</title>
</head>
<body>
<h1>Error 400004</h1>
</body>
</html>
?>

Result

The 404 view is used to display the 404 error.
The 404 view is in the app/views/404.view.php file.

Views

Creating the Models

The Model.php file is used to connect to the database.
The Model.php file is in the app/core/Model.php file.
The Model.php file has the following methods.
Execute_Querry: The Execute_Querry method is used to execute the querry.
Connect_To_DataBase: The Connect_To_DataBase method is used to connect to the database.
Disconnect_From_DataBase: The Disconnect_From_DataBase method is used to disconnect from the database.

PHP

<?php
trait Model
{
use DataBase_Connection;
// Tnside the trait Model we have to define the CRUD methods
// CRUD = Create, Read, Update, Delete
// This way we can use these methods just by providing the table name and data
// $My_Table = table name
public $My_Table;
public $My_Errors = [];
public function Single_Result($My_Data)
{
$keys = array_keys($My_Data);
$My_Querry = "select * from $this->My_Table where ";
foreach ($keys as $key) {
$My_Querry .= $key . " = :" . $key . " && ";
}
$My_Querry = trim($My_Querry, " && ");
print_r($My_Querry);
$My_Results = $this->Execute_Querry($My_Querry, $My_Data);
if ($My_Results) {
return $My_Results[0];
} else {
return false;
}
}
public function Search_For($My_Data)
{
$keys = array_keys($My_Data);
$My_Querry = "select * from $this->My_Table where ";
foreach ($keys as $key) {
$My_Querry .= $key . " = :" . $key . " && ";
}
$My_Querry = trim($My_Querry, " && ");
return $this->Execute_Querry($My_Querry, $My_Data);
}
public function Insert($My_Data)
{
$keys = array_keys($My_Data);
$My_Querry = "insert into $this->My_Table (" . implode(",", $keys) . ") values (:" .
implode(",:", $keys) . ")";
print_r($My_Querry);
$this->Execute_Querry($My_Querry, $My_Data);
return false;
}
public function Update($id, $My_Data)
{
$keys = array_keys($My_Data);
$My_Querry = "select * from $this->My_Table where ";
foreach ($keys as $key) {
$My_Querry .= $key . " = :" . $key . " && ";
}
$My_Querry = trim($My_Querry, " && ");
$this->Execute_Querry($My_Querry, $My_Data);
return false;
}
public function Delete($My_Data)
{
$keys = array_keys($My_Data);
$My_Querry = "delete from $this->My_Table where ";
$this->Execute_Querry($My_Querry, $My_Data);
}
}
?>

Result

The app/models folder contains the model files. The model files are used to get the data from the database.
For example, the Home model is in the app/models/Home.php file.

PHP

<?php
class Account_User
{
use Model;
public function Verify_My_Data($My_Data)
{
$this->My_Errors = [];
if (empty($My_Data['ism'])) {
$this->My_Errors['ism'] = "الرجاء ادخال الاسم";
}
if (empty($My_Data['laqab'])) {
$this->My_Errors['laqab'] = "الرجاء ادخال اللقب";
}
if (empty($My_Data['mostakhdim'])) {
$this->My_Errors['mostakhdim'] = "الرجاء ادخال اسم المستخدم";
} elseif (!filter_var($My_Data['mostakhdim'], FILTER_VALIDATE_EMAIL)) {
$this->My_Errors['mostakhdim'] = "الرجاء التأكد من اسم المستخدم";
}
if (empty($My_Data['kalimat_sir'])) {
$this->My_Errors['kalimat_sir'] = "الرجاء ادخال كلمة المرور";
}
if (empty($My_Data['Re_kalimat_sir'])) {
$this->My_Errors['Re_kalimat_sir'] = " الرجاء ادخال كلمة المرور مره اخرى";
}
/*
if($My_Data['Re_kalimat_sir'] != $My_Data['kalimat_sir'])
{
$this->My_Errors['Re_kalimat_sir'] = "كلمة المرور غير متطابقة";
}
*/
if (empty($this->My_Errors)) {
return true;
}
return false;
}
}
?>

Result

Models