GitHub GitHub stars

Page

Table Of Contents


Built with πŸ›  MkDocs - Theme πŸ–€ Github.

Membuat Framework PHP dengan standard PSR (Component)

Bissmilahhiromanhirom, bingung mau buat judul apa, berlebihan sebenernya kalo membuat framework. Karena pada tutorial ini hanya mengunakan Component yang sudah ada dari berbagai Framework. Hinga menjadi layak nya Framework dengan code standart PSR. ,

sebelum memulai harus sudah terinstall di pc kalian.

  1. PHP harus versi 7.3.x atau di atas nya (saya menggunakan v 7.3)
  2. Apache atau Nginx ( saya menggunakan Apache )
  3. OOP basic
  4. composer sudah terinstall
  5. Texteditor Sesuai selera.

daftar isi Tutorial ini:

  1. Composer init ( Mebuat Project )
  2. Auto Loader (PSR-4)
  3. Class Controller
  4. Error Handler
  5. Router
  6. Dispatching Class
  7. HTTP
  8. DI (Dependency Injection)
  9. Templating Engine
  10. Implementasi PDO / ORM
  11. Referensi / Inspirasi (Dokumentasi)

PHP Feature

seiring nya waktu, pemograman PHP banyak menambahkan feature. Hingga sekarang php sudah update hingga PHP 7.x. Banyak sekali feature keren di PHP 7 yang hampir mirip mengikuti coding style seperti JAVA. Seperti Implementation of Type Declarations,

contoh : - Scalar type declarations : - function jumlah(int ..$nilai) - Return type declarations : - function hallo(string $nama, int $umur) : String {} - Strict type-declaration : - declare(strict_types=1);

dan masih banyak lagi, bisa kalian baca di Disini untuk lebih detail contoh penulisan code dan fungsi nya.

Apa itu PSR PSR atau PHP Standars Recommendation sebuah group yang bernama FIG (Framework Interoperability Group) mereka group yang secara tidak langsung ikut dalam pengembangan berbagai Framework yang berdasarkan voting dari para member dan menerapkan untuk penulisan standart code. Hingga sampai saat ini PSR sudah sampai PSR-19. Lebih jelas bisa lihat di sini. Wikipedia

1. Membuat Project (Composer Init)

Jika server local sudah siap saat nya kita membuat project dengan composer. Buka cmd, dan pindahkan path ke Document Root. buat lah folder dengan nama Framework atau apalah. Lalu ketikan composer init. Enter enter aja sampai selesei.

2. Membuat Auto Loader (PSR-4) Class

Selanjut nya kita membuat folder src dan public di dalam folder Framework. Setelah itu buka file composer.json dan tambakan code ini setelah require.

"autoload": {
        "psr-4": {
          "Framework\\": "src/"
       }
}

lalu kita simpan. Buka Cmd dan ketikan composer dump-autoload Nanti akan muncul sebuah folder bernama vendor. Untuk sampai saat ini kita masih tahap persiapan project. Dan untuk lebih detail soal PSR-4 bisa di bisa baca artikal mas ganteng ini di Medium.

Selanjut kita buat 2 buah file .htaccess di folder Framework Dan Public. Dan isi code ini untuk file .htaccess di folder Framework.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^$ public/ [L]
    RewriteRule (.*) public/$1 [L]
</IfModule>

dan code ini untuk file .htaccess di folder public.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /framework
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [QSA,L]
</IfModule>

oia, 1 lagi buat file index.php di public isi kan code ini.

<?php declare(strict_types = 1);
ini_set('display_errors', "1");

echo "Heloo Indonesia";

skrang kita coba Buka di Browser http://localhost/framework/ maka muncul tulisan 'hello indonesia' NB: Jika kalian membuat project tanpa subdirectory. Hapus nama framework di file .htaccess bagian RewriteBase /framework menjadi RewriteBase / atau sesuai nama folder yg kalian buat.

3. Class Controller

buat lah folder Controller di dalam folder src dan buat lah file Class bernama HeroCtrl.php di dalam folder Controller dan isi kan kode ini.

<?php declare(strict_types = 1);

namespace Framework\Controller;

class HeroCtrl {

function __construct(){
    // nanti lanjut
    }

    public function heroIndex() {
        echo "Semua Jagoan ..";
    }

    public function heroByid($param) {
        echo "cari jagoan by id " .$param['id'];
    }

