27 Jun 2022, ver. 1
- Project Overview
- Technologies
- Deployment
- Details: Libraries
- Details: Controllers
- Details: Models
- Details: Views
This is a simple web-app accessible by URL containing two pages for:
- Product list page
- Adding a product page
The product list page displays a list of products in stock and associated information. There are currently 3 types of products: furniture, books, DVDs. There are two buttons on the page: Add Product button and Mass Delete button. When clicked, the buttons perform their respective functions.
Add product page displays a form with several fields and 2 buttons: Save and Cancel. Save button submits the form to the database. Cancel button redirects back to the main page.
As of June 2022, the app is live at https://juniortest.arotari.com
!!! In May 2023 I've finally added adaptive styling (using media queries) to this project. The reason it took me so long to add this is because I was busy with other things. Anyway, better late than never! Also, I've dockerized the project to make it easier to work on in the development mode. Now all you have to do is install docker and run 'docker compose up' command from the project directory. This will spin up docker containers with php, nginx, mysql and phpadmin, you can work on the code and interact with the app on localhost:80
The project has been developed using PHP 7.4, MySQL 8.0, HTML, CSS, JavaScript. No frameworks were used, although the project's back-end design follows MVC pattern, constituting a simplistic framework in and of itself.
The project can be deployed on a virtual private server (VPS) running Ubuntu Linux, and requires customization of web-server settings to ensure correct processing of parameters in requests. Also, see the Section 1 for info about deploying the project in development mode.
Prepare the environment by installing Apache or NGINX, MySQL, and PHP. Click the links for more info about installing and configuring the so-called LAMP or LEMP stacks.
Once the environment has been prepared, create the main app directory at the root of your web-server and copy the directories app/ and public/ into the main app directory.
Create the project's database in MySQL, then create a dedicated user that has a strong password and has been granted all privileges to work with the project's database. You then should run the SQL script create.sql included in the root directory of this repository. The script will create two tables: product and attribute.
Edit database's name, username, user's password in app/config/config.php to match the actual settings of your MySQL configuration:
define('DB_HOST', 'localhost');
define('DB_USER', 'DATABASE_USER');
define('DB_PASS', 'USER_PASSWORD');
define('DB_NAME', 'DATABASE_NAME');
Edit your web-server's configuration to make sure that all incoming requests are routed to directory public/, and that if public/ does not contain any directory or file matching the request, the request is then routed to public/index.php with the original URI passed as a value of the parameter url. For example, for the app to work properly, the original request https://example.com/delete-products/57/135 must be rewritten as https://example.com/public/index.php?url=delete-products/57/135.
You will need to configure your web-server of choice to work with your website. Here are the instructions for Apache and NGINX covering basic configuration of your website.
You then need to use the provided configuration templates to further set up the app.
After having configured the Virtual Hosts file you will need to create 3 files named .htaccess in 3 directories of the app: one in the root directory, another in directory app/, and the third one in directory public/. The contents of the files are shown below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
</IfModule>
Options -Indexes
<IfModule mod_rewrite.c>
Options -Multiviews
RewriteEngine On
RewriteBase /public
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
</IfModule>
After having created server block file for your website in directory /etc/nginx/sites-available/, paste the following into it, replacing the capitalized parts with your path, then activate the server block, check the configuration and, if everything seems OK, reload NGINX.
server {
root /PATH_TO_APP_ROOT/public;
index index.html index.php;
server_name juniortest.arotari.com www.juniortest.arotari.com;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location / {
try_files $uri $uri/ @rules;
}
location @rules {
rewrite ^/(.*)$ /index.php?url=$1 last;
}
The app/libraries/ directory of the app contains three libraries: Core.php, Controller.php, Database.php.
The core of the app. The first and, at the same time, the final step after the server passes the data to public/index.php is to instantiate the Core class. The constructor method of the Core class facilitates the parsing of the data received from the URI and, based on the results of the parsing, calls a specific method of a specific controller, passing specific arguments.
The parent class abstract class of controllers. Implements methods model() that instantiates a specific model and view() that displays a specific view.
Class that instantiates PDO object and facilitates the interaction of models with database.
This is the controller for Product model. When the Products class is instantiated it instantiates Product model as its property. The constructor method of the Core class then calls one of the methods of the Products controller based on the parsed request data, passing arguments, if the request URI contained any.
Products object has three methods: index(): returns the view app/views/index.php displaying the main page with a list of products.
addproducts(): returns the view app/views/add-product.php. Depending on the request method (GET or POST) the controller either displays the form for adding new products, or submits the form data to the server for insertion into database.
deleteproducts(): deletes the products whose IDs are passed as arguments, and then redirects to main page.
The model is instantiated as a property of the controller and interacts with the database, performing create, read, delete operations via its methods getProducts(), setProduct(), deleteProduct(). The model's validate...() methods perform validation of form fields' values before they are inserted into database. The model's format...() methods format the values output from database before they are displayed in a view.
The two views currently implemented are: index.php for the main page and add-product.php for the add product page. The views only cater to desktop browsing, since adaptive/responsive approaches were outside of the scope of this exercise. add-product.php features a form some of whose fields are dynamically generated for added flexibility in choosing a product type. Both views rely on JavaScript for correct operation.
A lot of the app's internal activity is focused on processing the products' attributes in the form of elements of arrays. Due to somewhat complex structure of these arrays, it would probably be useful to include their description here. This may be done at a later time.
This is the first project I did with PHP and JavaScript, and, while I have no doubt that more will follow, it will always have a special place in my heart. This project would be impossible without the people who are happy to share their knowledge with the world and who, through perseverance and dedication, create coding courses that open a world of possibilities for those willing to dive in.