Contoh Website Membuat Framework Sendiri

Diterbitkan Oleh Muaz Ramdany July 27, 2017 Loading... views No Comments

Hi sobat kali ini saya ingin berbagi ilmu pemograman yang berjudul Contoh Membuat Framework Sendiri dengan PHP. Seperti yang kita ketahui bahwa framework ini adalah kerangka kerja yang memudahkan kita dalam membangun website dari segi pemograman PHP atau lainnya.

Mungkin ini tidak ada apa apanya ketimbang kerangka kerja yang sudah populer seperti CodeIgniter, YiiFramework, Laravel dll, Kebetulan disini saya pribadi suka sekali ber-experiment mungkin ini bisa jadi bahan belajar untuk sobat yang lagi membutuhkannya atau yang mendalami sebuah kerangka kerja tersebut.

Baik saya akan langsung saja memberikan contoh kode membuat kerangka kerja tersebut dan seterusnya sobatlah yang memahaminya dan mengembangkannya.

Pertama sobat siapkan software seperti :
  1. Xampp atau Wamp Server.
  2. Editor Sublime atau sejenisnya.
  3. Point penting sabar dalam menghadapi code error.
Buatlah struktur folder seperti gambar di bawah ini :
Saya akan terangkan sedikit tentang struktur folder ini :
Folder [apps] - Di folder ini adalah bagian dari aplikasi untuk membangun website sobat yang terdiri dari Models, Views & Controllers.
Folder [core] - Di folder ini adalah inti yang menjalankan MVC.
Folder [libs] - Di folder ini adalah librari class yang siap pakai. akan tetapi saya juga masih belajar jadi saya kosongkan saja. tapi jika sobat punya ide atau sudah paham bahasa PHP mungkin sobat bisa memodifikasi atau membuat class baru.
Folder [public] - Di folder ini untuk kumpulan bahan mendesain website seperti css, js, img, fonts-nya secara offline dan plugins, sebernanya untuk plugin yang tersedia di pihak ke 2 seperti bootstrap dll.
Folder [routes] - Di folder ini kumpulan rute URL untuk mengakses halaman website sobat pada saat di jalankan di browser.

Jika sudah siap sobat bisa copy & paste kode di bawah ini dan sama kan seperti gambar di atas.
File index.php
// ex : C:www/foo/bar/  
define('_BASEPATH_', dirname(realpath(__FILE__)) . '/' );  
define('ENVIRONMENT', 'development');  
if(defined('ENVIRONMENT'))   
{  
 switch(ENVIRONMENT)   
 {  
  case 'development': error_reporting(E_ALL); break;  
  case 'production': error_reporting(0); break;  
  default: exit('The application environment is not set correctly.'); break;  
 }  
}  
// Autoload ( Init )  
require _BASEPATH_ . 'loader.php'; 