    public function heroByName($param) {
        echo "cari jagoan by nama " .$param['name'];
    }
}

Mau di ganti nama folder lain juga gpp, cuma agar mudah di pahami aja. Kelak nanti kalo ada yg ngelanjutin codingan nya.
Lanjut kita buka file index.php dan mencoba mengunakan Class HeroCtrl yang baru saja di buat di folder Controller. Kita akan mengunakan USE untuk memanggil Class tersebut.

<?php declare(strict_types = 1);

use Framework\Controller\HeroCtrl;

$hero = new HeroCtrl;
$hero->heroIndex();

ketika di jalankan akan Error. Karena fungsi file autoload.php nya belum ter include. Skrang tambah kan require DIR .'/../vendor/autoload.php'; di bawah use. Dan save lalu refresh kembali browser nya. Dan ini lah fungsi dari PSR-4. Tanpa harus include file nya. Class nya sudah bisa dapat di panggil.

4. Error Handler

Dalam nulis code tak luput dari sebuah kesalahan, layak nya aku yang tak bisa mendapatkan mu . Wokwokwo 🀣😭 dalam penulisan code terkadang lupa sama semicolon, variable typo. Dll. banyak masalah yg akan di tempuh seperti dia yang salah memilih orang lain dari pada aku. 😫😭🀣 . oke kali ini kita akan mengunakan component yang sudah bertebaran di public. Dan kita akan menginstall Component Error Handler. Fungsi nya untuk apa ? Untuk menampilkan error PHP nya agar Keren. Macam kaya Framework Laravel. Ini 5 Component Error Handler popular.

  1. whoops
  2. nette\Tracy
  3. PHP-Error
  4. phpdebugbar
  5. symfony\errorhandler

dan untuk tutorial ini kita akan menggunakan whoops sebagai error handler nya. Karena 1 alasan. Keren tampilan nya kalo error. Wkwkwk. Kaya Laravel. Dan Stars di github nya paling banyak di antara component yg lain. Oke skrang kita install woops nya dengan mengetikan ini composer require filp/whoops di cmd. Setelah sudah ter install. Saat nya implemenatasi Class nya di project kita. Buat lah File bootstrap.php di folder src. Lalu buka file index.php Dengan kode ini. Agar class nya dapat bekerja.

Index.php

<?php declare(strict_types = 1);

ini_set('display_errors', "1");

require __DIR__ . '/../src/bootstrap.php';

bootstrap.php

<?php declare(strict_types = 1);

namespace Framework;

require __DIR__ .'/../vendor/autoload.php';
/**
\* Error Handler Register ( basic )
*/
$whoops = new \Whoops\Run;
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();
throw new \Exception;

Sekrang refresh page nya, akan muncul Bidarari cantik yang datang menghampiri mu. 😍😘

5. Router

Gimana ya cara penyampain nya. Agar mudah di pahami. Googling aja deh mendingan kalian. Wkwkwk. Router di sini akan bekerja sebagai mengatur sebuah url pada project kita. Dan untuk menghandle semua Request HTTP pada project. Sebagai contoh. Localhost/home. Link tersebut dapat di akses tanpa harus membuat file home.php atau home.html. Dan dapat di atur (limit) hanya untuk GET atau hanya POST saja. Selanjutnya kita akan menginstall Component router. 5 component Router yg Populer.

  1. FastRoute
  2. phroute
  3. Klein.php
  4. Pux
  5. symfony\routing

kita akan mengunakan Fastroute sebagai handler router nya. Karena 1 Fast ! Dan banyak component lain yang mengunakan Fastroute sebagai codebase nya, contoh Slim. Skrang kita akan install fastroute nya dengan mengetikan composer require nikic/fast-route di cmd kalian. Jika selesei proses install nya, lanjut buka texteditor. Buka file bootsrap.php edit dan tambahkan code ini. dan buat file routes.php di folder src yang nanti nya agar mudah di definisikan router nya.

coba kalian refresh lagi browser nya dan jika bershasil maka tidak akan error, dan coba tambahkan kata sesudah link index. Contoh http://localhost/framework/keren . Sedikit penjelasan. Ini hanya untuk mecoba router menghandler function. Masalah nya gimana kalo kita nanti punya banyak router, dan ga mungkin kita akan membuat handler function di file routes.php. 😡πŸ₯΄ untuk mengatasi nya kita akan mengunakan Dispatch Class yg akan kita bahas di sesion selanjutnya.

