From 008cd8674ade93ba8933aca101afb4cff2bc5735 Mon Sep 17 00:00:00 2001 From: vgalvoso Date: Tue, 20 Feb 2024 01:31:51 +0800 Subject: [PATCH] Clean source code --- .htaccess | 9 +++- Core/Config.php | 7 ++- Core/DAL.php | 35 +++++++++++--- Core/Database.php | 19 ++++++++ Core/Helper.php | 118 ++++++++++++++++++++++++++++++++++++--------- Core/Validator.php | 42 +++++----------- Models/Model.php | 23 ++++++--- Models/Users.php | 10 +++- README.md | 40 ++++++++++----- api/sample.php | 3 -- api/users.php | 52 ++++++++++++++++++++ api/users/add.php | 12 ----- api/users/all.php | 6 --- autoload.php | 11 ----- composer.json | 13 ++++- index.php | 13 ++--- 16 files changed, 291 insertions(+), 122 deletions(-) create mode 100644 Core/Database.php delete mode 100644 api/sample.php create mode 100644 api/users.php delete mode 100644 api/users/add.php delete mode 100644 api/users/all.php delete mode 100644 autoload.php diff --git a/.htaccess b/.htaccess index 24d921d..203ff2b 100644 --- a/.htaccess +++ b/.htaccess @@ -1,9 +1,14 @@ RewriteEngine On -# Redirect Trailing Slashes... + +# Redirect Trailing Slashes for GET requests... +RewriteCond %{REQUEST_METHOD} =GET RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} (.+)/$ - RewriteRule ^ %1 [L,R=301] +RewriteRule ^ %1 [L,R=301] +# Route requests to index.php... RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^([\s\S]*)$ index.php/$1 [L,NC,QSA] + +Options -Indexes diff --git a/Core/Config.php b/Core/Config.php index 112d648..af98c4d 100644 --- a/Core/Config.php +++ b/Core/Config.php @@ -1,4 +1,7 @@ "Failed","message"=>"Database config [$dbase] not found"]; + output($data); + } + $server = $db[$dbase]["server"]; + $user = $db[$dbase]["user"]; + $pass = $db[$dbase]["pass"]; + $dbname = $db[$dbase]["dbname"]; + $driver = $db[$dbase]["driver"]; + $charset = $db[$dbase]["charset"]; + try{ - $this->conn = new PDO("$driver:host=$server;dbname=$dbname;",$user,$pass, + if($driver=="sqlsrv"){ + $this->conn = new PDO("$driver:Server=$server;database=$dbname;Encrypt=true;TrustServerCertificate=true;",$user,$pass, + [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); + } + if($driver=="mysql"){ + $this->conn = new PDO("$driver:host=$server;dbname=$dbname;charset=$charset",$user,$pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); + } }catch(PDOException $e){ exit($this->error = $e); } diff --git a/Core/Database.php b/Core/Database.php new file mode 100644 index 0000000..1c3c5c2 --- /dev/null +++ b/Core/Database.php @@ -0,0 +1,19 @@ + [ + "server" => "localhost", + "user" => "root", + "pass" => "", + "dbname" => "phpeasy_db", + "driver" => "mysql", + "charset" => "utf8" + ], + "ms_local" => [ + "server" => "LAPTOP-Q8NP2H0P\SQLEXPRESS", + "user" => "", + "pass" => "", + "dbname" => "srspos", + "driver" => "sqlsrv", + "charset" => "utf8" + ] +]; \ No newline at end of file diff --git a/Core/Helper.php b/Core/Helper.php index 8ff0005..f626aea 100644 --- a/Core/Helper.php +++ b/Core/Helper.php @@ -1,8 +1,11 @@ "failed", + "code" => 404, + "error" => "Resource not found!" + ]; + response($errData,404); } /** @@ -100,16 +108,35 @@ function esc($string){ } /** - * Set content type then output content and exit script - * @param string $content The content to output - * @param string $contentType The content type (default application/json) + * Enclose value of array items with specified character + * @param array $arr|indexed Array containing items to enclose + * @param string $char Character to be use as enclosure + * @return array */ -function output($content,$contentType = 'application/json'){ +function encloseItems($arr,$char = "'"){ + foreach($arr as &$item): + $item = $char.$item.$char; + endforeach; + return $arr; +} + +/** + * Set content type and status code then output content and exit script + * @param string|array $content The content to output + * @param int $statusCode The response status code (default 200) + * @param string $contentType The content type (default application/json). + * Available content-types: [ application/json | plain/text | text/html ] + * @return void + */ +function response(string|array $content,int $statusCode = 200,string $contentType = 'application/json',){ header("Content-Type: $contentType"); + http_response_code($statusCode); $data = match ($contentType) { - "application/json" => json_encode($content) + "application/json" => json_encode($content), + "plain/text" => json_encode($content), + "text/html" => $content }; - die($data); + exit($data); } /** @@ -187,11 +214,19 @@ function session($sessionVar, $value = null){ function objArrayToValues($objArr,$item){ $arr = []; foreach($objArr as $obj){ + $obj = (object)$obj; array_push($arr, $obj->$item); } return $arr; } +/** + * Check wether the path provided in request is view or an api. + * If view includes the specified view, + * if not, returns false. + * + * @return void|false + */ function view(){ if(PATH == ""){ include "View/index.php"; @@ -213,24 +248,63 @@ function view(){ die; } +/** + * State that a php view file is an SPA component. + * This function will prevent the view file to be accessible via url, + * can only be accessed through ajax call + */ function component(){ if(isset($_SERVER["HTTP_SEC_FETCH_MODE"]) && ($_SERVER["HTTP_SEC_FETCH_MODE"] == "navigate")) notFound(); } +/** + * Check wether the path provided in request is an api or a view. + * If api, includes the specified api, + * if not, returns false. + * + * @return void|false + */ function api(){ - if(isset($_SERVER["HTTP_SEC_FETCH_MODE"]) && ($_SERVER["HTTP_SEC_FETCH_MODE"] == "navigate")) - notFound(); + //get all after "api/" $rawPath = substr(PATH,4); + //remove query params so raw resource uri remains eg. [users?city='caloocan'] to [users] + $rawPath = strstr($rawPath, "?", true) ?: $rawPath; + //check if has uri param + $parts = explode("/",rtrim($rawPath,"/")); + if(count($parts) > 1): + $rawPath = $parts[0]; + //extract the uri param + define("URI_PARAM",$parts[1]); + endif; + $rawPath = rtrim($rawPath,"/"); if(!file_exists("api/$rawPath.php")) - if(!file_exists("api/$rawPath/index.php")) - return false; - else - $rawPath .= "/index"; - - if(!empty($_GET)) - extract($_GET); - + notFound(); include "api/$rawPath.php"; die; -} \ No newline at end of file +} + +/** + * Starts a php file as a REST API + */ +function startAPI(){ + if(function_exists(strtolower(REQUEST_METHOD))) + strtolower(REQUEST_METHOD)(); + else + response(["status" => "failed","error" =>"Method Not Allowed!"],405); +} + +/** + * Decode JSON string from request body [file_get_contents("php://input")] + * into associative array, exit and return 403 status code with message + * "Invalid json data" if fail + * @return array + */ +function getRequestBody(){ + $data = file_get_contents("php://input"); + if(!$data = json_decode($data,true)) + response("Invalid json data"); + return $data; +} + +//EOF diff --git a/Core/Validator.php b/Core/Validator.php index 20092b5..d0b463c 100644 --- a/Core/Validator.php +++ b/Core/Validator.php @@ -1,8 +1,15 @@ $fieldErrors) { - foreach ($fieldErrors as $error) { - echo "