File config.php
// Ex : Output Subfolder/  
define('_BASE_DIR_', basename(dirname($_SERVER['PHP_SELF'])) . '/');  
// AUTO DETECT SUBFOLDER  
// Jika Di URL terditeksi /subfolder/ or /subfolder  
// ex output : subfolder/param/param [or] /subfolder/param/param  
if( str_replace('/', '', _BASE_DIR_) ) {   
 // Variable Tetap  
 define('_BASEROOT_', str_replace('/', '/', _BASE_DIR_));  
}  
else {  
 // Variable Tetap  
 define('_BASEROOT_', str_replace('/', '', _BASE_DIR_));  
}  
// Jalur DIR application/  
define('_APP_PATH_', _BASEPATH_ . 'apps/');  
// Jalur DIR library/  
define('_LIB_PATH_', _BASEPATH_ . 'libs/');  
// Jalur DIR core/  
define('_CORE_', _BASEPATH_ . 'core/');  
// Automatis Menentukan Socket Menggunakan SSL Atau Tidak dan port  
// Ex 1 : http://localhost/ atau http://localhost:8080/  
// Ex 2 : https://localhost/ atau https://localhost:8080/  
if(isset($_SERVER['SERVER_NAME'])) {  
 if($_SERVER["SERVER_PORT"] == '80') {  
  $server = sprintf("%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['SERVER_NAME'], '/');  
 }  
 else {  
  $server = sprintf("%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"], '/');  
 }  
}  
else {  
 if($_SERVER["SERVER_PORT"] == '80') {   
  $server = sprintf("%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['SERVER_ADDR'], '/');   
 }  
 else {  
  $server = sprintf("%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['SERVER_ADDR'].':'.$_SERVER["SERVER_PORT"], '/');   
 }  
}  
// Ex : http://localhost/ | https://localhost/  
define('_HOSTNAME_', $server);  
// URL Standart | if exists subfolder   
// output : http://localhost/subfolder  
define('_BASE_URL_', _HOSTNAME_ . _BASEROOT_);  
// URL API   
// output : http://localhost/api/  
define('_URL_API_', _HOSTNAME_ . _BASEROOT_ . 'api/');  
// URL AJAX   
// output : http://localhost/ajax/  
define('_URL_AJAX_', _HOSTNAME_ . _BASEROOT_ . 'ajax/');  
// Set Path Project untuk router  
define('_BASE_PROJECT_', _BASEROOT_);  
// Definisi String Connect To Database  
define('DB_ENGINE', 'mysql');  
define('DB_HOST', '127.0.0.1');  
define('DB_USER', 'root');  
define('DB_PASS', '');  
define('DB_NAME', '');  
define('DB_PORT', '3306');

File loader.php
// panggil file config  
require _BASEPATH_ . 'config.php';  
// Autoload Class   
function __autoload($class)   
{  
 // Load semua class yang terdapat pada folder   
 if(file_exists( _CORE_ . $class . '.php'))   
 {  
    require _CORE_ . $class . '.php';  
 }  
}  
// menjalankan mvc system  
$router = new Loader;  
$router->init();

File .htaccess
  
# Menolak Pembacaan .htaccess   
  
order allow,deny  
deny from all  
  
  
Options All -Indexes  
  
RewriteEngine On  
# DISINI TEMPAT PENGATURAN RUTE URL SERVER  
#-------------------------------------------------------------------------  
# Document Error  
# jika disimpan di subfolder silahkan untuk ubah /404 to /subfolder/404  
ErrorDocument 401 /subfolder-jika-ada/404  
ErrorDocument 403 /subfolder-jika-ada/404  
ErrorDocument 404 /subfolder-jika-ada/404  
ErrorDocument 500 /subfolder-jika-ada/404  
# Redirect Trailing Slashes If Not A Folder  
# jika disimpan di subfolder silahkan untuk ubah /$1 to /subfolder/$1  
#RewriteCond %{REQUEST_FILENAME} !-d  
#RewriteRule ^(.*)/$ /subfolder-jika-ada/$1 [L,R=301]  
# Redirect If User Make URL '/index.php/param/'  
# jika disimpan di subfolder silahkan untuk ubah / to /subfolder/  
#RewriteRule ^index\.php(.+)$ /subfolder-jika-ada/ [R,L,QSA]  
#-------------------------------------------------------------------------  
# Handle Front Controller  
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteCond %{REQUEST_FILENAME} !-d  
RewriteRule ^(.*)$ index.php/$1 [L]  

Baik beberapa komponen untuk pembangunan framework sudah siap. Sekarang sobat buat folder core dan buatlah nama file dan sesuaikan dengan kode di bawah ini.

File Controller.php
class Controller   
{  
 var $controllerpath = _APP_PATH_ . 'controllers/';  
 /**  
 * initialize class  
 */  
 function __construct()   
 {  
  // membuat objek untuk menghubungkan dengan class views  
  $this->view = new View();  
  // membuat objek untuk menghubungkan dengan class model  
  $this->model = new Model();  
 }  
}

File Model.php
class Model   
{  
 var $modelpath = _APP_PATH_ . 'models/';  
 function __construct()   
 {  
  // buat objek jembatan koneksi ke database  
  // parameter constanta terdapat di file config.php  
  //$this->db = new Database(DB_ENGINE, DB_HOST = null, DB_USER, DB_PASS, DB_PORT);  
 }  
 function load($filename)   
 {  
  // cek file apakah ada  
  if(file_exists($this->modelpath . $filename . '_Model.php'))  
  {  
   require $this->modelpath . $filename . '_Model.php';  
   $modelname = $filename . '_Model';  
   $this->get = new $modelname();  
  }  
 }  
}

File View.php
class View   
{  
 var $viewpath = _APP_PATH_ . 'views/';  
 public function get($filename)   
 {       
  // cek file apakah ada  
  if(file_exists($this->viewpath . $filename . '.php'))  
  {  
   require $this->viewpath . $filename . '.php';  
  }  
 }  
}

File Router.php
class Router {  
 /**  
 * @var array Array of all routes (incl. named routes).  
 */  
 protected $routes = array();  
 /**  
 * @var array Array of all named routes.  
 */  
 protected $namedRoutes = array();  
 /**  
 * @var string Can be used to ignore leading part of the Request URL (if main file lives in subdirectory of host)  
 */  
 protected $basePath = '';  
 /**  
 * @var array Array of default match types (regex helpers)  
 */  
 protected $matchTypes = array(  
    'i' => '[0-9]++',  
    'a' => '[0-9A-Za-z]++',  
    'h' => '[0-9A-Fa-f]++',  
    '*' => '.+?',  
    '**' => '.++',  
    ''  => '[^/\.]++'  
 );  
 /**  
 * Create router in one call from config.  
 *  
 * @param array $routes  
 * @param string $basePath  
 * @param array $matchTypes  
 */  
 public function __construct( $routes = array(), $basePath = '', $matchTypes = array() ) {  
    $this->addRoutes($routes);  
    $this->setBasePath($basePath);  
    $this->addMatchTypes($matchTypes);  
 }  
 /**  
 * Retrieves all routes.  
 * Useful if you want to process or display routes.  
 * @return array All routes.  
 */  
 public function getRoutes() {  
    return $this->routes;  
 }  
 /**  
 * Add multiple routes at once from array in the following format:  
 *  
 *  $routes = array(  
 *   array($method, $route, $target, $name)  
 *  );  
 *  
 * @param array $routes  
 * @return void  
 * @author Koen Punt  
 * @throws Exception  
 */  
 public function addRoutes($routes){  
    if(!is_array($routes) && !$routes instanceof Traversable) {  
   throw new \Exception('Routes should be an array or an instance of Traversable');  
    }  
    foreach($routes as $route) {  
   call_user_func_array(array($this, 'map'), $route);  
    }  
 }  
 /**  
 * Set the base path.  
 * Useful if you are running your application from a subdirectory.  
 */  
 public function setBasePath($basePath) {  
    $this->basePath = $basePath;  
 }  
 /**  
 * Add named match types. It uses array_merge so keys can be overwritten.  
 *  
 * @param array $matchTypes The key is the name and the value is the regex.  
 */  
 public function addMatchTypes($matchTypes) {  
    $this->matchTypes = array_merge($this->matchTypes, $matchTypes);  
 }  
 /**  
 * Map a route to a target  
 *  
 * @param string $method One of 5 HTTP Methods, or a pipe-separated list of multiple HTTP Methods (GET|POST|PATCH|PUT|DELETE)  
 * @param string $route The route regex, custom regex must start with an @. You can use multiple pre-set regex filters, like [i:id]  
 * @param mixed $target The target where this route should point to. Can be anything.  
 * @param string $name Optional name of this route. Supply if you want to reverse route this url in your application.  
 * @throws Exception  
 */  
 public function map($method, $route, $target, $name = null) {  
    $this->routes[] = array($method, $route, $target, $name);  
    if($name) {  
   if(isset($this->namedRoutes[$name])) {  
     throw new \Exception("Can not redeclare route '{$name}'");  
   } else {  
     $this->namedRoutes[$name] = $route;  
   }  
    }  
    return;  
 }  
 /**  
 * Reversed routing  
 *  
 * Generate the URL for a named route. Replace regexes with supplied parameters  
 *  
 * @param string $routeName The name of the route.  
 * @param array @params Associative array of parameters to replace placeholders with.  
 * @return string The URL of the route with named parameters in place.  
 * @throws Exception  
 */  
 public function generate($routeName, array $params = array()) {  
    // Check if named route exists  
    if(!isset($this->namedRoutes[$routeName])) {  
   throw new \Exception("Route '{$routeName}' does not exist.");  
    }  
    // Replace named parameters  
    $route = $this->namedRoutes[$routeName];  
    // prepend base path to route url again  
    $url = $this->basePath . $route;  
    if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {  
   foreach($matches as $match) {  
     list($block, $pre, $type, $param, $optional) = $match;  
     if ($pre) {  
       $block = substr($block, 1);  
     }  
     if(isset($params[$param])) {  
       $url = str_replace($block, $params[$param], $url);  
     } elseif ($optional) {  
       $url = str_replace($pre . $block, '', $url);  
     }  
   }  
    }  
    return $url;  
 }  
 /**  
 * Match a given Request Url against stored routes  
 * @param string $requestUrl  
 * @param string $requestMethod  
 * @return array|boolean Array with route information on success, false on failure (no match).  
 */  
 public function match($requestUrl = null, $requestMethod = null) {  
    $params = array();  
    $match = false;  
    // set Request Url if it isn't passed as parameter  
    if($requestUrl === null) {  
   $requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';  
    }  
    // strip base path from request url  
    $requestUrl = substr($requestUrl, strlen($this->basePath));  
    // Strip query string (?a=b) from Request Url  
    if (($strpos = strpos($requestUrl, '?')) !== false) {  
   $requestUrl = substr($requestUrl, 0, $strpos);  
    }  
    // set Request Method if it isn't passed as a parameter  
    if($requestMethod === null) {  
   $requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';  
    }  
    foreach($this->routes as $handler) {  
   list($methods, $route, $target, $name) = $handler;  
   $method_match = (stripos($methods, $requestMethod) !== false);  
   // Method did not match, continue to next route.  
   if (!$method_match) continue;  
   if ($route === '*') {  
     // * wildcard (matches all)  
     $match = true;  
   } elseif (isset($route[0]) && $route[0] === '@') {  
     // @ regex delimiter  
     $pattern = '`' . substr($route, 1) . '`u';  
     $match = preg_match($pattern, $requestUrl, $params) === 1;  
   } elseif (($position = strpos($route, '[')) === false) {  
     // No params in url, do string comparison  
     $match = strcmp($requestUrl, $route) === 0;  
   } else {  
     // Compare longest non-param string with url  
     if (strncmp($requestUrl, $route, $position) !== 0) {  
       continue;  
     }  
     $regex = $this->compileRoute($route);  
     $match = preg_match($regex, $requestUrl, $params) === 1;  
   }  
   if ($match) {  
     if ($params) {  
       foreach($params as $key => $value) {  
         if(is_numeric($key)) unset($params[$key]);  
       }  
     }  
     return array(  
       'target' => $target,  
       'params' => $params,  
       'name' => $name  
     );  
   }  
    }  
    return false;  
 }  
 /**  
 * Compile the regex for a given route (EXPENSIVE)  
 */  
 private function compileRoute($route) {  
    if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {  
   $matchTypes = $this->matchTypes;  
   foreach($matches as $match) {  
     list($block, $pre, $type, $param, $optional) = $match;  
     if (isset($matchTypes[$type])) {  
       $type = $matchTypes[$type];  
     }  
     if ($pre === '.') {  
       $pre = '\.';  
     }  
     //Older versions of PCRE require the 'P' in (?P)  
     $pattern = '(?:'  
         . ($pre !== '' ? $pre : null)  
         . '('  
         . ($param !== '' ? "?P<$param>" : null)  
         . $type  
         . '))'  
         . ($optional !== '' ? '?' : null);  
     $route = str_replace($block, $pattern, $route);  
   }  
    }  
    return "`^$route$`u";  
 }  
} 

File Loader.php
class Loader   
{  
 function __construct()  
 {  
    $this->router = new Router();  
 }  
 function init()   
 {  
  // Auto ditect direktori router  
  $this->router->setBasePath(_BASE_PROJECT_);  
  // manual set router  
  $dir = _APP_PATH_ . "controllers/";  
  $scan = array_diff(scandir($dir, 1), array('..', '.'));  
  foreach ($scan as $value)   
  {  
   require $dir . $value ;  
  }  
  // load router  
  require _BASEPATH_ . 'routes/web.php';  
  $match = $this->router->match();  
  if ($match === false) {  
  // here you can handle 404  
  } 
  else {  
   list( $controller, $action ) = explode( '#', $match['target'] );  
   if ( is_callable(array($controller, $action)) ) {  
    $obj = new $controller();  
    call_user_func_array(array($obj,$action), array($match['params']));  
   } 
   else {  
    // here your routes are wrong.  
   // Throw an exception in debug, send a 500 error in production  
   }  
  }  
 }  
}

Sejauh ini sistem atau inti MVC sudah siap. Sekarang buat folder apps, controllers, models, dan views di dalamnya dan nanti masukan ke masing-masing folder atau file yang telah kamu buat pada kode di bawah ini.

File Example_Controller.php
class Example extends Controller  
{  
 public function __construct()  
 {  
  parent::__construct();  
 }  
 public function index()  
 {  
  $this->view->pagetitle = "Example";  
  $this->view->get('example');  
  $this->model->load('example');  
  $this->model->get->demo();  
 }  
 function post()  
 {  
  echo 'ini post';  
 }  
}

File Example_Model.php
class Example_Model extends Model  
{  
 function __construct()  
 {  
  parent::__construct();  
 }  
 function demo()  
 {  
  echo 'ini modeling';  
 }  
}

File example.php
<!DOCTYPE html>  
<html>  
 <head>  
  <title><?= $this->pagetitle; ?></title>  
 </head>  
 <body>  
  <h1>Ini Halaman Example</h1>  
 </body>  
</html>

Selesai. Sekarang sobar coba jalankan di browser dengan akses URL : http://localhost/namafoldermu/ dan lihat outputnya. Jika terjadi error atau belum jelas jangan segan untuk bertanya atau berkomentar. Terima kasih telah berkunjung.

Pos Terkait

Komentar Pada `Contoh Website Membuat Framework Sendiri`

0 Komentar Pada `Contoh Website Membuat Framework Sendiri`