6. Dispatching Class

Seperti yang sudah di bahas di session sebelum nya. Fungsi dispatch Class ini untuk menghandler semua prosess Request Router ke Class yang sudah kita buat di folder Controller. Dengan mendefinisikan Class handler nya di file routes.php. Skrang kalian coba buka file routes.php dan definisikan nama Class yg sudah di buat tadi. Ganti menjadi seperti ini.

<?php declare(strict_types = 1);

return [
    ['GET', '/framework/', ['Framework\Controller\HeroCtrl','heroIndex'] ],
    ['GET', '/framework/{id:[0-9]+}', ['Framework\Controller\HeroCtrl','heroById'] ],
    ['GET', '/framework/name/{name}', ['Framework\Controller\HeroCtrl','heroByName'] ],
];

dan rubah file bootsrap.php di bagian

case \FastRoute\Dispatcher::FOUND:
    $handler = $routeInfo[1][0];
    $method = $routeInfo[1][1];
    $vars = $routeInfo[2];
    $class = new $handler;
    $class->$method($vars);
    break;

Skrang coba refresh kembali browser nya. Maka akan menapilkan pesan dari class Hero dengan method heroIndex. Setelah berhasil. Kalian akan menemukan masalah, Untuk menapilkan kode HTML. Ga mungkin kan kita echo setiap kode HTML di Class yang sudah di buat ? Session selanjut kita akan bahas di sesion Templating.

7. HTTP

untuk mempermudah menerima atau Menghandler semua Request dari Client kita membutuhkan Component HTTP untuk memanipulasi Header dan Respone. 5 Component HTTP Populer

  1. Symfony\HttpFoundation
  2. psr\http-message
  3. Slim\Http
  4. Laminas\diactoros
  5. nette\Http

Kita akan memilih Component dari Symfony, alasan nya document nya jelas. Dan banyak CMS yang menggunakan Component dari Symfony ini. Langsung aja install dengan composer. buka cmd Ketikan composer require symfony/http-foundation Jika sudah ter install kita buka file bootsrap.php dahulu untuk meregister Class nya.

Code bootstrap.php dan HeroCtrl.php Sekrang kita buka Class di folder controller yang tadi di buat dan kita coba gunakan Respone dari component Symfony untuk memanipulasi Header respone nya. Ubah file HeroCtrl.php menjadi seperti ini.

Coba resfresh page nya, Maka akan ketemu Mantan yg lagi jalan sama pacar baru nya. Wkkwk. Slow jangan kesel. Gara” abis liat mantan. Oke skrang kita buka lagi file bootstrap.php rubah bagian Dispatch Class nya. Error di karena kan Class HeroCtrl mempunyai 2 paramenter (respone dan request). Sedanghkan di Dispatch Class nya. Belum mengunakan paramenter. Jadi masih kosong. Edit Bagian ini.

    case \FastRoute\Dispatcher::FOUND:
     $handler = $routeInfo[1][0];
     $method = $routeInfo[1][1];
     $vars = $routeInfo[2];
     $class = new $handler(Response::create(), $request); // param class
     $class->$method($vars);
     break;

refresh page nya kembali maka respone header berubah menjadi content type json.

8. Dependency Injection (DI)

dependency injection di php di bagi menjadi 3 cara : 1. Constructor Injection 2. Setter Injection 3. Interface Injection

ada penjeleasan Interface Injection dari mas ganteng ini disini. mas ganteng itu ngejelasin Interface Injection bersama sample class nya. Kalo untuk lebih detail nya bisa di lihat. disini. Atau ini Tapi pada tutorial ini kita akan menggunakan cara Constructor Injection sebagai jalan untuk meimpletasikan dependency injection. Dan seperti biasa kita akan mengunakan component yang sudah ada. Heheh 5 component dependency injection.

  1. PHP-DI
  2. pimple\pimple
  3. league\container
  4. rdlowrey\auryn
  5. level-2\dice

aku akan memilih km sebagai wanita pilihan ku, karena km sexy, 😍 kita akan pilih Dice.php php karena ada benchmark nya. Dan Dice.php single file. Kalao pun mau di ganti nanti nya dengan component lain pun bisa, asal sudah paham dengan cara Constructor Injection karena sistem kerja nya sama, hanya Penullisan nya aja yg beda. Untuk lihat hasil brenchmark Sekrang kita coba install dice nya, buka cmd ketikan. composer require level-2/dice jika selesai download nya, lanjut buat file bernama dependency.php di folder Src. Dan isikan kode ini.