$error


"; - } - } + $data = [ + "status" => "Failed", + "error(s):" => array_reduce($errors,'array_merge',[]) + ]; + response($data,400); exit(); } return true; - //return $errors; -} - -/** - * Return 403 response code to mark as invalid - * @param string $message Error message to show - */ -function invalid($message){ - http_response_code(403); - exit($message); } - -/** - * Place specified inputs from GET/POST to an array - */ -function allowedVars($inputs,$rules){ - $vars = []; - foreach($inputs as $key => $val) - foreach($rules as $ruleKey => $ruleVal) - if($key ==$ruleKey) - $vars[$key]=$val; - return $vars; -} \ No newline at end of file diff --git a/Models/Model.php b/Models/Model.php index 79cd1f9..27e22f8 100644 --- a/Models/Model.php +++ b/Models/Model.php @@ -1,4 +1,9 @@ db = $db; } - public function getAll(){ - $sql = "SELECT * FROM $this->table"; - return $this->db->getItems($sql); - } - - public function create($values){ - return $this->db->insert($this->table,$values); + public function getAll(string $condition = "1=1",array $params = []){ + $sql = "SELECT * FROM $this->table WHERE $condition"; + return $this->db->getItems($sql,$params); } public function get($id){ @@ -22,7 +23,13 @@ public function get($id){ return $this->db->getItem($sql,["id" => $id]); } + public function add($values){ + return $this->db->insert($this->table,$values); + } + public function delete($id){ return $this->db->delete($this->table,"id=:id",["id"=>$id]); } -} \ No newline at end of file +} + +//EOF diff --git a/Models/Users.php b/Models/Users.php index 670842d..57833d7 100644 --- a/Models/Users.php +++ b/Models/Users.php @@ -1,8 +1,16 @@ table = "users"; } -} \ No newline at end of file +} + +//EOF diff --git a/README.md b/README.md index 911ed77..ba21784 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ It's goal is to enable php developers to code freely, write less and do more. 7. Supports PHP 8 and above , MySQL, MSSQL and SQlite 8. Includes basic css and js helpers. +## Main Points +1. Use of Data Abstraction Layer rather than ORM, focused on maximum performance without large database calls used by orms. + ## Table of Contents I. [Intro] @@ -31,26 +34,37 @@ II. [Installation] [Model]: #5-model ## Intro -For this document let's assume that the server is hosted in your local machine. -The base url is http://localhost/phpeasy - -And a mysql database named (phpeasy_db) - +Nowadays you must follow coding standards(OOP,SOLID,DRY,etc.) and mvc frameworks to do web development +using PHP. PHP frameworks out there comes with too much files, configurations, classes and dependencies. +I made this mini framework so php developers can do web development faster while mastering and enjoying +the PHP language itself (Yes! no need to learn libraries a,b,c...). + +## Pre-requisites +Hands-on is the best way to learn, so let's get started. +1. You must have php web server installed and setup like(XAMPP). +2. You must have composer installed. +3. Create the sample database +Execute this MySQL query to create phpeasy_db with 1 table (users) - id - int(11) auto increment primary, - username - varchar(255), - password - varchar(255), - firstname - varchar(255), - lastname - varchar(255) +```SQL +CREATE DATABASE IF NOT EXISTS phpeasy_db; +USE phpeasy_db; -## Installation -Manual - Download the repo and paste to htdocs or your webserver's root folder. +CREATE TABLE IF NOT EXISTS users ( + id INT(11) AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(255), + password VARCHAR(255), + firstname VARCHAR(255), + lastname VARCHAR(255) +); +``` +## Installation Composer - open a terminal inside htdocs folder and execute the command below. ``` -composer create-project vgalvoso/phpeasy +composer create-project vgalvoso/phpeasy my_phpeasy ``` ## 1. Views diff --git a/api/sample.php b/api/sample.php deleted file mode 100644 index bbe069d..0000000 --- a/api/sample.php +++ /dev/null @@ -1,3 +0,0 @@ -get(URI_PARAM)) + response("User not found!",404); + response([$user]); + } + + $users = $usersModel->getAll(); + response($users); +} + +function post(){ + $db = new DAL(); + $db->startTrans(); + $users = new Users($db); + + $postData = getRequestBody(); + validate($postData,[ + "username" => "required|string", + "password" => "required|string", + "firstname" => "required|string", + "lastname" => "required|string" + ]); + + $values = ["username" => $postData["username"], + "password" => password_hash($postData["password"],PASSWORD_BCRYPT), + "firstname" => $postData["firstname"], + "lastname" => $postData["lastname"]]; + + if(!$users->add($values)) + response("Can't add user!".$db->getError(),400); + + $db->commit(); + response(["status" => "Success"]); +} + +//EOF diff --git a/api/users/add.php b/api/users/add.php deleted file mode 100644 index 932c3a8..0000000 --- a/api/users/add.php +++ /dev/null @@ -1,12 +0,0 @@ - $username, - "firstname" => $firstname, - "lastnamr" => $lastname]; - -if(!$users->create($values)) - invalid("Can't add user!"); \ No newline at end of file diff --git a/api/users/all.php b/api/users/all.php deleted file mode 100644 index a831512..0000000 --- a/api/users/all.php +++ /dev/null @@ -1,6 +0,0 @@ -getAll(); \ No newline at end of file diff --git a/autoload.php b/autoload.php deleted file mode 100644 index 7d2d924..0000000 --- a/autoload.php +++ /dev/null @@ -1,11 +0,0 @@ -