Kerangka mikro PHP yang kuat namun mudah digunakan yang dirancang untuk membantu Anda membangun aplikasi Web yang dinamis dan kuat - dengan cepat!
Diringkas dalam satu file ~65KB, F3 (begitu kami menyebutnya) memberi Anda dasar yang kuat, basis kode yang matang, dan pendekatan yang sungguh-sungguh dalam menulis aplikasi Web. Di dalamnya terdapat kit alat pengembangan Web yang mudah digunakan, perutean URL berkinerja tinggi dan mesin cache, penyorotan kode bawaan, dan dukungan untuk aplikasi multibahasa. Ringan, mudah digunakan, dan cepat. Yang terpenting, hal itu tidak menghalangi Anda.
Apakah Anda seorang pemula atau ahli programmer PHP, F3 akan membantu Anda bekerja dalam waktu singkat. Tidak ada prosedur instalasi yang tidak perlu dan melelahkan. Tidak diperlukan konfigurasi yang rumit. Tidak ada struktur direktori yang berbelit-belit. Tidak ada waktu yang lebih baik untuk mulai mengembangkan aplikasi Web dengan cara yang mudah selain sekarang!
F3 mendukung database SQL dan NoSQL yang tersedia: MySQL, SQLite, MSSQL/Sybase, PostgreSQL, DB2, dan MongoDB. Ia juga dilengkapi dengan pemetaan objek-relasional yang kuat untuk abstraksi dan pemodelan data yang ringan seperti kerangka kerjanya. Tidak diperlukan konfigurasi.
Bukan itu saja. F3 dikemas dengan plug-in opsional lain yang memperluas kemampuannya: -
Tidak seperti kerangka kerja lainnya, F3 bertujuan agar dapat digunakan - bukan kerangka kerja biasa.
Filosofi di balik kerangka kerja dan pendekatannya terhadap arsitektur perangkat lunak adalah menuju minimalisme dalam komponen struktural, menghindari kompleksitas aplikasi dan mencapai keseimbangan antara keanggunan kode, kinerja aplikasi, dan produktivitas pemrogram.
F3 memiliki arsitektur kelas enterprise yang stabil. Performa tak terkalahkan, fitur ramah pengguna, dan bobot ringan. Apa lagi yang bisa Anda minta? Untuk mendapatkan paket ini, cukup unduh paket ini atau kunjungi repositori fatfree-core untuk menemukan versi edge terbaru.
Untuk semua pengguna komposer di luar sana:
composer create-project bcosca/fatfree
composer require bcosca/fatfree-core
Sangat disarankan bagi pengguna berpengalaman untuk mengembangkan aplikasi baru dengan versi terbaru untuk memanfaatkan basis kode yang diperbarui dan peningkatan berkelanjutan.
Panduan pengguna terbaru dan dokumentasi API terperinci dengan banyak contoh kode dan panduan grafis dapat ditemukan di fatfreeframework.com/.
Tentu saja referensi online yang berguna ini didukung oleh F3! Ini menunjukkan kemampuan dan kinerja kerangka kerja. Coba lihat sekarang. Jika Anda ingin membacanya langsung di github, Anda dapat menemukan konten situs webnya di github.com/F3Community/F3com-data
Seorang desainer tahu bahwa dia telah mencapai kesempurnaan bukan ketika tidak ada lagi yang bisa ditambahkan, tapi ketika tidak ada lagi yang bisa diambil. -- Antoine de Saint-Exupéry
Kerangka Bebas Lemak memudahkan pembuatan seluruh situs Web dalam sekejap. Dengan kekuatan dan keringkasan yang sama dengan toolkit dan pustaka Javascript modern, F3 membantu Anda menulis program PHP yang lebih bagus dan andal. Sekilas kode sumber PHP Anda dan siapa pun akan mudah memahaminya, seberapa banyak yang dapat Anda capai dalam beberapa baris kode, dan betapa hebatnya hasilnya.
F3 adalah salah satu kerangka kerja terdokumentasi terbaik. Mempelajarinya tidak memerlukan biaya apa pun. Tidak ada serangkaian struktur direktori yang sulit dinavigasi dan langkah pemrograman yang mengganggu. Tidak ada banyak pilihan konfigurasi hanya untuk menampilkan 'Hello, World'
di browser Anda. Bebas Lemak memberi Anda banyak kebebasan - dan gaya - untuk menyelesaikan lebih banyak pekerjaan dengan mudah dan dalam waktu lebih singkat.
Pendekatan deklaratif F3 terhadap pemrograman memudahkan pemula dan ahli untuk memahami kode PHP. Jika Anda familiar dengan bahasa pemrograman Ruby, Anda akan melihat kemiripan antara kerangka mikro Fat-Free dan Sinatra karena keduanya menggunakan Bahasa Khusus Domain yang sederhana untuk layanan Web ReSTful. Namun tidak seperti Sinatra dan inkarnasi PHP-nya (Fitzgerald, Limonade, Glue - dan masih banyak lagi), Fat-Free lebih dari sekadar menangani rute dan permintaan. Tampilan bisa dalam bentuk apa pun, seperti teks biasa, HTML, XML, atau pesan email. Kerangka kerja ini dilengkapi dengan mesin templat yang cepat dan mudah digunakan. F3 juga bekerja secara lancar dengan mesin templat lainnya, termasuk Twig, Smarty, dan PHP itu sendiri. Model berkomunikasi dengan pemeta data F3 dan pembantu SQL untuk interaksi yang lebih kompleks dengan berbagai mesin database. Plug-in lain memperluas fungsionalitas dasar lebih jauh lagi. Ini adalah kerangka pengembangan Web total - dengan banyak kekuatan!
Buka zip isi paket distribusi di mana saja di hard drive Anda. Secara default, file kerangka kerja dan plug-in opsional terletak di jalur lib/
. Atur struktur direktori Anda sesuai keinginan Anda. Anda dapat memindahkan folder default ke jalur yang tidak dapat diakses oleh Web untuk keamanan yang lebih baik. Hapus plugin yang tidak Anda perlukan. Anda selalu dapat memulihkannya nanti dan F3 akan mendeteksi keberadaannya secara otomatis.
Penting: Jika aplikasi Anda menggunakan APC, Memcached, WinCache, XCache, atau cache sistem file, hapus semua entri cache terlebih dahulu sebelum menimpa versi kerangka kerja yang lebih lama dengan yang baru.
Pastikan Anda menjalankan versi PHP yang benar. F3 tidak mendukung versi sebelum PHP 7.2. Anda akan mendapatkan kesalahan sintaksis (positif palsu) di mana-mana karena konstruksi bahasa baru dan penutupan/fungsi anonim tidak didukung oleh versi PHP yang sudah ketinggalan zaman. Untuk mengetahuinya, buka konsol Anda ( bash
shell di GNU/Linux, atau cmd.exe
di Windows):-
/path/to/php -v
PHP akan memberi tahu Anda versi tertentu yang Anda jalankan dan Anda akan mendapatkan sesuatu yang mirip dengan ini:-
PHP 7.4.21 (cli) (built: Jul 27 2021 15:56:07) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v2.9.8, Copyright (c) 2002-2020, by Derick Rethans
Tingkatkan versi jika perlu dan kembali lagi ke sini jika Anda telah beralih ke PHP 7.4 atau rilis yang lebih baru. Fatfree membutuhkan setidaknya PHP 7.2 agar dapat berfungsi. Jika Anda memerlukan penyedia layanan hosting, cobalah salah satu layanan berikut:
Saatnya untuk mulai menulis aplikasi pertama kami: -
$ f3 = require ( ' path/to/base.php ' );
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
Tambahkan base.php
pada baris pertama dengan jalur yang sesuai. Simpan potongan kode di atas sebagai index.php
di folder root Web Anda. Kami telah menulis halaman Web pertama kami.
Menggunakan komposer? Kemudian jalankan composer require bcosca/fatfree
dan gunakan perintah berikut:
require ' vendor/autoload.php ' ;
$ f3 = Base:: instance ();
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
Perintah pertama memberi tahu juru bahasa PHP bahwa Anda ingin fungsi dan fitur kerangka kerja tersedia untuk aplikasi Anda. Metode $f3->route()
menginformasikan Bebas Lemak bahwa halaman Web tersedia di URL relatif yang ditandai dengan garis miring ( /
). Siapa pun yang mengunjungi situs Anda di http://www.example.com/
akan melihat pesan 'Hello, world!'
pesan karena URL /
setara dengan halaman root. Untuk membuat rute yang bercabang dari halaman root, seperti http://www.example.com/inside/
, Anda dapat menentukan rute lain dengan string GET /inside
sederhana.
Rute yang dijelaskan di atas memberitahu kerangka kerja untuk merender halaman hanya ketika menerima permintaan URL menggunakan metode HTTP GET
. Situs Web yang lebih kompleks yang berisi formulir menggunakan metode HTTP lain seperti POST
, dan Anda juga dapat mengimplementasikannya sebagai bagian dari spesifikasi $f3->route()
.
Jika kerangka kerja melihat permintaan masuk untuk halaman Web Anda yang terletak di URL root /
, kerangka kerja akan secara otomatis mengarahkan permintaan tersebut ke fungsi panggilan balik, yang berisi kode yang diperlukan untuk memproses permintaan dan merender hal-hal HTML yang sesuai. Dalam contoh ini, kita hanya mengirimkan string 'Hello, world!'
ke browser Web pengguna.
Jadi kami telah menetapkan rute pertama kami. Tapi itu tidak akan banyak membantu, kecuali memberi tahu F3 bahwa ada proses yang akan menanganinya dan ada beberapa teks untuk ditampilkan di browser Web pengguna. Jika Anda memiliki lebih banyak halaman di situs Anda, Anda perlu menyiapkan rute berbeda untuk setiap grup. Untuk saat ini, mari kita buat tetap sederhana. Untuk menginstruksikan framework agar mulai menunggu permintaan, kami mengeluarkan perintah $f3->run()
.
Tidak Bisa Menjalankan Contohnya? Jika Anda kesulitan menjalankan program sederhana ini di server Anda, Anda mungkin harus sedikit mengubah pengaturan server Web Anda. Lihatlah contoh konfigurasi Apache di bagian berikut (bersama dengan Nginx dan Lighttpd yang setara).
Masih mengalami kesulitan? Pastikan $f3 = require('path/to/base.php');
tugas datang sebelum keluaran apa pun dalam skrip Anda. base.php
memodifikasi header HTTP, sehingga karakter apa pun yang dikeluarkan ke browser sebelum penetapan ini akan menyebabkan kesalahan.
Contoh pertama kita tidak terlalu sulit untuk diterima, bukan? Jika Anda ingin lebih banyak rasa pada sup Bebas Lemak Anda, masukkan rute lain sebelum perintah $f3->run()
:-
$ f3 -> route ( ' GET /about ' ,
function () {
echo ' Donations go to a local charity... us! ' ;
}
);
Anda tidak ingin mengacaukan namespace global dengan nama fungsi? Bebas Lemak mengenali berbagai cara memetakan penangan rute ke kelas dan metode OOP: -
class WebPage {
function display () {
echo ' I cannot object to an object ' ;
}
}
$ f3 -> route ( ' GET /about ' , ' WebPage->display ' );
Permintaan HTTP juga dapat dialihkan ke metode kelas statis: -
$ f3 -> route ( ' GET /login ' , ' Auth::login ' );
Argumen yang diteruskan selalu diberikan sebagai parameter kedua:
$ f3 -> route ( ' GET /hello/@name ' , ' User::greet ' );
class User {
public static function greet ( $ f3 , $ args ) { // $ args is type of Array
echo " Hello " . $ args [ ' name ' ];
}
}
Jika argumen nama yang diberikan adalah foo (/hello/foo), output berikut akan ditampilkan:
Hello foo
Sebagai demonstrasi bahasa khusus domain (DSL) Bebas Lemak yang kuat, Anda dapat menentukan satu rute untuk menangani berbagai kemungkinan: -
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 ) {
echo $ f3 -> get ( ' PARAMS.count ' ). ' bottles of beer on the wall. ' ;
}
);
Contoh ini menunjukkan bagaimana kita dapat menentukan token @count
untuk mewakili bagian dari URL. Kerangka kerja ini akan melayani URL permintaan apa pun yang cocok dengan awalan /brew/
, seperti /brew/99
, /brew/98
, dll. Ini akan menampilkan '99 bottles of beer on the wall'
dan '98 bottles of beer on the wall'
, masing-masing. Bebas Lemak juga akan menerima permintaan halaman untuk /brew/unbreakable
. (Berharap ini menampilkan 'unbreakable bottles of beer on the wall'
.) Ketika rute dinamis seperti itu ditentukan, Bebas Lemak secara otomatis mengisi variabel array PARAMS
global dengan nilai string yang ditangkap di URL. Panggilan $f3->get()
di dalam fungsi panggilan balik mengambil nilai variabel kerangka kerja. Anda tentu dapat menerapkan metode ini dalam kode Anda sebagai bagian dari presentasi atau logika bisnis. Namun kita akan membahasnya lebih detail nanti.
Perhatikan bahwa Bebas Lemak memahami notasi titik array. Anda dapat menggunakan notasi reguler PARAMS['count']
sebagai gantinya dalam kode, yang rentan terhadap kesalahan ketik dan kurung kurawal tidak seimbang. Dalam tampilan dan templat, kerangka kerja mengizinkan notasi @PARAMS.count
yang agak mirip dengan Javascript. (Kami akan membahas tampilan dan templat nanti.)
Berikut cara lain untuk mengakses token dalam pola permintaan:-
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 , $ params ) {
echo $ params [ ' count ' ]. ' bottles of beer on the wall. ' ;
}
);
Anda dapat menggunakan tanda bintang ( *
) untuk menerima URL apa pun setelah rute /brew
- jika Anda tidak terlalu peduli dengan jalur selanjutnya:-
$ f3 -> route ( ' GET /brew/* ' ,
function () {
echo ' Enough beer! We always end up here. ' ;
}
);
Hal penting untuk dipertimbangkan: Anda akan bingung (dan diri Anda sendiri) Bebas Lemak jika Anda memiliki GET /brew/@count
dan GET /brew/*
secara bersamaan dalam aplikasi yang sama. Gunakan satu atau yang lain. Hal lain: Fat-Free melihat GET /brew
terpisah dan berbeda dari rute GET /brew/@count
. Masing-masing dapat memiliki penangan rute yang berbeda.
Tunggu sebentar - dalam semua contoh sebelumnya, kami tidak pernah benar-benar membuat direktori apa pun di hard drive kami untuk menyimpan rute ini. Jawaban singkatnya: kita tidak perlu melakukannya. Semua rute F3 bersifat virtual. Mereka tidak mencerminkan struktur folder hard disk kita. Jika Anda memiliki program atau file statis (gambar, CSS, dll.) yang tidak menggunakan kerangka kerja - selama jalur ke file ini tidak bertentangan dengan rute apa pun yang ditentukan dalam aplikasi Anda - perangkat lunak server Web Anda akan mengirimkannya ke browser pengguna, asalkan server dikonfigurasi dengan benar.
Saat Anda menentukan rute, Anda dapat memberinya nama. Gunakan nama rute dalam kode dan templat Anda, bukan url yang diketik. Kemudian jika Anda perlu mengubah url Anda untuk menyenangkan tuan pemasaran, Anda hanya perlu melakukan perubahan di mana rute telah ditentukan. Nama rute harus mengikuti aturan penamaan variabel php (tidak boleh ada titik, tanda hubung, atau tanda hubung).
Mari beri nama rute: -
$ f3 -> route ( ' GET @beer_list: /beer ' , ' Beer->list ' );
Nama disisipkan setelah rute KATA KERJA ( GET
dalam contoh ini) diawali dengan simbol @
, dan dipisahkan dari bagian URL dengan simbol titik dua :
. Anda dapat menyisipkan spasi setelah titik dua jika itu memudahkan membaca kode Anda (seperti yang ditunjukkan di sini).
Untuk mengakses rute bernama dalam templat, dapatkan nilai rute bernama sebagai kunci dari array sarang ALIASES
: -
< a href =" {{ @ALIASES.beer_list }} " > View beer list </ a >
Untuk mengarahkan pengunjung ke URL baru, panggil rute bernama di dalam metode reroute()
seperti:-
// a named route is a string value
$ f3 -> reroute ( ' @beer_list ' ); // note the single quotes
Jika Anda menggunakan token di rute Anda, F3 akan mengganti token tersebut dengan nilainya saat ini. Jika Anda ingin mengubah nilai token sebelum memanggil reroute, teruskan sebagai argumen ke-2.:-
$ f3 -> route ( ' GET @beer_list: /beer/@country ' , ' Beer->bycountry ' );
$ f3 -> route ( ' GET @beer_list: /beer/@country/@village ' , ' Beer->byvillage ' );
// a set of key - value pairs is passed as argument to named route
$ f3 -> reroute ( ' @beer_list(@country=Germany) ' );
// if more than one token needed
$ f3 -> reroute ( ' @beer_list(@country=Germany,@village=Rhine) ' );
Ingatlah untuk urlencode()
argumen Anda jika Anda memiliki karakter yang tidak mematuhi pedoman RFC 1738 untuk URL yang dibuat dengan baik.
Versi stabil terbaru PHP memiliki server Web bawaannya sendiri. Mulai menggunakan konfigurasi berikut: -
php -S localhost:80 -t /var/www/
Perintah di atas akan mulai merutekan semua permintaan ke root Web /var/www
. Jika permintaan HTTP masuk untuk file atau folder diterima, PHP akan mencarinya di dalam root Web dan mengirimkannya ke browser jika ditemukan. Jika tidak, PHP akan memuat index.php
default (berisi kode Anda yang mendukung F3).
Jika Anda menggunakan Apache, pastikan Anda mengaktifkan modul penulisan ulang URL (mod_rewrite) di file Apache.conf (atau httpd.conf) Anda. Anda juga harus membuat file .htaccess yang berisi yang berikut:-
# Enable rewrite engine and route requests to framework
RewriteEngine On
# Some servers require you to specify the `RewriteBase` directive
# In such cases, it should be the path (relative to the document root)
# containing this .htaccess file
#
# RewriteBase /
RewriteRule ^(tmp)/|.ini$ - [R=404]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
Skrip ini memberi tahu Apache bahwa setiap kali permintaan HTTP tiba dan jika tidak ada file fisik ( !-f
) atau jalur ( !-d
) atau tautan simbolik ( !-l
) yang dapat ditemukan, maka harus mentransfer kendali ke index.php
, yang berisi pengontrol utama/depan kita, dan yang pada gilirannya, memanggil kerangka kerja.
.htaccess file
yang berisi arahan Apache yang disebutkan di atas harus selalu berada di folder yang sama dengan index.php
.
Anda juga perlu mengatur Apache agar mengetahui lokasi fisik index.php
di hard drive Anda. Konfigurasi tipikal adalah: -
DocumentRoot " /var/www/html "
< Directory "/var/www/html">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
Jika Anda mengembangkan beberapa aplikasi secara bersamaan, konfigurasi host virtual lebih mudah dikelola:-
NameVirtualHost *
< VirtualHost *>
ServerName site1.com
DocumentRoot " /var/www/site1 "
< Directory "/var/www/site1">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
< VirtualHost *>
ServerName site2.com
DocumentRoot " /var/www/site2 "
< Directory "/var/www/site2">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
Setiap ServerName
( site1.com
dan site2.com
dalam contoh kita) harus terdaftar di file /etc/hosts
Anda. Di Windows, Anda harus mengedit C:/WINDOWS/system32/drivers/etc/hosts
. Reboot mungkin diperlukan untuk melakukan perubahan. Anda kemudian dapat mengarahkan browser Web Anda ke alamat http://site1.com
atau http://site2.com
. Host virtual membuat aplikasi Anda lebih mudah untuk diterapkan.
Untuk server Nginx, berikut konfigurasi yang disarankan (ganti ip_address:port dengan pengaturan FastCGI PHP lingkungan Anda):-
server {
root /var/www/html;
location / {
index index.php index.html index.htm;
try_files $uri $uri / /index.php? $query_string ;
}
location ~ .php$ {
fastcgi_pass ip_address:port;
include fastcgi_params;
}
}
Server Lighttpd dikonfigurasi dengan cara yang sama: -
$HTTP["host"] =~ "www.example.com$" {
url.rewrite-once = ( "^/(.*?)(?.+)?$"=>"/index.php/$1?$2" )
server.error-handler-404 = "/index.php"
}
Instal modul penulisan ulang URL dan kerangka .NET yang sesuai dengan versi Windows Anda. Kemudian buat file bernama web.config
di root aplikasi Anda dengan isi sebagai berikut:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Application" stopProcessing="true">
<match url=".*" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Jadi mari kita kembali ke pengkodean. Anda dapat menyatakan suatu halaman menjadi usang dan mengarahkan pengunjung Anda ke situs/halaman lain:-
$ f3 -> route ( ' GET|HEAD /obsoletepage ' ,
function ( $ f3 ) {
$ f3 -> reroute ( ' /newpage ' );
}
);
Jika seseorang mencoba mengakses URL http://www.example.com/obsoletepage
menggunakan permintaan HTTP GET atau HEAD, kerangka kerja mengarahkan pengguna ke URL: http://www.example.com/newpage
seperti yang ditunjukkan di contoh di atas. Anda juga dapat mengarahkan pengguna ke situs lain, seperti $f3->reroute('http://www.anotherexample.org/');
.
Perutean ulang bisa sangat berguna ketika Anda perlu melakukan beberapa pekerjaan pemeliharaan di situs Anda. Anda dapat memiliki pengendali rute yang memberi tahu pengunjung bahwa situs Anda sedang offline untuk jangka waktu singkat.
Pengalihan HTTP sangat diperlukan tetapi juga mahal. Sebisa mungkin, jangan menggunakan $f3->reroute()
untuk mengirim pengguna ke halaman lain di situs Web yang sama jika Anda dapat mengarahkan alur aplikasi Anda dengan memanggil fungsi atau metode yang menangani rute target. Namun, pendekatan ini tidak akan mengubah URL pada bilah alamat browser Web pengguna. Jika ini bukan perilaku yang Anda inginkan dan Anda benar-benar perlu mengirim pengguna ke halaman lain, misalnya berhasil mengirimkan formulir atau setelah pengguna diautentikasi, Fat-Free mengirimkan header HTTP 302 Found
. Untuk semua upaya lain untuk merutekan ulang ke halaman atau situs lain, kerangka kerja mengirimkan header HTTP 301 Moved Permanently
.
Saat runtime, Fat-Free secara otomatis menghasilkan kesalahan HTTP 404 setiap kali melihat bahwa permintaan HTTP masuk tidak cocok dengan rute mana pun yang ditentukan dalam aplikasi Anda. Namun, ada kalanya Anda perlu memicunya sendiri.
Ambil contoh rute yang didefinisikan sebagai GET /dogs/@breed
. Logika aplikasi Anda mungkin melibatkan pencarian database dan upaya mengambil catatan yang sesuai dengan nilai @breed
dalam permintaan HTTP yang masuk. Karena Fat-Free akan menerima nilai apa pun setelah awalan /dogs/
karena kehadiran token @breed
, menampilkan pesan HTTP 404 Not Found
secara terprogram menjadi perlu ketika program tidak menemukan kecocokan apa pun di database kami. Untuk melakukannya, gunakan perintah berikut:-
$ f3 -> error ( 404 );
Arsitektur Fat-Free didasarkan pada konsep bahwa URI HTTP mewakili sumber daya Web abstrak (tidak terbatas pada HTML) dan setiap sumber daya dapat berpindah dari satu status aplikasi ke status aplikasi lainnya. Oleh karena itu, F3 tidak memiliki batasan apa pun dalam cara Anda menyusun aplikasi. Jika Anda lebih suka menggunakan pola Model-View-Controller, F3 dapat membantu Anda mengelompokkan komponen aplikasi agar tetap berpegang pada paradigma ini. Di sisi lain, kerangka kerja ini juga mendukung pola Representasi-Metode Sumber Daya, dan penerapannya lebih mudah.
Berikut ini contoh antarmuka ReST:-
class Item {
function get () {}
function post () {}
function put () {}
function delete () {}
}
$ f3 = require ( ' lib/base.php ' );
$ f3 -> map ( ' /cart/@item ' , ' Item ' );
$ f3 -> run ();
Metode $f3->map()
Fat-Free menyediakan antarmuka ReST dengan memetakan metode HTTP dalam rute ke metode setara dari suatu objek atau kelas PHP. Jika aplikasi Anda menerima permintaan HTTP masuk seperti GET /cart/123
, Fat-Free akan secara otomatis mentransfer kontrol ke metode get()
objek atau kelas. Di sisi lain, permintaan POST /cart/123
akan dialihkan ke metode post()
kelas Item
.
Catatan: Browser tidak menerapkan metode HTTP PUT
dan DELETE
dalam bentuk HTML biasa. Metode ini dan metode ReST lainnya ( HEAD
, dan CONNECT
) hanya dapat diakses melalui panggilan AJAX ke server.
Jika kerangka kerja menerima permintaan HTTP untuk rute yang dipetakan ke metode yang tidak diimplementasikan oleh kelas (mungkin Anda membuat kesalahan dalam pemetaan rute, atau metode tersebut belum ditulis), kerangka kerja akan menghasilkan HTTP 405 Method Not Allowed
Kesalahan HTTP 405 Method Not Allowed
.
Jika klien meminta OPTIONS
HTTP untuk sumber daya URL, F3 merespons dengan header HTTP yang sesuai yang menunjukkan metode mana yang diperbolehkan untuk sumber daya tersebut (HEAD, GET, PUT, dll). Kerangka kerja tidak akan memetakan permintaan OPTIONS
ke suatu kelas.
Fat-Free memiliki cara untuk memuat kelas hanya pada saat Anda membutuhkannya, sehingga kelas tersebut tidak menghabiskan lebih banyak memori daripada segmen tertentu yang dibutuhkan aplikasi Anda. Dan Anda tidak perlu menulis daftar panjang pernyataan include
atau require
hanya untuk memuat kelas PHP yang disimpan di file berbeda dan lokasi berbeda. Kerangka kerja ini dapat melakukan ini secara otomatis untuk Anda. Simpan saja file Anda (satu kelas per file) dalam folder dan beri tahu kerangka kerja untuk secara otomatis memuat file yang sesuai setelah Anda memanggil metode di kelas: -
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
Anda dapat menetapkan lokasi berbeda untuk kelas yang dimuat secara otomatis dengan mengubah nilai variabel global AUTOLOAD
. Anda juga dapat memiliki beberapa jalur muat otomatis. Jika kelas Anda terorganisir dan berada di folder yang berbeda, Anda dapat menginstruksikan kerangka kerja untuk memuat kelas yang sesuai secara otomatis ketika metode statis dipanggil atau ketika sebuah objek dipakai. Ubah variabel AUTOLOAD
dengan cara ini: -
$ f3 -> set ( ' AUTOLOAD ' , ' admin/autoload/; user/autoload/; default/ ' );
Penting: Kecuali untuk ekstensi .php, nama kelas dan nama file harus sama, agar kerangka kerja dapat memuat kelas Anda secara otomatis dengan benar. Nama dasar file ini harus sama dengan pemanggilan kelas Anda, misalnya F3 akan mencari Foo/BarBaz.php
atau foo/barbaz.php
ketika mendeteksi pernyataan new FooBarBaz
di aplikasi Anda.
AUTOLOAD
memungkinkan hierarki kelas berada di subfolder dengan nama serupa, jadi jika Anda ingin kerangka kerja memuat secara otomatis kelas dengan spasi nama yang dipanggil dengan cara berikut:-
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
$ obj = new Gadgets iPad ;
Anda dapat membuat hierarki folder yang mengikuti struktur yang sama. Dengan asumsi /var/www/html/
adalah root Web Anda, maka F3 akan mencari kelas di /var/www/html/autoload/gadgets/ipad.php
. File ipad.php
harus memiliki kode minimum berikut:-
namespace Gadgets ;
class iPad {}
Ingat: Semua nama direktori di Fat-Free harus diakhiri dengan garis miring. Anda dapat menetapkan jalur pencarian untuk autoloader sebagai berikut: -
$ f3 -> set ( ' AUTOLOAD ' , ' main/;aux/ ' );
F3, sebagai kerangka kerja yang sadar akan namespace, memungkinkan Anda menggunakan metode di kelas dengan namespace sebagai pengendali rute, dan ada beberapa cara untuk melakukannya. Untuk memanggil metode statis:-
$ f3 -> set ( ' AUTOLOAD ' , ' classes/ ' );
$ f3 -> route ( ' GET|POST / ' , ' MainHome::show ' );
Kode di atas akan memanggil metode statis show()
dari kelas Home
dalam namespace Main
. Kelas Home
harus disimpan di folder classes/main/home.php
agar dapat dimuat secara otomatis.
Jika Anda lebih suka bekerja dengan objek:-
$ f3 -> route ( ' GET|POST / ' , ' MainHome->show ' );
akan membuat instance kelas Home
saat runtime dan memanggil metode show()
setelahnya.
F3 memiliki beberapa pendengar peristiwa perutean yang mungkin membantu Anda meningkatkan aliran dan struktur kelas pengontrol. Katakanlah Anda memiliki rute yang ditentukan sebagai berikut: -
$ f3 -> route ( ' GET / ' , ' Main->home ' );
Jika aplikasi menerima permintaan HTTP yang cocok dengan rute di atas, F3 akan membuat instance Main
, namun sebelum mengeksekusi metode home()
, framework akan mencari metode di kelas ini yang bernama beforeRoute()
. Jika ditemukan, F3 menjalankan kode yang terdapat dalam event handler beforeRoute()
sebelum mentransfer kontrol ke metode home()
. Setelah ini selesai, kerangka kerja mencari event handler afterRoute()
. Seperti beforeRoute()
, metode ini akan dieksekusi jika ditentukan.
Inilah barang F3 lainnya:-
$ f3 -> route ( ' GET /products/@action ' , ' Products->@action ' );
Jika aplikasi Anda menerima permintaan, misalnya /products/itemize
, F3 akan mengekstrak string 'itemize'
dari URL dan meneruskannya ke token @action
di pengendali rute. F3 kemudian akan mencari kelas bernama Products
dan menjalankan metode itemize()
.
Penangan rute dinamis mungkin memiliki berbagai bentuk: -
// static method
$ f3 -> route ( ' GET /public/@genre ' , ' Main::@genre ' );
// object mode
$ f3 -> route ( ' GET /public/@controller/@action ' , ' @controller->@action ' );
F3 memicu kesalahan HTTP 404 Not Found
saat runtime jika tidak dapat mentransfer kontrol ke kelas atau metode yang terkait dengan rute saat ini, yaitu kelas atau metode yang tidak ditentukan.
Pola perutean mungkin berisi pengubah yang mengarahkan kerangka kerja untuk mendasarkan keputusan peruteannya pada jenis permintaan HTTP: -
$ f3 -> route ( ' GET /example [ajax] ' , ' Page->getFragment ' );
$ f3 -> route ( ' GET /example [sync] ' , ' Page->getFull ' );
Pernyataan pertama akan merutekan permintaan HTTP ke panggilan balik Page->getFragment()
hanya jika header X-Requested-With: XMLHttpRequest
(objek AJAX) diterima oleh server. Jika permintaan biasa (sinkron) terdeteksi, F3 akan turun ke pola pencocokan berikutnya, dan dalam hal ini ia mengeksekusi callback Page->getFull()
.
Jika tidak ada pengubah yang ditentukan dalam pola perutean, maka jenis permintaan AJAX dan sinkron dirutekan ke penangan yang ditentukan.
Pengubah pola rute juga dikenali oleh $f3->map()
.
Variabel yang didefinisikan dalam Bebas Lemak bersifat global, yaitu dapat diakses oleh komponen MVC apa pun. Framework global tidak identik dengan global PHP. Variabel F3 bernama content
tidak identik dengan $content
PHP. F3 adalah bahasa khusus domain dan memelihara tabel simbol terpisah untuk variabel sistem dan aplikasi. Kerangka kerja ini, seperti setiap program berorientasi objek yang dirancang dengan baik, tidak mencemari namespace global PHP dengan konstanta, variabel, fungsi, atau kelas yang mungkin bertentangan dengan aplikasi apa pun. Tidak seperti framework lain, F3 tidak menggunakan pernyataan define()
PHP. Semua konstanta kerangka terbatas pada kelas.
Untuk memberikan nilai pada variabel Bebas Lemak:
$ f3 -> set ( ' var ' ,value); // or
$ f3 -> var =value;
$ f3 -> set ( ' hello.world ' , ' good morning ' ); // translates to : 'hello' == array ( 'world' = > 'good morning' )
$ f3 ->{ ' hello.world ' }= ' good morning ' ; // same as prior statement
Catatan: Variabel Bebas Lemak menerima semua tipe data PHP, termasuk objek dan fungsi anonim.
Untuk menetapkan beberapa variabel sekaligus:
$ f3 -> mset (
[
' foo ' => ' bar ' ,
' baz ' => 123
]
);
Untuk mengambil nilai variabel kerangka kerja bernama var
:-
echo $ f3 -> get ( ' var ' ); // or
echo $ f3 -> var ;
Untuk menghapus variabel Bebas Lemak dari memori jika Anda tidak membutuhkannya lagi (buang agar tidak mengganggu fungsi/metode Anda yang lain), gunakan metode:-
$ f3 -> clear ( ' var ' ); // or
unset( $ f3 -> var );
Untuk mengetahui apakah suatu variabel telah didefinisikan sebelumnya: -
$ f3 -> exists ( ' var ' ) //
isset ( $ f3 -> var )
F3 memelihara tabel simbolnya sendiri untuk variabel kerangka kerja dan aplikasi, yang tidak bergantung pada PHP. Beberapa variabel dipetakan ke PHP global. SESSION
Bebas Lemak setara dengan $_SESSION
, dan REQUEST
dipetakan ke $_REQUEST
. Disarankan untuk menggunakan variabel kerangka kerja, bukan PHP, untuk membantu Anda mentransfer data di berbagai fungsi, kelas, dan metode. Mereka juga memiliki keuntungan lain: -
SESSION
juga mengubah $_SESSION
yang mendasari PHP. Mengubah yang terakhir juga mengubah kerangka kerja. Bebas Lemak tidak hanya menyimpan penyimpanan bodoh untuk variabel dan nilainya. Itu juga dapat mengotomatiskan manajemen sesi dan hal-hal lainnya. Menetapkan atau mengambil nilai melalui variabel SESSION
F3 akan memulai sesi secara otomatis. Jika Anda menggunakan $_SESSION
(atau fungsi terkait sesi) secara langsung, alih-alih menggunakan variabel kerangka kerja SESSION
, aplikasi Anda bertanggung jawab untuk mengelola sesi.
Sebagai aturan, variabel kerangka kerja tidak bertahan di antara permintaan HTTP. Hanya SESSION
dan COOKIE
(dan elemen-elemennya) yang dipetakan ke variabel global $_SESSION
dan $_COOKIE
PHP yang dikecualikan dari sifat HTTP tanpa kewarganegaraan.
Ada beberapa variabel global yang telah ditentukan sebelumnya yang digunakan secara internal oleh Fat-Free, dan Anda pasti dapat menggunakannya dalam aplikasi Anda. Pastikan Anda tahu apa yang Anda lakukan. Mengubah beberapa variabel global Bebas Lemak dapat mengakibatkan perilaku kerangka kerja yang tidak terduga.
Kerangka kerja ini memiliki beberapa variabel untuk membantu Anda mengatur file dan struktur direktori. Kita telah melihat bagaimana kita dapat mengotomatiskan pemuatan kelas dengan menggunakan AUTOLOAD
. Ada variabel global UI
, yang berisi jalur yang menunjuk ke lokasi tampilan/templat HTML Anda. DEBUG
adalah variabel lain yang akan sering Anda gunakan selama pengembangan aplikasi dan digunakan untuk mengatur verbositas jejak kesalahan.
Lihat Referensi Cepat jika Anda memerlukan daftar lengkap variabel kerangka kerja bawaan.
Variabel kerangka kerja dapat berisi sejumlah huruf, angka, dan garis bawah. Itu harus dimulai dengan karakter alfa dan tidak boleh ada spasi. Nama variabel peka huruf besar-kecil.
F3 menggunakan huruf besar semua untuk variabel global internal yang telah ditentukan sebelumnya. Tidak ada yang menghentikan Anda untuk menggunakan nama variabel yang terdiri dari huruf kapital semua dalam program Anda sendiri, namun sebagai aturan umum, gunakan huruf kecil (atau camelCase) saat Anda menyiapkan variabel Anda sendiri sehingga Anda dapat menghindari kemungkinan konflik dengan rilis kerangka kerja saat ini dan masa depan. .
Anda tidak boleh menggunakan kata-kata khusus PHP seperti if
, for
, class
, default
, dll. sebagai nama variabel kerangka kerja. Hal ini dapat menyebabkan hasil yang tidak terduga.
F3 juga menyediakan sejumlah alat untuk membantu Anda dengan variabel kerangka kerja.
$ f3 -> set ( ' a ' , ' fire ' );
$ f3 -> concat ( ' a ' , ' cracker ' );
echo $ f3 -> get ( ' a ' ); // returns the string 'firecracker'
$ f3 -> copy ( ' a ' , ' b ' );
echo $ f3 -> get ( ' b ' ); // returns the same string : 'firecracker'
F3 juga menyediakan beberapa metode primitif untuk bekerja dengan variabel array:-
$ f3 -> set ( ' colors ' ,[ ' red ' , ' blue ' , ' yellow ' ]);
$ f3 -> push ( ' colors ' , ' green ' ); // works like PHP ' s array_push ()
echo $ f3 -> pop ( ' colors ' ); // returns 'green'
$ f3 -> unshift ( ' colors ' , ' purple ' ); // similar to array_unshift ()
echo $ f3 -> shift ( ' colors ' ); // returns 'purple'
$ f3 -> set ( ' grays ' ,[ ' light ' , ' dark ' ]);
$ result = $ f3 -> merge ( ' colors ' , ' grays ' ); // merges the two arrays
Tidak seperti framework lain yang memiliki struktur folder kaku, F3 memberi Anda banyak fleksibilitas. Anda dapat memiliki struktur folder yang terlihat seperti ini (kata-kata dalam tanda kurung dengan huruf kapital semua mewakili variabel kerangka F3 yang perlu diubah): -
/ (your Web root, where index.php is located)
app/ (application files)
dict/ (LOCALES, optional)
controllers/
logs/ (LOGS, optional)
models/
views/ (UI)
css/
js/
lib/ (you can store base.php here)
tmp/ (TEMP, used by the framework)
cache/ (CACHE)
Jangan ragu untuk mengatur file dan direktori Anda sesuka Anda. Cukup atur variabel global F3 yang sesuai. Jika Anda menginginkan situs yang benar-benar aman, Fat-Free bahkan memungkinkan Anda menyimpan semua file Anda di direktori yang tidak dapat diakses oleh Web. Satu-satunya persyaratan adalah Anda membiarkan index.php
, .htaccess
dan file publik Anda, seperti CSS, JavaScript, gambar, dll. di jalur yang terlihat oleh browser Anda.
Bebas Lemak menghasilkan halaman kesalahan HTML-nya sendiri, dengan jejak tumpukan untuk membantu Anda melakukan debug. Berikut ini contohnya:-
Kesalahan Server Internal
strpos() mengharapkan setidaknya 2 parameter, 0 diberikan
• var/html/dev/main.php:96 strpos() • var/html/dev/index.php:16 Base->run()
Jika Anda merasa ini agak terlalu sederhana atau ingin melakukan hal lain ketika kesalahan terjadi, Anda dapat membuat penangan kesalahan khusus Anda sendiri:-
$ f3 -> set ( ' ONERROR ' ,
function ( $ f3 ) {
// custom error handler code goes here
// use this if you want to display errors in a
// format consistent with your site ' s theme
echo $ f3 -> get ( ' ERROR.status ' );
}
);
F3 menyimpan variabel global yang berisi rincian kesalahan terbaru yang terjadi pada aplikasi Anda. Variabel ERROR
adalah array yang terstruktur sebagai berikut: -
ERROR.code - displays the error code (404, 500, etc.)
ERROR.status - header and page title
ERROR.text - error context
ERROR.trace - stack trace
Saat mengembangkan aplikasi Anda, yang terbaik adalah mengatur tingkat debug ke maksimum sehingga Anda dapat melacak semua kesalahan hingga akar penyebabnya:-
$ f3 -> set ( ' DEBUG ' , 3 );
Cukup masukkan perintah dalam urutan bootstrap aplikasi Anda.
Setelah aplikasi Anda siap dirilis, cukup hapus pernyataan dari aplikasi Anda, atau ganti dengan:-
$ f3 -> set ( ' DEBUG ' , 0 );
Ini akan menyembunyikan keluaran pelacakan tumpukan di laman kesalahan HTML apa pun yang dihasilkan sistem (karena tidak dimaksudkan untuk dilihat oleh pengunjung situs Anda).
DEBUG
dapat memiliki nilai mulai dari 0 (pelacakan tumpukan ditekan) hingga 3 (paling bertele-tele).
Jangan lupa! Pelacakan tumpukan mungkin berisi jalur, nama file, perintah database, nama pengguna, dan kata sandi. Anda mungkin mengekspos situs Web Anda terhadap risiko keamanan yang tidak perlu jika Anda gagal mengatur variabel global DEBUG
ke 0 di lingkungan produksi.
Jika aplikasi Anda perlu dikonfigurasi pengguna, F3 menyediakan metode praktis untuk membaca file konfigurasi guna menyiapkan aplikasi Anda. Dengan cara ini, Anda dan pengguna Anda dapat mengubah aplikasi tanpa mengubah kode PHP apa pun.
Daripada membuat skrip PHP yang berisi kode contoh berikut:-
$ f3 -> set ( ' num ' , 123 );
$ f3 -> set ( ' str ' , ' abc ' );
$ f3 -> set ( ' hash ' ,[ ' x ' => 1 , ' y ' => 2 , ' z ' => 3 ]);
$ f3 -> set ( ' items ' ,[ 7 , 8 , 9 ]);
$ f3 -> set ( ' mix ' ,[ ' this ' , 123.45 , FALSE ]);
Anda dapat membuat file konfigurasi yang melakukan hal yang sama: -
[globals]
num =123
; this is a regular string
str =abc
; another way of assigning strings
str = " abc "
; this is an array
hash[x]=1
hash[y]=2
hash[z]=3
; dot-notation is recognized too
hash.x =1
hash.y =2
hash.z =3
; this is also an array
items =7,8,9
; array with mixed elements
mix = " this " ,123.45,FALSE
Daripada pernyataan $f3->set()
yang panjang dalam kode Anda, Anda dapat menginstruksikan kerangka kerja untuk memuat file konfigurasi sebagai pengganti kode. Mari simpan teks di atas sebagai setup.cfg. Kami kemudian dapat menyebutnya dengan sederhana: -
$ f3 -> config ( ' setup.cfg ' );
Nilai string tidak perlu dikutip, kecuali Anda ingin menyertakan spasi di awal atau di akhir. Jika koma harus diperlakukan sebagai bagian dari string, sertakan string menggunakan tanda kutip ganda - jika tidak, nilai akan diperlakukan sebagai array (koma digunakan sebagai pemisah elemen array). String dapat menjangkau beberapa baris: -
[globals]
str = " this is a
very long
string "
F3 juga memberi Anda kemampuan untuk menentukan rute HTTP dalam file konfigurasi:-
[routes]
GET /=home
GET / 404 =App->page404
GET /page/@ num =Page->@controller
Peta rute juga dapat ditentukan dalam file konfigurasi: -
[maps]
/ blog =BlogLogin
/blog/@ controller =Blog@controller
Header bagian [globals]
, [routes]
, dan [maps]
wajib diisi. Anda dapat menggabungkan kedua bagian dalam satu file konfigurasi - meskipun disarankan memiliki [routes]
dan [maps]
dalam file terpisah. Dengan cara ini Anda dapat mengizinkan pengguna akhir untuk mengubah beberapa tanda khusus aplikasi, dan pada saat yang sama membatasi mereka agar tidak mengganggu logika perutean Anda.
Antarmuka pengguna seperti halaman HTML harus independen dari kode PHP dasar yang terkait dengan perutean dan logika bisnis. Ini adalah dasar dari paradigma MVC. Revisi dasar seperti mengonversi <h3>
menjadi <p>
seharusnya tidak menuntut perubahan pada kode aplikasi Anda. Dengan cara yang sama, mengubah rute sederhana seperti GET /about
menjadi GET /about-us
seharusnya tidak berdampak apa pun pada antarmuka pengguna dan logika bisnis Anda, (tampilan dan model dalam MVC, atau representasi dan metode dalam RMR).
Mencampur konstruksi pemrograman dan komponen antarmuka pengguna dalam satu file, seperti pengkodean spageti, menjadikan pemeliharaan aplikasi di masa depan sebagai mimpi buruk.
F3 mendukung PHP sebagai mesin template. Lihatlah fragmen HTML ini yang disimpan sebagai template.htm
:-.
< p > Hello, < ?php echo $name; ? > ! </ p >
Jika tag pendek diaktifkan di server Anda, ini juga akan berfungsi:-
< p > Hello, < ?= $name ? > </ p >
Untuk menampilkan template ini, Anda dapat memiliki kode PHP yang terlihat seperti ini (disimpan dalam file yang terpisah dari templat):-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ view = new View ;
echo $ view -> render ( ' template.htm ' );
// Previous two lines can be shortened to : -
// echo View :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();
Satu -satunya masalah dengan menggunakan PHP sebagai mesin templat, karena kode PHP tertanam dalam file -file ini, adalah upaya sadar yang diperlukan untuk tetap pada pedoman pemisahan kekhawatiran dan menahan godaan pencampuran logika bisnis dengan antarmuka pengguna Anda.
Sebagai alternatif untuk PHP, Anda dapat menggunakan mesin template F3 sendiri. Fragmen HTML di atas dapat ditulis ulang sebagai:-
< p > Hello, {{ @name }}! </ p >
dan kode yang diperlukan untuk melihat templat ini:-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ template = new Template ;
echo $ template -> render ( ' template.htm ' );
// Above lines can be written as : -
// echo Template :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();
Seperti routing token yang digunakan untuk menangkap variabel dalam URL (masih ingat contoh GET /brew/@count
di bagian sebelumnya?), Token template F3 dimulai dengan simbol @
diikuti oleh serangkaian huruf dan angka yang terlampir dalam kawat gigi keriting. Karakter pertama harus alfa. Token template memiliki korespondensi satu-ke-satu dengan variabel kerangka kerja. Kerangka kerja secara otomatis menggantikan token dengan nilai yang disimpan dalam variabel dengan nama yang sama.
Dalam contoh kami, F3 menggantikan token @name
di templat kami dengan nilai yang kami tetapkan ke variabel nama. Saat runtime, output dari kode di atas adalah:-
< p > Hello, world </ p >
Khawatir tentang kinerja template F3? Saat runtime, kerangka kerja mem-parsing dan mengkompilasi/mengonversi template F3 ke kode php pertama kali ditampilkan melalui $template->render()
. Kerangka kerja kemudian menggunakan kode yang dikompilasi ini di semua panggilan berikutnya. Oleh karena itu, kinerja harus sama dengan templat PHP, jika tidak lebih baik karena optimasi kode yang dilakukan oleh kompiler template ketika templat yang lebih kompleks terlibat.
Apakah Anda menggunakan mesin template PHP atau sendiri, rendering template dapat secara signifikan lebih cepat jika Anda memiliki APC, Wincache atau Xcache yang tersedia di server Anda.
Seperti disebutkan sebelumnya, variabel kerangka kerja dapat menampung tipe data PHP apa pun. Namun, penggunaan tipe data non-skalar dalam templat F3 dapat menghasilkan hasil yang aneh jika Anda tidak hati-hati. Ekspresi dalam kawat gigi keriting akan selalu dievaluasi dan dikonversi menjadi string. Anda harus membatasi variabel antarmuka pengguna Anda untuk skalar sederhana:- string
, integer
, boolean
atau tipe data float
.
Tapi bagaimana dengan array? Fat-bebas mengenali array dan Anda dapat menggunakannya di templat Anda. Anda dapat memiliki sesuatu seperti:-
< p > {{ @buddy[0] }}, {{ @buddy[1] }}, and {{ @buddy[2] }} </ p >
Dan mengisi array @buddy
dalam kode PHP Anda sebelum melayani template:-
$ f3 -> set ( ' buddy ' ,[ ' Tom ' , ' Dick ' , ' Harry ' ]);
Namun, jika Anda cukup memasukkan {{ @buddy }}
di template Anda, PHP akan menggantinya dengan 'Array'
karena mengubah token menjadi string. PHP, di sisi lain, akan menghasilkan Array to string conversion
saat runtime.
F3 memungkinkan Anda untuk menyematkan ekspresi dalam templat. Ekspresi ini dapat mengambil berbagai bentuk, seperti perhitungan aritmatika, ekspresi boolean, konstanta php, dll. Berikut adalah beberapa contoh:-
{{ 2*(@page-1) }}
{{ (int)765.29+1.2e3 }}
< option value =" F " {{ @active? 'selected=" selected "':'' }} > Female </ option >
{{ var_dump(@xyz) }}
< p > That is {{ preg_match('/Yes/i',@response)?'correct':'wrong' }}! </ p >
{{ @obj- > property }}
Catatan tambahan tentang ekspresi array: Perhatikan bahwa @foo.@bar
adalah gabungan string $foo.$bar
), sedangkan @foo.bar
diterjemahkan menjadi $foo['bar']
. Jika $foo[$bar]
adalah yang Anda maksudkan, gunakan notasi reguler @foo[@bar]
.
Variabel kerangka kerja juga dapat berisi fungsi anonim:
$ f3 -> set ( ' func ' ,
function ( $ a , $ b ) {
return $ a . ' , ' . $ b ;
}
);
Mesin Template F3 akan menafsirkan token seperti yang diharapkan, jika Anda menentukan ekspresi berikut:
{{ @func('hello','world') }}
Substitusi variabel sederhana adalah satu hal yang dimiliki semua mesin template. Bebas lemak memiliki lebih banyak lengan bajunya:-
< include href =" header.htm " />
Petunjuk akan menanamkan isi header.htm Template pada posisi yang tepat di mana arahan dinyatakan. Anda juga dapat memiliki konten dinamis dalam bentuk:-
< include href =" {{ @content }} " />
Penggunaan praktis untuk arahan templat tersebut adalah ketika Anda memiliki beberapa halaman dengan tata letak HTML yang umum tetapi dengan konten yang berbeda. Menginstruksikan kerangka kerja untuk memasukkan sub-template ke dalam template utama Anda sesederhana menulis kode PHP berikut:-
// switch content to your blog sub - template
$ f3 -> set ( ' content ' , ' blog.htm ' );
// in another route , switch content to the wiki sub - template
$ f3 -> set ( ' content ' , ' wiki.htm ' );
Sub-templat pada gilirannya dapat berisi sejumlah arahan. F3 memungkinkan templat bersarang tanpa batas.
Anda dapat menentukan nama file dengan sesuatu selain ekstensi file .htm atau .html, tetapi lebih mudah untuk mempratinjau mereka di browser web Anda selama fase pengembangan dan debugging. Mesin template tidak terbatas pada rendering file HTML. Bahkan Anda dapat menggunakan mesin template untuk membuat jenis file lainnya.
Petunjuk <include>
juga memiliki atribut Opsional if
Anda dapat menentukan kondisi yang perlu dipenuhi sebelum sub-template dimasukkan:-
< include if =" {{ count(@items) }} " href =" items.htm " />
Selama proses menulis/men-debug program bertenaga F3 dan merancang templat, mungkin ada contoh ketika menonaktifkan tampilan blok HTML mungkin berguna. Anda dapat menggunakan arahan <exclude>
untuk tujuan ini:-
< exclude >
< p > A chunk of HTML we don't want displayed at the moment </ p >
</ exclude >
Itu seperti <!-- comment -->
tag komentar html, tetapi arahan <exclude>
membuat blok html benar-benar tidak terlihat setelah template diterjemahkan.
Berikut cara lain untuk mengecualikan konten template atau menambahkan komentar:-
{* < p > A chunk of HTML we don't want displayed at the moment </ p > *}
Fitur templat lain yang berguna adalah arahan <check>
. Ini memungkinkan Anda untuk menanamkan fragmen HTML tergantung pada evaluasi kondisi tertentu. Berikut beberapa contoh:-
< check if =" {{ @page=='Home' }} " >
< false > < span > Inserted if condition is false </ span > </ false >
</ check >
< check if =" {{ @gender=='M' }} " >
< true >
< div > Appears when condition is true </ div >
</ true >
< false >
< div > Appears when condition is false </ div >
</ false >
</ check >
Anda dapat memiliki banyak arahan <check>
bersarang seperti yang Anda butuhkan.
Ekspresi F3 di dalam atribut IF yang setara dengan NULL
, string kosong, FALSE
boolean, array kosong atau nol, secara otomatis memanggil <false>
. Jika template Anda tidak memiliki blok <false>
, maka tag pembukaan dan penutupan <true>
adalah opsional:-
< check if =" {{ @loggedin }} " >
< p > HTML chunk to be included if condition is true </ p >
</ check >
Bebas lemak juga dapat menangani blok html berulang:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " >
< p > {{ trim(@fruit) }} </ p >
</ repeat >
Atribut group
@fruits
di dalam arahan <repeat>
harus berupa array dan harus diatur dalam kode PHP Anda sesuai:-
$ f3 -> set ( ' fruits ' ,[ ' apple ' , ' orange ' , ' banana ' ]);
Tidak ada yang diperoleh dengan menetapkan nilai ke @fruit
dalam kode aplikasi Anda. Bebas lemak mengabaikan nilai prasetel yang mungkin dimilikinya karena menggunakan variabel untuk mewakili item saat ini selama iterasi atas grup. Output dari fragmen template html di atas dan kode PHP yang sesuai menjadi:-
< p > apple </ p >
< p > orange </ p >
< p > banana </ p >
Kerangka kerja ini memungkinkan bersarang tanpa batas dari blok <repeat>
:-
< repeat group =" {{ @div }} " key =" {{ @ikey }} " value =" {{ @idiv }} " >
< div >
< p > < span > < b > {{ @ikey }} </ b > </ span > </ p >
< p >
< repeat group =" {{ @idiv }} " value =" {{ @ispan }} " >
< span > {{ @ispan }} </ span >
</ repeat >
</ p >
</ div >
</ repeat >
Terapkan perintah F3 berikut:-
$ f3 -> set ( ' div ' ,
[
' coffee ' =>[ ' arabica ' , ' barako ' , ' liberica ' , ' kopiluwak ' ],
' tea ' =>[ ' darjeeling ' , ' pekoe ' , ' samovar ' ]
]
);
Akibatnya, Anda mendapatkan fragmen HTML berikut:-
< div >
< p > < span > < b > coffee </ b > </ span > </ p >
< p >
< span > arabica </ span >
< span > barako </ span >
< span > liberica </ span >
< span > kopiluwak </ span >
< p >
</ div >
< div >
< p > < span > < b > tea </ b > </ span > </ p >
< p >
< span > darjeeling </ span >
< span > pekoe </ span >
< span > samovar </ span >
</ p >
</ div >
Luar biasa, bukan? Dan satu -satunya hal yang harus Anda lakukan dalam PHP adalah menentukan isi dari div
F3 tunggal untuk menggantikan token @div
. Bebas lemak membuat desain pemrograman dan template web sangat mudah.
Atribut value
Petunjuk Template <repeat>
Template mengembalikan nilai elemen saat ini dalam iterasi. Jika Anda perlu mendapatkan kunci array dari elemen saat ini, gunakan atribut key
sebagai gantinya. Atribut key
adalah opsional.
<repeat>
juga memiliki atribut penghitung opsional yang dapat digunakan sebagai berikut:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " counter =" {{ @ctr }} " >
< p class =" {{ @ctr%2?'odd':'even' }} " > {{ trim(@fruit) }} </ p >
</ repeat >
Secara internal, mesin templat F3 mencatat jumlah iterasi loop dan menyimpan nilai itu dalam variabel/token @ctr
, yang digunakan dalam contoh kami untuk menentukan klasifikasi ganjil/genap.
Jika Anda harus memasukkan token F3 di dalam bagian <script>
atau <style>
dari template Anda, kerangka kerja masih akan menggantikannya dengan cara yang biasa:-
< script type =" text/javascript " >
function notify ( ) {
alert ( 'You are logged in as: {{ @userID }}' ) ;
}
</ script >
Tag template embedding di dalam tag <script>
atau <style>
Anda tidak memerlukan penanganan khusus:-
< script type =" text/javascript " >
var discounts = [ ] ;
< repeat group = "{{ @rates }}" value = "{{ @rate }}" >
// whatever you want to repeat in Javascript, e.g.
discounts.push(" { { @ rate } } ");
</ repeat >
</ script >
Secara default, bebas lemak menggunakan set karakter UTF-8 kecuali diubah. Anda dapat mengesampingkan perilaku ini dengan mengeluarkan sesuatu seperti:-
$ f3 -> set ( ' ENCODING ' , ' ISO-8859-1 ' );
Setelah Anda menginformasikan kerangka set karakter yang diinginkan, F3 akan menggunakannya di semua templat HTML dan XML sampai diubah lagi.
Seperti yang disebutkan sebelumnya di bagian ini, kerangka kerja tidak terbatas pada templat HTML. Anda dapat memproses templat XML juga. Mekaniknya sangat mirip. Anda masih memiliki token {{ @variable }}
dan {{ expression }}
yang sama, <repeat>
, <check>
, <include>
, dan arahan <exclude>
yang Anda miliki. Cukup beri tahu F3 bahwa Anda melewati file XML alih-alih html:-
echo Template:: instance ()-> render ( ' template.xml ' , ' application/xml ' );
Argumen kedua mewakili tipe MIME dari dokumen yang diberikan.
Komponen tampilan MVC mencakup segala sesuatu yang tidak termasuk dalam model dan pengontrol, yang berarti presentasi Anda dapat dan harus mencakup semua jenis antarmuka pengguna, seperti RSS, email, RDF, FOAF, file teks, dll. Contohnya Di bawah ini menunjukkan cara memisahkan presentasi email Anda dari logika bisnis aplikasi Anda:-
MIME-Version: 1.0
Content-type: text/html; charset={{ @ENCODING }}
From: {{ @from }}
To: {{ @to }}
Subject: {{ @subject }}
< p > Welcome, and thanks for joining {{ @site }}! </ p >
Simpan template email di atas sebagai sambutan.txt. Kode F3 yang terkait adalah:-
$ f3 -> set ( ' from ' , ' <[email protected]> ' );
$ f3 -> set ( ' to ' , ' <[email protected]> ' );
$ f3 -> set ( ' subject ' , ' Welcome ' );
ini_set ( ' sendmail_from ' , $ f3 -> get ( ' from ' ));
mail (
$ f3 -> get ( ' to ' ),
$ f3 -> get ( ' subject ' ),
Template:: instance ()-> render ( ' email.txt ' , ' text/html ' )
);
Kiat: Ganti fungsi SMTP Mail () dengan imap_mail () Jika skrip Anda berkomunikasi dengan server IMAP.
Sekarang bukankah itu sesuatu? Tentu saja, jika Anda memiliki seikat penerima email, Anda akan menggunakan database untuk mengisi nama FirstName, LastName, dan email.
Berikut solusi alternatif menggunakan plug-in SMTP F3:-
$ mail = new SMTP ( ' smtp.gmail.com ' , 465 , ' SSL ' , ' [email protected] ' , ' secret ' );
$ mail -> set ( ' from ' , ' <[email protected]> ' );
$ mail -> set ( ' to ' , ' "Slasher" <[email protected]> ' );
$ mail -> set ( ' subject ' , ' Welcome ' );
$ mail -> send (Template:: instance ()-> render ( ' email.txt ' ));
F3 mendukung banyak bahasa di luar kotak.
Pertama, buat file kamus dengan struktur berikut (satu file per bahasa):-
<?php
return [
' love ' => ' I love F3 ' ,
' today ' => ' Today is {0,date} ' ,
' pi ' => ' {0,number} ' ,
' money ' => ' Amount remaining: {0,number,currency} '
];
Simpan sebagai dict/en.php
. Mari kita buat kamus lain, kali ini untuk bahasa Jerman. Simpan file sebagai dict/de.php
:-
<?php
return [
' love ' => ' Ich liebe F3 ' ,
' today ' => ' Heute ist {0,date} ' ,
' money ' => ' Restbetrag: {0,number,currency} '
];
Kamus tidak lebih dari pasangan nilai kunci. F3 secara otomatis membuat variabel kerangka kerja berdasarkan kunci dalam file bahasa. Dengan demikian, mudah untuk menanamkan variabel -variabel ini sebagai token di templat Anda. Menggunakan mesin template f3:-
< h1 > {{ @love }} </ h1 >
< p >
{{ @today,time() | format }}. < br />
{{ @money,365.25 | format }} < br />
{{ @pi }}
</ p >
Dan versi yang lebih panjang yang menggunakan PHP sebagai mesin templat:-
<?php $ f3 =Base:: instance (); ?>
<h1> <?php echo $ f3 -> get ( ' love ' ); ?> </h1>
<p>
<?php echo $ f3 -> get ( ' today ' , time ()); ?> .<br />
<?php echo $ f3 -> get ( ' money ' , 365.25 ); ?>
<?php echo $ f3 -> get ( ' pi ' ); ?>
</p>
Selanjutnya, kami menginstruksikan F3 untuk mencari kamus di dict/
folder:-
$ f3 -> set ( ' LOCALES ' , ' dict/ ' );
Tetapi bagaimana kerangka kerja menentukan bahasa mana yang akan digunakan? F3 akan mendeteksinya secara otomatis dengan melihat header permintaan HTTP terlebih dahulu, khususnya header Accept-Language
yang dikirim oleh browser.
Untuk mengganti perilaku ini, Anda dapat memicu F3 untuk menggunakan bahasa yang ditentukan oleh pengguna atau aplikasi:-
$ f3 -> set ( ' LANGUAGE ' , ' de ' );
Catatan: Dalam contoh di atas, PI kunci hanya ada di Kamus Bahasa Inggris. Kerangka kerja akan selalu menggunakan bahasa Inggris ( en
) sebagai fallback untuk mengisi kunci yang tidak ada dalam bahasa yang ditentukan (atau terdeteksi).
Anda juga dapat membuat file kamus untuk varian bahasa seperti en-US
, es-AR
, dll. Dalam hal ini, F3 akan menggunakan varian bahasa terlebih dahulu (seperti es-AR
). Jika ada kunci yang tidak ada dalam varian, kerangka kerja akan mencari kunci dalam bahasa root ( es
), maka gunakan file bahasa en
sebagai fallback akhir. Pasangan Nilai Kunci Kamus menjadi variabel F3 yang pernah direferensikan. Pastikan tombol tidak bertentangan dengan variabel kerangka kerja apa pun yang dipakai melalui $f3->set()
, $f3->mset()
, atau $f3->config()
.
Apakah Anda memperhatikan pola 'Today is {0,date}'
dalam contoh kami sebelumnya? Kemampuan multibahasa F3 bergantung pada aturan format string/pesan dari proyek ICU. Kerangka kerja menggunakan subsetnya sendiri dari implementasi pemformatan string ICU. Tidak perlu ekstensi intl
PHP diaktifkan di server.
Satu hal lagi: F3 juga dapat memuat file yang diformat gaya .ini sebagai kamus:-
love = " I love F3 "
today = " Today is {0,date} "
pi = " {0,number} "
money = " Amount remaining: {0,number,currency} "
Simpan sebagai dict/en.ini
sehingga kerangka kerja dapat memuatnya secara otomatis.
Secara default, baik penangan tampilan dan mesin template lolos dari semua variabel yang diberikan, yaitu dikonversi ke entitas HTML untuk melindungi Anda dari kemungkinan XSS dan serangan injeksi kode. Di sisi lain, jika Anda ingin meneruskan fragmen HTML yang valid dari kode aplikasi Anda ke template Anda:-
$ f3 -> set ( ' ESCAPE ' , FALSE );
Ini mungkin memiliki efek yang tidak diinginkan. Anda mungkin tidak ingin semua variabel melewati tanpa batas. Bebas lemak memungkinkan Anda untuk membuka variabel secara individual. Untuk template f3:-
{{ @html_content | raw }}
Dalam kasus templat PHP:-
<?php echo View:: instance ()-> raw ( $ html_content ); ?>
Sebagai tambahan untuk meningkatkan variabel F3 secara otomatis, kerangka kerja ini juga memberi Anda kebebasan untuk membersihkan input pengguna dari formulir HTML:-
$ f3 -> scrub ( $ _GET , ' p; br; span; div; a ' );
Perintah ini akan menghapus semua tag (kecuali yang ditentukan dalam argumen kedua) dan karakter yang tidak aman dari variabel yang ditentukan. Jika variabel berisi array, setiap elemen dalam array disanitasi secara rekursif. Jika tanda bintang (*) dilewatkan sebagai argumen kedua, $f3->scrub()
memungkinkan semua tag HTML untuk melewati yang tidak tersentuh dan cukup menghapus karakter kontrol yang tidak aman.
Fat-Free dirancang untuk membuat pekerjaan berinteraksi dengan database SQL menjadi mudah. Jika Anda bukan tipe yang membenamkan diri dalam detail tentang SQL, tetapi lebih condong ke arah penanganan data yang berorientasi objek, Anda dapat langsung ke bagian selanjutnya dari tutorial ini. Namun, jika Anda perlu melakukan beberapa tugas penanganan data dan pengoptimalan kinerja basis data yang kompleks, SQL adalah cara untuk pergi.
Membangun komunikasi dengan mesin SQL seperti MySQL, SQLite, SQL Server, Sybase, dan Oracle dilakukan dengan menggunakan perintah $f3->set()
yang sudah dikenal. Menghubungkan ke database SQLite adalah:-
$ db = new DB SQL ( ' sqlite:/absolute/path/to/your/database.sqlite ' );
Contoh lain, kali ini dengan mysql:-
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' p455w0rD '
);
OKE. Itu mudah, bukan? Begitulah cara Anda melakukan hal yang sama dalam PHP biasa. Anda hanya perlu mengetahui format DSN dari database yang Anda hubungkan. Lihat bagian PDO manual PHP.
Mari kita lanjutkan kode PHP kami:-
$ f3 -> set ( ' result ' , $ db -> exec ( ' SELECT brandName FROM wherever ' ));
echo Template:: instance ()-> render ( ' abc.htm ' );
Huh, apa yang terjadi di sini? Bukankah kita harus menyiapkan hal -hal seperti PDO, pernyataan, kursor, dll.? Jawaban sederhananya adalah: Anda tidak perlu melakukannya. F3 menyederhanakan semuanya dengan mengurus semua kerja keras di backend.
Kali ini kami membuat templat HTML seperti abc.htm
yang minimal berikut ini:-
< repeat group =" {{ @result }} " value =" {{ @item }} " >
< span > {{ @item.brandName }} </ span >
</ repeat >
Dalam kebanyakan kasus, set perintah SQL harus cukup untuk menghasilkan hasil yang siap web sehingga Anda dapat menggunakan variabel array result
di templat Anda secara langsung. Bagaimanapun, bebas lemak tidak akan menghentikan Anda untuk masuk ke internal SQL Handler. Faktanya, kelas DBSQL
F3 berasal langsung dari kelas PDO
PHP, sehingga Anda masih memiliki akses ke komponen PDO yang mendasari dan primitif yang terlibat dalam setiap proses, jika Anda memerlukan beberapa kontrol gandum halus.
Inilah contoh lain. Alih-alih satu pernyataan yang disediakan sebagai argumen untuk perintah $db->exec()
, Anda juga dapat melewati berbagai pernyataan SQL:-
$ db -> exec (
[
' DELETE FROM diet WHERE food="cola" ' ,
' INSERT INTO diet (food) VALUES ("carrot") ' ,
' SELECT * FROM diet '
]
);
F3 cukup pintar untuk mengetahui bahwa jika Anda melewati array instruksi SQL, ini menunjukkan transaksi batch SQL. Anda tidak perlu khawatir tentang rollback SQL dan berkomitmen karena kerangka kerja akan secara otomatis kembali ke keadaan awal database jika ada kesalahan yang terjadi selama transaksi. Jika berhasil, F3 melakukan semua perubahan yang dilakukan pada database.
Anda juga dapat memulai dan mengakhiri transaksi secara terprogram:-
$ db -> begin ();
$ db -> exec ( ' DELETE FROM diet WHERE food="cola" ' );
$ db -> exec ( ' INSERT INTO diet (food) VALUES ("carrot") ' );
$ db -> exec ( ' SELECT * FROM diet ' );
$ db -> commit ();
Rollback akan terjadi jika salah satu pernyataan mengalami kesalahan.
Untuk mendapatkan daftar semua instruksi basis data yang dikeluarkan:-
echo $ db -> log ();
Melewati argumen string ke pernyataan SQL penuh dengan bahaya. Pertimbangkan ini:-
$ db -> exec (
' SELECT * FROM users ' .
' WHERE username=" ' . $ f3 -> get ( ' POST.userID ' . ' " ' )
);
Jika POST
variable userID
tidak melalui proses sanitasi data apa pun, pengguna jahat dapat melewati string berikut dan merusak basis data Anda secara ireversibel:-
admin " ; DELETE FROM users; SELECT " 1
Untungnya, pertanyaan parameterisasi membantu Anda mengurangi risiko ini:-
$ db -> exec (
' SELECT * FROM users WHERE userID=? ' ,
$ f3 -> get ( ' POST.userID ' )
);
Jika F3 mendeteksi bahwa nilai parameter/token kueri adalah string, lapisan akses data yang mendasarinya lolos dari string dan menambahkan kutipan yang diperlukan.
Contoh kami di bagian sebelumnya akan jauh lebih aman dari injeksi SQL jika ditulis dengan cara ini:-
$ db -> exec (
[
' DELETE FROM diet WHERE food=:name ' ,
' INSERT INTO diet (food) VALUES (?) ' ,
' SELECT * FROM diet '
],
[
array ( ' :name ' => ' cola ' ),
array ( 1 => ' carrot ' ),
NULL
]
);
F3 dikemas dengan pemetaan (ORM) objek-relasional yang mudah digunakan yang duduk di antara aplikasi Anda dan data Anda-membuatnya jauh lebih mudah dan lebih cepat bagi Anda untuk menulis program yang menangani operasi data umum-seperti membuat, mengambil, memperbarui, dan menghapus informasi (CRUD) dari database SQL dan NoSQL. Mapper data melakukan sebagian besar pekerjaan dengan memetakan interaksi objek PHP ke kueri backend yang sesuai.
Misalkan Anda memiliki database MySQL yang ada yang berisi tabel pengguna aplikasi Anda. (SQLite, PostgreSQL, SQL Server, Sybase akan melakukannya dengan baik.) Itu akan dibuat dengan menggunakan perintah SQL berikut:-
CREATE TABLE users (
userID VARCHAR ( 30 ),
password VARCHAR ( 30 ),
visits INT ,
PRIMARY KEY (userID)
);
Catatan: MongoDB adalah mesin database NoSQL dan secara inheren skema-kurang. F3 memiliki implementasi NoSQL yang cepat dan ringan yang disebut JIG, yang menggunakan file datar php-serialized atau JSON-encoded. Lapisan abstraksi ini tidak memerlukan struktur data yang kaku. Bidang dapat bervariasi dari satu catatan ke catatan lainnya. Mereka juga dapat didefinisikan atau dijatuhkan dengan cepat.
Sekarang kembali ke SQL. Pertama, kami membangun komunikasi dengan database kami.
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' wh4t3v3r '
);
Untuk mengambil catatan dari tabel kami:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? ' , ' tarzan ' ]);
Baris pertama membuat objek data mapper yang berinteraksi dengan tabel users
di database kami. Di belakang tempat kejadian, F3 mengambil struktur tabel users
dan menentukan bidang mana yang didefinisikan sebagai kunci utama. Pada titik ini, objek Mapper belum mengandung data (keadaan kering) sehingga $user
tidak lebih dari objek terstruktur - tetapi berisi metode yang dibutuhkan untuk melakukan operasi dasar CRUD dan beberapa tambahan. Untuk mengambil catatan dari tabel pengguna kami dengan bidang userID
yang berisi nilai string tarzan
, kami menggunakan load() method
. Proses ini disebut "Auto-Hydrating" Objek Mapper Data.
Mudah, bukan? F3 memahami bahwa tabel SQL sudah memiliki definisi struktural yang ada di dalam mesin database itu sendiri. Tidak seperti kerangka kerja lainnya, F3 tidak memerlukan deklarasi kelas tambahan (kecuali jika Anda ingin memperluas pemetaan data agar sesuai dengan objek yang kompleks), tidak ada array PHP/objek yang redundan/objek pemetaan ke lapangan (duplikasi upaya), tidak ada generator kode (yang memerlukan kode Regenerasi Jika struktur basis data berubah), tidak ada file XML/YAML yang bodoh untuk mengonfigurasi model Anda, tidak ada perintah berlebihan hanya untuk mengambil satu catatan tunggal. Dengan F3, pengubah ukuran sederhana bidang varchar
di MySQL tidak menuntut perubahan dalam kode aplikasi Anda. Konsisten dengan MVC dan "Pemisahan Kekhawatiran", admin database memiliki banyak kontrol atas data (dan struktur) sebagai perancang templat memiliki atas templat HTML/XML.
Jika Anda lebih suka bekerja dengan database NoSQL, kesamaan dalam sintaks kueri dangkal. Dalam kasus Mapper Data MongoDB, kode yang setara adalah:-
$ db = new DB Mongo ( ' mongodb://localhost:27017 ' , ' testdb ' );
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' tarzan ' ]);
Dengan jig, sintaksnya mirip dengan mesin template F3:-
$ db = new DB Jig ( ' db/data/ ' , DB Jig:: FORMAT_JSON );
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? ' , ' tarzan ' ]);
Kerangka kerja secara otomatis memetakan visits
lapangan di tabel kami ke properti data mapper selama instantiasi objek, yaitu $user=new DBSQLMapper($db,'users');
. Setelah objek dibuat, $user->password
dan $user->userID
akan memetakan ke password
dan bidang userID
di tabel kami, masing-masing.
Anda tidak dapat menambahkan atau menghapus bidang yang dipetakan, atau mengubah struktur tabel menggunakan ORM. Anda harus melakukan ini di MySQL, atau mesin basis data apa pun yang Anda gunakan. Setelah Anda membuat perubahan di mesin database Anda, bebas lemak akan secara otomatis menyinkronkan struktur tabel baru dengan objek data mapper Anda saat Anda menjalankan aplikasi Anda.
F3 memperoleh struktur data mapper langsung dari skema database. Tidak ada dugaan yang terlibat. Ini memahami perbedaan antara mesin database MySQL, SQLite, MSSQL, Sybase, dan PostgreSQL.
Pengidentifikasi SQL tidak boleh menggunakan kata-kata yang dicadangkan, dan harus dibatasi pada karakter alfanumerik AZ
, 0-9
, dan simbol garis bawah ( _
). Nama kolom yang berisi spasi (atau karakter khusus) dan dikelilingi oleh kutipan dalam definisi data tidak kompatibel dengan ORM. Mereka tidak dapat direpresentasikan dengan benar sebagai sifat objek PHP.
Katakanlah kami ingin menambah jumlah kunjungan pengguna dan memperbarui catatan yang sesuai di tabel pengguna kami, kami dapat menambahkan kode berikut:-
$ user -> visits ++;
$ user -> save ();
Jika kami ingin memasukkan catatan, kami mengikuti proses ini:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
// or $ user = new DB Mongo Mapper ($ db , 'users' );
// or $ user = new DB Jig Mapper ($ db , 'users' );
$ user -> userID = ' jane ' ;
$ user -> password = password_hash ( ' secret ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> visits = 0 ;
$ user -> save ();
Kami masih menggunakan metode save()
yang sama. Tetapi bagaimana F3 tahu kapan catatan harus dimasukkan atau diperbarui? Pada saat objek Mapper Data dihidrasi secara otomatis dengan pengambilan rekaman, kerangka kerja tersebut melacak kunci utama catatan (atau _id
, dalam kasus MongoDB dan Jig) - jadi ia tahu catatan mana yang harus diperbarui atau dihapus - bahkan Ketika nilai -nilai tombol utama diubah. Mapper data yang dihidrasi secara terprogram - nilai -nilai yang tidak diambil dari database, tetapi diisi oleh aplikasi - tidak akan memiliki memori nilai -nilai sebelumnya dalam kunci utamanya. Hal yang sama berlaku untuk MongoDB dan Jig, tetapi menggunakan objek _id
sebagai referensi. Jadi, ketika kami membuat objek $user
di atas dan mengisi propertinya dengan nilai -nilai dari program kami - tanpa semua mengambil catatan dari tabel pengguna, F3 tahu bahwa ia harus memasukkan catatan ini.
Objek mapper tidak akan kosong setelah save()
. Jika Anda ingin menambahkan catatan baru ke database Anda, Anda harus terlebih dahulu mendehidrasi mapper:-
$ user -> reset ();
$ user -> userID = ' cheetah ' ;
$ user -> password = password_hash ( ' unknown ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> save ();
Memanggil save()
kedua kalinya tanpa memohon reset()
hanya akan memperbarui catatan yang saat ini ditunjukkan oleh mapper.
Meskipun masalah memiliki kunci utama di semua tabel di database Anda adalah argumentatif, F3 tidak menghentikan Anda dari membuat objek data mapper yang berkomunikasi dengan tabel yang tidak mengandung kunci primer. Satu -satunya kelemahan adalah: Anda tidak dapat menghapus atau memperbarui catatan yang dipetakan karena sama sekali tidak ada cara bagi F3 untuk menentukan catatan mana yang Anda maksud plus fakta bahwa referensi posisi tidak dapat diandalkan. ID baris tidak portabel di berbagai mesin SQL dan mungkin tidak dikembalikan oleh driver database PHP.
Untuk menghapus catatan yang dipetakan dari tabel kami, panggil metode erase()
pada mapper data yang dihidrasi secara otomatis. Misalnya:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? AND password=? ' , ' cheetah ' , ' ch1mp ' ]);
$ user -> erase ();
Sintaks kueri jig akan sedikit mirip:-
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? AND @password=? ' , ' cheetah ' , ' chimp ' ]);
$ user -> erase ();
Dan setara MongoDB adalah:-
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' cheetah ' , ' password ' => ' chimp ' ]);
$ user -> erase ();
Untuk mengetahui apakah mapper data kami terhidrasi atau tidak:-
if ( $ user -> dry ())
echo ' No record matching criteria ' ;
Kami telah meliput penangan CRUD. Ada beberapa metode tambahan yang mungkin Anda temukan berguna:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> copyFrom ( ' POST ' );
$ f3 -> get ( ' user ' )-> save ();
Perhatikan bahwa kita juga dapat menggunakan variabel bebas lemak sebagai wadah untuk objek mapper. Metode copyFrom()
menghidrasi objek mapper dengan elemen dari variabel array kerangka kerja, tombol array yang harus memiliki nama yang identik dengan properti objek mapper, yang pada gilirannya sesuai dengan nama bidang catatan. Jadi, ketika formulir web dikirimkan (dengan asumsi atribut nama HTML diatur ke userID
), isi bidang input tersebut ditransfer ke $_POST['userID']
, digandakan oleh f3 dalam variabel POST.userID
, dan disimpan ke Bidang yang dipetakan $user->userID
di database. Prosesnya menjadi sangat sederhana jika semuanya memiliki elemen yang dinamai secara identik. Konsistensi dalam tombol array, yaitu nama token template, nama variabel kerangka dan nama bidang adalah kunci :)
Di sisi lain, jika kami ingin mengambil catatan dan menyalin nilai bidang ke variabel kerangka kerja untuk digunakan nanti, seperti rendering template:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> load ([ ' userID=? ' , ' jane ' ]);
$ f3 -> get ( ' user ' )-> copyTo ( ' POST ' );
Kami kemudian dapat menetapkan {{ @post.userid}} ke atribut nilai bidang input yang sama. Singkatnya, bidang input HTML akan terlihat seperti ini:-
< input type =" text " name =" userID " value =" {{ @POST.userID }} " />
Metode data save()
, update()
, copyFrom()
dan varian parameterisasi load()
dan erase()
aman dari injeksi SQL.
Secara default, metode Mapper load()
data hanya mengambil catatan pertama yang cocok dengan kriteria yang ditentukan. Jika Anda memiliki lebih dari satu yang memenuhi kondisi yang sama dengan catatan pertama yang dimuat, Anda dapat menggunakan metode skip()
untuk navigasi:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ( ' visits>3 ' );
// Rewritten as a parameterized query
$ user -> load ([ ' visits>? ' , 3 ]);
// For MongoDB users : -
// $ user = new DB Mongo Mapper ($ db , 'users' );
// $ user - > load ([ 'visits' = > [ '$gt' = > 3 ]]);
// If you prefer Jig : -
// $ user = new DB Jig Mapper ($ db , 'users' );
// $ user - > load ( '@visits>?' , 3 );
// Display the userID of the first record that matches the criteria
echo $ user -> userID ;
// Go to the next record that matches the same criteria
$ user -> skip (); // Same as $ user - > skip ( 1 );
// Back to the first record
$ user -> skip (- 1 );
// Move three records forward
$ user -> skip ( 3 );
Anda dapat menggunakan $user->next()
sebagai pengganti untuk $user->skip()
, dan $user->prev()
jika Anda pikir itu memberi lebih banyak makna untuk $user->skip(-1)
.
Gunakan metode dry()
untuk memeriksa apakah Anda telah bermanuver di luar batas hasil yang ditetapkan. dry()
akan mengembalikan true jika Anda mencoba skip(-1)
pada catatan pertama. Ini juga akan mengembalikan true jika Anda skip(1)
pada catatan terakhir yang memenuhi kriteria pengambilan.
Metode load()
menerima argumen kedua: serangkaian opsi yang berisi pasangan nilai kunci seperti:-
$ user -> load (
[ ' visits>? ' , 3 ],
[
' order ' => ' userID DESC '
'offset'=> 5 ,
' limit ' => 3
]
);
Jika Anda menggunakan MySQL, kueri diterjemahkan ke:-
SELECT * FROM users
WHERE visits > 3
ORDER BY userID DESC
LIMIT 3 OFFSET 5 ;
Ini adalah salah satu cara menyajikan data dalam potongan kecil. Inilah cara lain untuk memberi hasil paginasi:-
$ page = $ user -> paginate ( 2 , 5 ,[ ' visits>? ' , 3 ]);
Dalam skenario di atas, F3 akan mengambil catatan yang cocok dengan kriteria 'visits>3'
. Ini kemudian akan membatasi hasil menjadi 5 catatan (per halaman) mulai dari halaman offset 2 (berbasis 0). Kerangka kerja akan mengembalikan array yang terdiri dari elemen-elemen berikut:-
[subset] array of mapper objects that match the criteria
[count] number of subsets available
[pos] actual subset position
Posisi subset aktual yang dikembalikan akan menjadi nol jika argumen paginate()
adalah angka negatif atau melebihi jumlah himpunan bagian yang ditemukan.
Ada beberapa contoh ketika Anda perlu mengambil nilai yang dihitung dari suatu bidang, atau nilai silang dari tabel lain. Masukkan bidang virtual. SQL Mini-AN memungkinkan Anda mengerjakan data yang berasal dari bidang yang ada.
Misalkan kita memiliki tabel berikut yang didefinisikan sebagai:-
CREATE TABLE products
productID VARCHAR ( 30 ),
description VARCHAR ( 255 ),
supplierID VARCHAR ( 30 ),
unitprice DECIMAL ( 10 , 2 ),
quantity INT ,
PRIMARY KEY (productID)
);
Tidak ada bidang totalprice
, jadi kami dapat memberi tahu kerangka kerja untuk meminta dari mesin database produk aritmatika dari dua bidang:-
$ item = new DB SQL Mapper ( $ db , ' products ' );
$ item -> totalprice = ' unitprice*quantity ' ;
$ item -> load ([ ' productID=:pid ' , ' :pid ' => ' apple ' ]);
echo $ item -> totalprice ;
Cuplikan kode di atas mendefinisikan bidang virtual yang disebut totalprice
yang dihitung dengan mengalikan unitprice
dengan quantity
. SQL Mapper menyimpan aturan/rumus itu, jadi ketika saatnya tiba untuk mengambil catatan dari database, kita dapat menggunakan bidang virtual seperti bidang yang dipetakan reguler.
Anda dapat memiliki bidang virtual yang lebih kompleks:-
$ item -> mostNumber = ' MAX(quantity) ' ;
$ item -> load ();
echo $ item -> mostNumber ;
Kali ini kerangka kerja mengambil produk dengan jumlah tertinggi (perhatikan metode load()
tidak menentukan kriteria apa pun, sehingga semua catatan dalam tabel akan diproses). Tentu saja, bidang virtual mostNumber
masih akan memberi Anda angka yang tepat jika Anda ingin membatasi ekspresi ke kelompok catatan tertentu yang sesuai dengan kriteria yang ditentukan.
Anda juga dapat memperoleh nilai dari tabel lain:-
$ item -> supplierName =
' SELECT name FROM suppliers ' .
' WHERE products.supplierID=suppliers.supplierID ' ;
$ item -> load ();
echo $ item -> supplierName ;
Setiap kali Anda memuat catatan dari tabel Produk, ORM referensi silang supplerID
di tabel products
dengan supplierID
di tabel suppliers
.
Untuk menghancurkan bidang virtual, gunakan unset($item->totalPrice);
. Ekspresi isset($item->totalPrice)
mengembalikan true jika bidang virtual totalPrice
ditentukan, atau salah jika sebaliknya.
Ingatlah bahwa bidang virtual harus didefinisikan sebelum pengambilan data. ORM tidak melakukan perhitungan yang sebenarnya, atau derivasi hasil dari tabel lain. Ini adalah mesin basis data yang melakukan semua kerja keras.
Jika Anda tidak perlu navigasi rekor-per rekor, Anda dapat mengambil seluruh batch catatan dalam satu tembakan:-
$ frequentUsers = $ user -> find ([ ' visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
Sintaks kueri Jig Mapper memiliki sedikit kemiripan:-
$ frequentUsers = $ user -> find ([ ' @visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
Kode setara menggunakan MongoDB Mapper:-
$ frequentUsers = $ user -> find ([ ' visits ' =>[ ' $gt ' => 3 ]],[ ' userID ' => 1 ]);
Metode find()
mencari tabel users
untuk catatan yang sesuai dengan kriteria, mengurutkan hasilnya dengan userID
dan mengembalikan hasilnya sebagai array objek mapper. find('visits>3')
berbeda dari load('visits>3')
. Yang terakhir mengacu pada objek $user
saat ini. find()
tidak memiliki efek pada skip()
.
PENTING: Mendeklarasikan kondisi kosong, nol, atau string panjang nol sebagai argumen pertama find()
atau load()
akan mengambil semua catatan. Pastikan Anda tahu apa yang Anda lakukan - Anda mungkin melebihi Memory_Limit PHP pada tabel atau koleksi besar.
Metode find()
memiliki sintaks berikut:-
find (
$ criteria ,
[
' group ' => ' foo ' ,
' order ' => ' foo,bar ' ,
' limit ' => 5 ,
' offset ' => 0
]
);
find () mengembalikan array objek. Setiap objek adalah mapper dengan catatan yang sesuai dengan kriteria yang ditentukan .:-
$ place = new DB SQL Mapper ( $ db , ' places ' );
$ list = $ place -> find ( ' state="New York" ' );
foreach ( $ list as $ obj )
echo $ obj -> city . ' , ' . $ obj -> country ;
Jika Anda perlu mengonversi objek mapper ke array asosiatif, gunakan metode cast()
:-
$ array = $ place -> cast ();
echo $ array [ ' city ' ]. ' , ' . $ array [ ' country ' ];
Untuk mengambil jumlah catatan dalam tabel yang cocok dengan kondisi tertentu, gunakan metode count()
.
if (! $ user -> count ([ ' visits>? ' , 10 ]))
echo ' We need a better ad campaign! ' ;
Ada juga metode select()
yang mirip dengan find()
tetapi memberikan lebih banyak kontrol berbutir halus atas bidang yang dikembalikan. Ini memiliki sintaksis seperti SQL:-
select (
' foo, bar, MIN(baz) AS lowest ' ,
' foo > ? ' ,
[
' group ' => ' foo, bar ' ,
' order ' => ' baz ASC ' ,
' limit ' => 5 ,
' offset ' => 3
]
);
Sama seperti metode find()
, select()
tidak mengubah konten objek mapper. Ini hanya berfungsi sebagai metode kenyamanan untuk menanyakan tabel yang dipetakan. Nilai pengembalian kedua metode adalah array objek mapper. Menggunakan dry()
untuk menentukan apakah suatu catatan ditemukan oleh metode ini tidak pantas. Jika tidak ada catatan yang cocok dengan kriteria find()
atau select()
, nilai pengembalian adalah array kosong.
Jika Anda ingin mengetahui pernyataan SQL mana yang dikeluarkan secara langsung oleh aplikasi Anda (atau secara tidak langsung melalui objek mapper) menyebabkan kemacetan kinerja, Anda dapat melakukannya dengan yang sederhana:-
echo $ db -> log ();
F3 melacak semua perintah yang dikeluarkan untuk driver database SQL yang mendasarinya, serta waktu yang diperlukan untuk setiap pernyataan untuk menyelesaikan - informasi yang tepat yang Anda butuhkan untuk mengubah kinerja aplikasi.
Dalam kebanyakan kasus, Anda dapat hidup dengan kenyamanan yang diberikan oleh metode data mapper yang telah kita bahas sejauh ini. Jika Anda memerlukan kerangka kerja untuk melakukan beberapa pekerjaan tugas berat, Anda dapat memperpanjang SQL Mapper dengan mendeklarasikan kelas Anda sendiri dengan metode khusus- tetapi Anda tidak dapat menghindari tangan Anda berminyak di beberapa SQL hardcore:-
class Vendor extends DB SQL Mapper {
// Instantiate mapper
function __construct ( DB SQL $ db ) {
// This is where the mapper and DB structure synchronization occurs
parent :: __construct ( $ db , ' vendors ' );
}
// Specialized query
function listByCity () {
return $ this -> select (
' vendorID,name,city ' ,[ ' order ' => ' city DESC ' ]);
/ *
We could have done the the same thing with plain vanilla SQL : -
return $ this - > db - > exec (
'SELECT vendorID,name,city FROM vendors ' .
'ORDER BY city DESC;'
);
* /
}
}
$ vendor = new Vendor ;
$ vendor -> listByCity ();
Memperluas pemetaan data dengan cara ini adalah cara mudah untuk membangun model terkait DB aplikasi Anda.
Jika Anda berguna dengan SQL, Anda mungkin akan mengatakan: Segala sesuatu di ORM dapat ditangani dengan kueri SQL jadul. Memang. Kita dapat melakukannya tanpa pendengar acara tambahan dengan menggunakan pemicu basis data dan prosedur tersimpan. Kami dapat menyelesaikan pertanyaan relasional dengan meja bergabung. ORM hanyalah overhead yang tidak perlu. Tetapi intinya adalah - pemetaan data memberi Anda fungsionalitas tambahan menggunakan objek untuk mewakili entitas basis data. Sebagai pengembang, Anda dapat menulis kode lebih cepat dan menjadi lebih produktif. Program yang dihasilkan akan lebih bersih, jika tidak lebih pendek. Tetapi Anda harus menimbang manfaat terhadap kompromi dalam kecepatan - khususnya saat menangani penyimpanan data besar dan kompleks. Ingat, semua ORM - tidak peduli seberapa kurusnya - akan selalu menjadi lapisan abstraksi lain. Mereka masih harus meneruskan pekerjaan ke mesin SQL yang mendasarinya.
Dengan desain, ORM F3 tidak menyediakan metode untuk secara langsung menghubungkan objek satu sama lain, yaitu SQL bergabung - karena ini membuka sekaleng cacing. Itu membuat aplikasi Anda lebih kompleks dari yang seharusnya, dan ada kecenderungan objek melalui teknik pengambilan yang bersemangat atau malas yang harus dituntun dan bahkan tidak sinkron karena warisan objek dan polimorfisme (ketidakcocokan impedansi) dengan entitas database yang mereka dipetakan . Ada cara tidak langsung untuk melakukannya di SQL Mapper, menggunakan bidang virtual - tetapi Anda harus melakukan ini secara terprogram dan dengan risiko Anda sendiri.
Jika Anda tergoda untuk menerapkan konsep OOP "murni" dalam aplikasi Anda untuk mewakili semua data Anda (karena "semuanya adalah objek"), perlu diingat bahwa data hampir selalu hidup lebih lama dari aplikasi. Program Anda mungkin sudah ketinggalan zaman jauh sebelum data kehilangan nilainya. Jangan menambahkan lapisan kompleksitas lain dalam program Anda dengan menggunakan objek dan kelas yang saling terkait yang menyimpang terlalu banyak dari skema dan struktur fisik data.
Sebelum Anda menenun beberapa objek bersama dalam aplikasi Anda untuk memanipulasi tabel yang mendasari dalam database Anda, pikirkan ini: membuat pandangan untuk mewakili hubungan dan pemicu untuk mendefinisikan perilaku objek dalam mesin basis data lebih efisien. Mesin basis data relasional dirancang untuk menangani tampilan, bergabung dengan tabel dan pemicu. Mereka bukan penyimpanan data bodoh. Tabel yang digabungkan dalam tampilan akan muncul sebagai tabel tunggal, dan bebas lemak dapat memetakan tampilan secara otomatis serta tabel biasa. Replikasi bergabung karena objek relasional dalam PHP lebih lambat dibandingkan dengan kode mesin mesin database, aljabar relasional dan logika optimasi. Selain itu, bergabung dengan tabel berulang kali dalam aplikasi kami adalah tanda pasti bahwa desain database perlu diaudit, dan tampilan dianggap sebagai bagian integral dari pengambilan data. Jika tabel referensi silang data dari tabel lain sering, pertimbangkan untuk menormalkan struktur Anda atau membuat tampilan sebagai gantinya. Kemudian buat objek mapper ke peta otomatis tampilan itu. Ini lebih cepat dan membutuhkan lebih sedikit usaha.
Pertimbangkan tampilan SQL ini yang dibuat di dalam mesin database Anda:-
CREATE VIEW combined AS
SELECT
projects . project_id AS project,
users . name AS name
FROM projects
LEFT OUTER JOIN users ON
projects . project_id = users . project_id AND
projects . user_id = users . user_id ;
Kode aplikasi Anda menjadi sederhana karena tidak harus memelihara dua objek Mapper (satu untuk tabel proyek dan satu lagi untuk pengguna) hanya untuk mengambil data dari dua tabel yang bergabung:-
$ combined = new DB SQL Mapper ( $ db , ' combined ' );
$ combined -> load ([ ' project=? ' , 123 ]);
echo $ combined -> name ;
Kiat: Gunakan alat yang dirancang untuk. Bebas lemak sudah memiliki penolong SQL yang mudah digunakan. Gunakan jika Anda membutuhkan palu yang lebih besar :) Cobalah untuk mencari keseimbangan antara kenyamanan dan kinerja. SQL akan selalu menjadi fallback Anda jika Anda sedang mengerjakan struktur data yang kompleks dan warisan.
Plug-ins are nothing more than autoloaded classes that use framework built-ins to extend F3's features and functionality. If you'd like to contribute, leave a note at the Fat-Free Discussion Area hosted by Google Groups or tell us about it in the FreeNode #fatfree
IRC channel. Someone else might be involved in a similar project. The framework community will appreciate it a lot if we unify our efforts.
There might be instances when you want to make your forms more secure against spam bots and malicious automated scripts. F3 provides a captcha()
method to generate images with random text that are designed to be recognizable only by humans.
$ img = new Image ();
$ img -> captcha ( ' fonts/CoolFont.ttf ' , 16 , 5 , ' SESSION.captcha_code ' );
$ img -> render ();
This example generates an random image based on your desired TrueType font. The fonts/
folder is a subfolder within application's UI
path. The second parameter indicates the font size, and the third argument defines the number of hexadecimal characters to generate.
The last argument represents an F3 variable name. This is where F3 will store the string equivalent of the CAPTCHA image. To make the string reload-safe, we specified a session variable:- SESSION.captcha_code
which maps to $_SESSION['captcha_code']
, which you can use later to verify whether the input element in the form submitted matches this string.
We've covered almost every feature available in the framework to run a stand-alone Web server. For most applications, these features will serve you quite well. But what do you do if your application needs data from another Web server on the network? F3 has the Web plugin to help you in this situation:-
$ web = new Web ;
$ request = $ web -> request ( ' http://www.google.com/ ' );
// another way to do it : -
$ request =Web:: instance ()-> request ( ' http://www.google.com/ ' );
This simple example sends an HTTP request to the page located at www.google.com and stores it in the $request
PHP variable. The request()
method returns an array containing the HTTP response such that $request['headers']
and $request['body']
represent the response headers and body, respectively. We could have saved the contents using the F3::set command, or echo'ed the output directly to our browser. Retrieving another HTML page on the net may not have any practical purpose. But it can be particularly useful in ReSTful applications, like querying a CouchDB server.
$ host = ' localhost:5984 ' ;
$ web -> request ( $ host . ' /_all_dbs ' ),
$ web -> request ( $ host . ' /testdb/ ' ,[ ' method ' => ' PUT ' ]);
You may have noticed that you can pass an array of additional options to the request()
method:-
$ web -> request (
' https://www.example.com:443? ' .
http_build_query (
[
' key1 ' => ' value1 ' ,
' key2 ' => ' value2 '
]
),
[
' headers ' =>[
' Accept: text/html,application/xhtml+xml,application/xml ' ,
' Accept-Language: en-us '
],
' follow_location ' => FALSE ,
' max_redirects ' => 30 ,
' ignore_errors ' => TRUE
]
);
If the framework variable CACHE
is enabled, and if the remote server instructs your application to cache the response to the HTTP request, F3 will comply with the request and retrieve the cached response each time the framework receives a similar request from your application, thus behaving like a browser.
Fat-Free will use whatever means are available on your Web server for the request()
method to run: PHP stream wrappers ( allow_url_fopen
), cURL module, or low-level sockets.
F3 has a utility for sending files to an HTTP client, ie fulfilling download requests. You can use it to hide the real path to your download files. This adds some layer of security because users won't be able to download files if they don't know the file names and their locations. Here's how it's done:-
$ f3 -> route ( ' GET /downloads/@filename ' ,
function ( $ f3 , $ args ) {
// send () method returns FALSE if file doesn ' t exist
if (!Web:: instance ()-> send ( ' /real/path/ ' . $ args [ ' filename ' ]))
// Generate an HTTP 404
$ f3 -> error ( 404 );
}
);
The request()
method can also be used in complex SOAP or XML-RPC applications, if you find the need for another Web server to process data on your computer's behalf - thus harnessing the power of distributing computing. W3Schools.com has an excellent tutorial on SOAP. On the other hand, TutorialsPoint.com gives a nice overview of XML-RPC.
Caching static Web pages - so the code in some route handlers can be skipped and templates don't have to be reprocessed - is one way of reducing your Web server's work load so it can focus on other tasks. You can activate the framework's cache engine by providing a third argument to the $f3->route()
method. Just specify the number of seconds before a cached Web page expires:-
$ f3 -> route ( ' GET /my_page ' , ' App->method ' , 60 );
Begini cara kerjanya. In this example, when F3 detects that the URL /my_page
is accessed for the first time, it executes the route handler represented by the second argument and saves all browser output to the framework's built-in cache (server-side). A similar instruction is automatically sent to the user's Web browser (client-side), so that instead of sending an identical request to the server within the 60-second period, the browser can just retrieve the page locally. The framework uses the cache for an entirely different purpose - serving framework-cached data to other users asking for the same Web page within the 60-second time frame. It skips execution of the route handler and serves the previously-saved page directly from disk. When someone tries to access the same URL after the 60-second timer has lapsed, F3 will refresh the cache with a new copy.
Web pages with static data are the most likely candidates for caching. Fat-Free will not cache a Web page at a specified URL if the third argument in the $f3->route()
method is zero or unspecified. F3 conforms to the HTTP specifications: only GET and HEAD requests can be cached.
Here's an important point to consider when designing your application. Don't cache Web pages unless you understand the possible unwanted side-effects of the cache at the client-side. Make sure that you activate caching on Web pages that have nothing to do with the user's session state.
For example, you designed your site in such a way that all your Web pages have the menu options: "Home"
, "About Us"
, and "Login"
, displayed when a user is not logged into your application. You also want the menu options to change to: "Home"
, "About Us"
, and "Logout"
, once the user has logged in. If you instructed Fat-Free to cache the contents of "About Us"
page (which includes the menu options), it does so and also sends the same instruction to the HTTP client. Regardless of the user's session state, ie logged in or logged out, the user's browser will take a snapshot of the page at the session state it was in. Future requests by the user for the "About Us"
page before the cache timeout expires will display the same menu options available at that time the page was initially saved. Now, a user may have already logged in, but the menu options are still the same as if no such event occurred. That's not the kind of behavior we want from our application.
Some pointers:-
GET
routes only. It will not cache submitted forms!Don't activate the cache on Web pages that at first glance look static. In our example, the "About Us" content may be static, but the menu isn't."About Us"
page, make sure it's available only when a user is not logged in.CACHE
global variable so it points to that drive. This will make your application run like a Formula 1 race car. Note: Don't set the timeout value to a very long period until you're ready to roll out your application, ie the release or production state. Changes you make to any of your PHP scripts may not have the expected effect on the displayed output if the page exists in the framework cache and the expiration period has not lapsed. If you do alter a program that generates a page affected by the cache timer and you want these changes to take effect immediately, you should clear the cache by erasing the files in the cache/ directory (or whatever path the CACHE
global variable points to) . F3 will automatically refresh the cache if necessary. At the client-side, there's little you can do but instruct the user to clear the browser's cache or wait for the cache period to expire.
PHP needs to be set up correctly for the F3 cache engine to work properly. Your operating system timezone should be synchronized with the date.timezone setting in the php.ini
file.
Similar to routes, Fat-Free also allows you to cache database queries. Speed gains can be quite significant, specially when used on complex SQL statements that involve look-up of static data or database content that rarely changes. Activating the database query cache so the framework doesn't have to re-execute the SQL statements every time is as simple as adding a 3rd argument to the F3::sql command - the cache timeout. Misalnya:-
$ db -> exec ( ' SELECT * from sizes; ' , NULL , 86400 );
If we expect the result of this database query to always be Small
, Medium
, and Large
within a 24-hour period, we specify 86400
seconds as the 2nd argument so Fat-Free doesn't have to execute the query more than once a day . Instead, the framework will store the result in the cache, retrieve it from the cache every time a request comes in during the specified 24-hour time frame, and re-execute the query when the timer lapses.
The SQL data mapper also uses the cache engine to optimize synchronization of table structures with the objects that represent them. The default is 60
seconds. If you make any changes to a table's structure in your database engine, you'll have to wait for the cache timer to expire before seeing the effect in your application. You can change this behavior by specifying a third argument to the data mapper constructor. Set it to a high value if you don't expect to make any further changes to your table structure.
$ user = new DB SQL Mapper ( $ db , ' users ' , 86400 );
By default, Fat-Free's cache engine is disabled. You can enable it and allow it to auto-detect APC, WinCache or XCache. If it cannot find an appropriate backend, F3 will use the filesystem, ie the tmp/cache/
folder:-
$ f3 -> set ( ' CACHE ' , TRUE );
Disabling the cache is as simple as:-
$ f3 -> set ( ' CACHE ' , FALSE );
If you wish to override the auto-detection feature, you can do so - as in the case of a Memcached back-end which F3 also supports:-
$ f3 -> set ( ' CACHE ' , ' memcache=localhost:11211 ' );
You can also use the cache engine to store your own variables. These variables will persist between HTTP requests and remain in cache until the engine receives instructions to delete them. To save a value in the cache:-
$ f3 -> set ( ' var ' , ' I want this value saved ' , 90 );
$f3->set()
method's third argument instructs the framework to save the variable in the cache for a 90-second duration. If your application issues a $f3->get('var')
within this period, F3 will automatically retrieve the value from cache. In like manner, $f3->clear('var')
will purge the value from both cache and RAM. If you want to determine if a variable exists in cache, `$f3->exists('var')); returns one of two possible values: FALSE if the framework variable passed does not exist in cache, or an integer representing the time the variable was saved (Un*x time in seconds, with microsecond precision).
Fat-Free also has a Javascript and CSS compressor available in the Web plug-in. It can combine all your CSS files into one stylesheet (or Javascript files into a single script) so the number of components on a Web page are decreased. Reducing the number of HTTP requests to your Web server results in faster page loading. First you need to prepare your HTML template so it can take advantage of this feature. Something like:-
< link rel =" stylesheet " type =" text/css "
href =" /minify/css?files=typo.css,grid.css " />
Do the same with your Javascript files:-
< script type =" text/javascript " src =" /minify/js?&files=underscore.js " >
</ script >
Of course we need to set up a route so your application can handle the necessary call to the Fat-Free CSS/Javascript compressor:-
$ f3 -> route ( ' GET /minify/@type ' ,
function ( $ f3 , $ args ) {
$ f3 -> set ( ' UI ' , $ args [ ' type ' ]. ' / ' );
echo Web:: instance ()-> minify ( $ _GET [ ' files ' ]);
},
3600
);
And that's all there is to it! minify()
reads each file ( typo.css
and grid.css
in our CSS example, underscore.js
in our Javascript example), strips off all unnecessary whitespaces and comments, combines all of the related items as a single Web page component, and attaches a far-future expiry date so the user's Web browser can cache the data. It's important that the PARAMS.type
variable base points to the correct path. Otherwise, the URL rewriting mechanism inside the compressor won't find the CSS/Javascript files.
In our examples, the framework sends a far-future expiry date to the client's Web browser so any request for the same CSS or Javascript block will come from the user's hard drive. On the server side, F3 will check each request and see if the CSS or Javascript blocks have already been cached. The route we specified has a cache refresh period of 3600
seconds. Additionally, if the Web browser sends an If-Modified-Since
request header and the framework sees the cache hasn't changed, F3 just sends an HTTP 304 Not Modified
response so no content is actually delivered. Without the If-Modified-Since
header, Fat-Free renders the output from the cached file if available. Otherwise, the relevant code is executed.
Tip: If you're not modifying your Javascript/CSS files frequently (as it would be if you're using a Javascript library like jQuery, MooTools, Dojo, etc.), consider adding a cache timer to the route leading to your Javascript/CSS minify handler (3rd argument of F3::route()) so Fat-Free doesn't have compress and combine these files each time such a request is received.
Want to make your site run even faster? Fat-Free works best with either Alternative PHP Cache (APC), XCache, or WinCache. These PHP extensions boost performance of your application by optimizing your PHP scripts (including the framework code).
A fast application that processes all HTTP requests and responds to them at the shortest time possible is not always a good idea - specially if your bandwidth is limited or traffic on your Web site is particularly heavy. Serving pages ASAP also makes your application vulnerable to Denial-of-Service (DOS) attacks. F3 has a bandwidth throttling feature that allows you to control how fast your Web pages are served. You can specify how much time it should take to process a request:-
$ f3 -> route ( ' /throttledpage ' , ' MyApp->handler ' , 0 , 128 );
In this example, the framework will serve the Web page at a rate of 128KiBps.
Bandwidth throttling at the application level can be particularly useful for login pages. Slow responses to dictionary attacks is a good way of mitigating this kind of security risk.
Robust applications are the result of comprehensive testing. Verifying that each part of your program conforms to the specifications and lives up to the expectations of the end-user means finding bugs and fixing them as early as possible in the application development cycle.
If you know little or nothing about unit testing methodologies, you're probably embedding pieces of code directly in your existing program to help you with debugging. That of course means you have to remove them once the program is running. Leftover code fragments, poor design and faulty implementation can creep up as bugs when you roll out your application later.
F3 makes it easy for you to debug programs - without getting in the way of your regular thought processes. The framework does not require you to build complex OOP classes, heavy test structures, and obtrusive procedures.
A unit (or test fixture) can be a function/method or a class. Let's have a simple example:-
function hello () {
return ' Hello, World ' ;
}
Save it in a file called hello.php
. Now how do we know it really runs as expected? Let's create our test procedure:-
$ f3 = require ( ' lib/base.php ' );
// Set up
$ test = new Test ;
include ( ' hello.php ' );
// This is where the tests begin
$ test -> expect (
is_callable ( ' hello ' ),
' hello() is a function '
);
// Another test
$ hello = hello ();
$ test -> expect (
! empty ( $ hello ),
' Something was returned '
);
// This test should succeed
$ test ->expect
is_string ( $ hello ),
' Return value is a string '
);
// This test is bound to fail
$ test -> expect (
strlen ( $ hello )== 13 ,
' String length is 13 '
);
// Display the results ; not MVC but let ' s keep it simple
foreach ( $ test -> results () as $ result ) {
echo $ result [ ' text ' ]. ' <br /> ' ;
if ( $ result [ ' status ' ])
echo ' Pass ' ;
else
echo ' Fail ( ' . $ result [ ' source ' ]. ' ) ' ;
echo ' <br /> ' ;
}
Save it in a file called test.php
. This way we can preserve the integrity of hello.php
.
Now here's the meat of our unit testing process.
F3's built-in Test
class keeps track of the result of each expect()
call. The output of $test->results()
is an array of arrays with the keys text
(mirroring argument 2 of expect()
), status
(boolean representing the result of a test), and source
(file name/line number of the specific test) to aid in debugging.
Fat-Free gives you the freedom to display test results in any way you want. You can have the output in plain text or even a nice-looking HTML template. So how do we run our unit test? If you saved test.php
in the document root folder, you can just open your browser and specify the address http://localhost/test.php
. That's all there is to it.
F3 gives you the ability to simulate HTTP requests from within your PHP program so you can test the behavior of a particular route. Here's a simple mock request:-
$ f3 -> mock ( ' GET /test?foo=bar ' );
To mock a POST request and submit a simulated HTML form:-
$ f3 -> mock ( ' POST /test ' ,[ ' foo ' => ' bar ' ]);
Once you get the hang of testing the smallest units of your application, you can then move on to the bigger components, modules, and subsystems - checking along the way if the parts are correctly communicating with each other. Testing manageable chunks of code leads to more reliable programs that work as you expect, and weaves the testing process into the fabric of your development cycle. The question to ask yourself is:- Have I tested all possible scenarios? More often than not, those situations that have not been taken into consideration are the likely causes of bugs. Unit testing helps a lot in minimizing these occurrences. Even a few tests on each fixture can greatly reduce headaches. On the other hand, writing applications without unit testing at all invites trouble.
string AGENT
Mozilla/5.0 (Linux; Android 4.2.2; Nexus 7) AppleWebKit/537.31
. bool AJAX
TRUE
if an XML HTTP request is detected, FALSE
otherwise. string AUTOLOAD
|
), comma ( ,
), or semi-colon ( ;
) as path separator. string BASE
index.php
main/front controller. string BODY
bool/string CACHE
'memcache=localhost'
(and the PHP memcache module is present), F3 auto-detects the presence of APC, WinCache and XCache and uses the first available PHP module if set to TRUE. If none of these PHP modules are available, a filesystem-based backend is used (default directory: tmp/cache
). The framework disables the cache engine if assigned a FALSE
value. bool CASELESS
FALSE
to make it case-sensitive. array COOKIE, GET, POST, REQUEST, SESSION, FILES, SERVER, ENV
integer DEBUG
string DNSBL
403 Forbidden
error if the user's IPv4 address is listed on the specified server(s). array DIACRITICS
string ENCODING
UTF-8
. array ERROR
ERROR.code
is the HTTP status code. ERROR.status
contains a brief description of the error. ERROR.text
provides more detail. For HTTP 500 errors, use ERROR.trace
to retrieve the stack trace. bool ESCAPE
string EXEMPT
string FALLBACK
bool HALT
array HEADERS
bool HIGHLIGHT
TRUE
(requires code.css
stylesheet). string HOST
$_SERVER['SERVER_NAME']
is not available, return value of gethostname()
is used. string IP
array JAR
string LANGUAGE
LOCALES
. If set to NULL
, language is auto-detected from the HTTP Accept-Language
request header. string LOCALES
string LOGS
mixed ONERROR
string PACKAGE
array PARAMS
route()
pattern. PARAMS.0
contains the captured URL relative to the Web root. string PATTERN
string PLUGINS
base.php
. int PORT
string PREFIX
bool QUIET
bool RAW
BODY
. Should be TRUE when processing large data coming from php://input
which will not fit in memory. Default value: FALSE
string REALM
string RESPONSE
QUIET
setting. string ROOT
array ROUTES
string SCHEME
http
or https
. string SERIALIZER
php
, unless PHP igbinary
extension is auto-detected. Assign json
if desired. string TEMP
tmp/
folder inside the Web root. Adjust accordingly to conform to your site's security policies. string TZ
date_default_timezone_set()
function. string UI
View
and Template
classes' render()
method. Default value is the Web root. Accepts a pipe ( |
), comma ( ,
), or semi-colon ( ;
) as separator for multiple paths. callback UNLOAD
string UPLOADS
string URI
string VERB
string VERSION
@token
@token
with value of equivalent F3 variable. {{ mixed expr }}
expr
may include template tokens, constants, operators (unary, arithmetic, ternary and relational), parentheses, data type converters, and functions. If not an attribute of a template directive, result is echoed. {{ string expr | raw }}
expr
. F3 auto-escapes strings by default. {{ string expr | esc }}
expr
. This is the default framework behavior. The | esc
suffix is only necessary if ESCAPE
global variable is set to FALSE
. {{ string expr, arg1, ..., argN | format }}
expr
and pass the comma-separated arguments, where arg1, ..., argn
is one of:- 'date'
, 'time'
, 'number, integer'
, 'number, currency'
, or 'number, percent'
. <include
[ if="{{ bool condition }}" ]
href="{{ string subtemplate }}"
/>
subtemplate
and insert at current position in template if optional condition is TRUE
. <exclude>text-block</exclude>
text-block
at runtime. Used for embedding comments in templates. <ignore>text-block</ignore>
text-block
as-is, without interpretation/modification by the template engine. <check if="{{ bool condition }}">
<true>true-block</true>
<false>false-block</false>
</check>
TRUE
, then true-block
is rendered. Otherwise, false-block
is used. <loop
from="{{ statement }}"
to="{{ bool expr }}"
[ step="{{ statement }}" ]>
text-block
</loop>
from
statement once. Check if the expression in the to
attribute is TRUE
, render text-block
and evaluate step
statement. Repeat iteration until to
expression is FALSE
. <repeat
group="{{ array @group|expr }}"
[ key="{{ scalar @key }}" ]
value="{{ mixed @value }}"
[ counter="{{ scalar @key }}" ]>
text-block
</repeat>
text-block
as many times as there are elements in the array variable @group
or the expression expr
. @key
and @value
function in the same manner as the key-value pair in the equivalent PHP foreach()
statement. Variable represented by key
in counter
attribute increments by 1
with every iteration. <switch expr="{{ scalar expr }}">
<case value="{{ scalar @value|expr }}" break="{{ bool TRUE|FALSE }}">
text-block
</case>
.
.
.
</switch>
{* text-block *}
<exclude>
.The most up-to-date documentation is located at http://fatfreeframework.com/. It contains examples of usage of the various framework components.
Technical support is available at the official discussion forum: https://groups.google.com/forum/#!forum/f3-framework
. If you need live support, you can talk to the development team and other members of the F3 community via Slack or IRC. We're on the FreeNode #fatfree
channel ( chat.freenode.net
). Visit http://webchat.freenode.net/
to join the conversation. You can also download the Firefox Chatzilla add-on or Pidgin if you don't have an IRC client so you can participate in the live chat. You can also find help at Stack Overflow
F3 uses Git for version control. To clone the latest code repository on GitHub:
git clone git://github.com/bcosca/fatfree-core.git
If all you want is a zipball of our test bench with all unit tests, grab it here .
To file a bug report, visit https://github.com/bcosca/fatfree-core/issues
.
Fat-Free Framework is free and released as open source software covered by the terms of the GNU Public License (GPL v3). You may not use the software, documentation, and samples except in compliance with the license. If the terms and conditions of this license are too restrictive for your use, alternative licensing is available for a very reasonable fee.
If you feel that this software is one great weapon to have in your programming arsenal, it saves you a lot of time and money, use it for commercial gain or in your business organization, please consider making a donation to the project. A significant amount of time, effort, and money has been spent on this project. Your donations help keep this project alive and the development team motivated. Donors and sponsors get priority support (24-hour response time on business days).
The Fat-Free Framework is community-driven software. It can't be what it is today without the help and support from the following people and organizations:
Special thanks to the selfless others who expressed their desire to remain anonymous, yet share their time, contribute code, send donations, promote the framework to a wider audience, as well as provide encouragement and regular financial assistance. Their generosity is F3's prime motivation.
By making a donation to this project you signify that you acknowledged, understood, accepted, and agreed to the terms and conditions contained in this notice. Your donation to the Fat-Free Framework project is voluntary and is not a fee for any services, goods, or advantages, and making a donation to the project does not entitle you to any services, goods, or advantages. We have the right to use the money you donate to the Fat-Free Framework project in any lawful way and for any lawful purpose we see fit and we are not obligated to disclose the way and purpose to any party unless required by applicable law. Although Fat-Free Framework is free software, to our best knowledge this project does not have any tax-exempt status. The Fat-Free Framework project is neither a registered non-profit corporation nor a registered charity in any country. Your donation may or may not be tax-deductible; please consult this with your tax advisor. We will not publish/disclose your name and e-mail address without your consent, unless required by applicable law. Your donation is non-refundable.
Copyright (c) 2009-2022 F3::Factory/Bong Cosca <[email protected]>
Hey dude! Bantu aku untuk beberapa waktu!