<?php declare(strict_types = 1);

$dice = new \Dice\Dice;

lanjut kita buka file bootstrap.php untuk menganti Dispatch Class nya. Dengan mengunakan Dice.php ubah menjadi seperti ini.

<?php declare(strict_types = 1);
/* .... */
    $class = $dice->create($handler);
    $response = $class->$method($vars);
    if ($response instanceof Response) {
        $response->prepare($request)->send();
    }
    break;
/* .... */

Coba di refresh browser kalian. Tidak terjadi Error seperti tadi. Dimana Class HeroCtrl membutuhkan 2 paramenter sebagai default. Its Magic Constructor Injection.

9. Templating Engine

sampai disinih kita sudah bisa membuat API yang tidak membutuhkan Engine template. Hanya tinggal menambahkan komponen Query Database aka PDO. Sesion selanjut nya kita akan bahas Implentasikan PDO di Dependency Injection. dengan membuat Class Model.

Hingga sampai Sesion terakhir. Kita hanya memanfaatkan Component yang sudah Ada di public. Hingga menjadi sebuah Application dengan Code Standard. beberapa Template Engine popular.

  1. Twig
  2. Mustache
  3. Jenssegers\Blade
  4. Nette\Latte
  5. Smarty
  6. Plates

Dalam memilih Engine Template, bikin bingung mau pilih kriteria seperti apa. Bisa dipilih sesuai selera kalian, saran sih yang mudah Tag nya dan dokumentasi nya lengkap, saya pribadi memilih Latte karena penulisan tag nya ga ribet dan document nya easy to read. Tapi pada tutorial ini kita akan memilih Twig, karena Populer. Takut nya kalo memlih ga populer ntar kalo stack bingung .πŸ˜… Plates recomend buat yg suka style php tag di template. Cocok buat yg suka ngoding native. Skrang kita install Twig nya, buka di cmd dan ketikan. composer require "twig/twig:^3.0" .

pertama kita buat folder baru dengan nama cache di folder framework, lalu buat folder lagi bernama Views di folder Src dan ubah file dependency.php . jangan bingung ya 😁

<?php declare(strict_types = 1);

$load = new \Twig\Loader\FilesystemLoader( __DIR__ . '/Views/');
$rules = [ 
    'Twig\Environment' => [
        'shared' => true,
        'constructParams'   =>  [$load, [ 'cache' => 'false', 'debug' => 'true']]
        //'constructParams'   =>  [$load, [ 'cache' => __DIR__ .'/../cache/']] Enable Cahce
    ],
];


$dice = new \Dice\Dice;
$dice = $dice->addRules($rules);

Dalam taham Develop kita disable dulu cahce nya, jika sudah siap production tinggal di enable cahce nya. sekrang kita buat file Render.php di folder Src dan isi kode ini

Class Render mempunyai 2 method send_html dan send_json

sekrang kita coba buat file twig nya untuk di render di folder Views. SANGAT DENGAN KERAS DI WAJIBKAN MEMBUAT FOLDER PARTIALS DI DALAM FOLDER VIEWS !!!! lanjut buat file base.twig di folder Views dan buat file head.twig di folder partials code untuk base.twig

{% include 'partials/head.twig' %}
<body>
    <h1>Indonesia Maju..</h1>
    <hr/>
         {% if id %} <h2> Hero by {{ id }} !!</h2> {% endif %}
        <a href="/framework/keren">Page </a> . 
        <a href="/framework/">Home </a> . 
        <a href="/framework/name/akujson"> Api Json</a>
</body>

code untuk head.twig

<!DOCTYPE html>
<html>
    <head>
        <title>Dari Head.twig</title>
    </head>

skrang kita gunakan Class Render di Class HeroCtrl. edit Class HeroCtrl nya jadi seperti ini.

<?php declare(strict_types = 1);

namespace Framework\Controller;

use Framework\Render;

class HeroCtrl {

    private $view;

    function __construct(Render $view){
        $this->view = $view;
    }

    public function heroIndex() {
        $this->view->send_html('base.twig');
    }

    public function heroById($params) {
        $this->view->send_html('base.twig', $params);
    }

    public function heroByName($params){
        $this->view->send_json($params);
    }
}

tambah kan ['GET', '/framework/name/{name}', ['Framework\Controller\HeroCtrl','heroByName'] ], di file routes.php untuk menthod loncat. refresh kembali browser nya. 😎 Di Class Render kita dapat membuat default Header atau Respone dan membuat Function Filter Twig . Contoh Membuat Filter Twig di Class Render.php.

/*...*/
    function __construct(Twig $view, Response $response, Request $request){
        $this->view = $view;
        $this->request = $request;
        $this->response = $response;
        $this->init_filter();
    }
/*...*/
    public function init_filter(){
        $filter = new \Twig\TwigFilter('encrypt',[$this, 'encrypt']);
        $this->view->addFilter($filter);
    }
    public function encrypt($str){
        return base64_encode(base64_encode($str)
    }

code di atas hanya contoh untuk membuat Filter Function di twig, jika Filter lebih banyak bisa di buat kan class sendiri yang nanti nya bisa di Inject di file Dependency.php. dan jika mau menganti Template engine nya yang harus di perhatikan adalah Construct di setiap Template Engine nya. karena setiap Class berbeda beda Construct nya.

10. Implementasi PDO / ORM

sekarang kita coba Install component PDO Database di Project kita. agar lebih mudah untuk mengakses Database tanpa perlu memikiran bug SQL Injection. Cukup dengan kita definisikan di nama table dengan membuat Class Model. Beberapa Component PDO Dabatabase yang Canggih. πŸ˜‚

  1. Doctrine\dbal
  2. Phpfastcache\phpfastcache
  3. Illuminate\database (Laravel Punya πŸ˜…)
  4. Spotorm\spot2
  5. Symfony\doctrine

Pribadi si mau pilih Doctrine karena ada Generator Model Class nya. tapi pada turorial ini kita pilih punya laravel deh, karena sudah banyak yang nulis tentang Laravel. Jadi biar mudah aja kalo Stack. kwkw langsung aja install di cmd.

composer require illuminate/database

males banget liat require dev nya banyak banget. πŸ˜‘ karena ini hanya tutorial tak apa lah. Lanjut buat folder Models di folder src. nanti nya Class Buat set/get Table Database. yg udah sering pakai Framework bukan hal aneh apa lagi basis Laravel.😚 haha lanjut edit File dependency.php

Jika ingin mengunakan Feature Seed atau Migrate bisa gunakan cakephp\phinx

Contoh code Models Hero.php

<?php declare(strict_types = 1);

namespace Framework\Models;

use Illuminate\Database\Eloquent\Model;

class Hero extends Model {

   protected $table = "hero";
   protected $primaryKey = 'id';

   public function getAll(){
        return $this->all();
   } 

   public function findId($id){
        return $this->find($id);
   }

   /*** laravel style ***/  
}

dan contoh code untuk Controller HeroCtrl.php

<?php declare(strict_types = 1);

/***/
use Framework\Models\Hero;

/***/
    private $hero;

    function __construct(Render $view){

        $this->view = $view;
        $this->hero = new Hero;
    }

    public function heroIndex() {
        $data = $this->hero->getAll()->toArray();
        $this->view->send_html('base.twig', array('result' => $data) );
    }

    public function heroById($param) {
        $data = $this->hero->findId($param['id']);
        $this->view->send_json($data->toArray());
    }

    public function heroByName($param) {
        $this->view->send_json($param['name']);
    }

Refresh Deh, 😎😍πŸ₯°πŸ€©πŸ˜ Jika langsung mengunakan Static Method pun bisa dengan Hero::All di method controller HeroCtrl.php. jika kalian mau langsung install semua nya bisa di install langsung di clone.

git clone https://github.com/g3xx/antiFramework.git

Referensi / Inspirasi (Dokumentasi)

- Referensi Dokumentasi components

Routing Dokumentasi

http_foundation Dokumentasi

Dice.php

Twig Dokumentasi

Eloquent ORM

- Inspirasi

https://github.com/mmeyer724/Frameworkless/

https://github.com/PatrickLouys/no-framework-tutorial/

- Tentang Saya

Sesorang lulusan SMK, yang suka ngotodidak sejak 2010 dan sampai sekarang belum pernah bekerja sebagai Developer.πŸ˜…

- Donasi

Ga nolak kok di beliin kopi, heheh..

- Penutup

Jika ada kesalahan dalam penulisan, atau sulit di pahami kata kata saya. mohon dibukaan maaf ya sayang. karena aku tau, bagaimana pun pria itu selalu salah. 😫