Artikel ini mengilustrasikan beberapa cara untuk membuat aplikasi PHP yang dapat dikonfigurasi. Artikel ini juga mengeksplorasi titik konfigurasi ideal dalam sebuah aplikasi dan mencari keseimbangan antara aplikasi yang terlalu dapat dikonfigurasi dan terlalu tertutup.
Jika Anda berencana membuat aplikasi PHP Anda tersedia untuk orang atau perusahaan lain, Anda perlu memastikan bahwa aplikasi tersebut dapat dikonfigurasi. Minimal, izinkan pengguna untuk mengatur login dan kata sandi basis data dengan cara yang aman sehingga materi di dalamnya tidak dipublikasikan.
Artikel ini menunjukkan beberapa teknik untuk menyimpan pengaturan konfigurasi dan mengedit pengaturan ini. Selain itu, artikel ini juga memberikan panduan tentang elemen mana yang perlu dikonfigurasi dan bagaimana menghindari dilema konfigurasi berlebih atau kurang.
Konfigurasi menggunakan file INI
PHP memiliki dukungan bawaan untuk file konfigurasi. Hal ini dicapai melalui mekanisme file inisialisasi (INI) seperti file php.ini, di mana konstanta seperti waktu tunggu koneksi database atau cara sesi disimpan ditentukan. Jika mau, Anda dapat menyesuaikan konfigurasi aplikasi Anda di file php.ini ini. Sebagai ilustrasi, saya menambahkan baris kode berikut ke file php.ini.
myapptempdir=foo
Kemudian, saya menulis skrip PHP kecil untuk membaca item konfigurasi ini, seperti yang ditunjukkan pada Listing 1.
Daftar 1.ini1.php
<?php
fungsi get_template_directory()
{
$v = get_cfg_var( "aplikasi sayatempdir" );
kembali ( $v == null ) ? "tempdir" : $v;
}
gema( get_template_directory()."n" );
?>
Saat Anda menjalankan kode ini pada baris perintah, Anda mendapatkan hasil berikut:
% php ini1.php
foo
%
luar biasa. Namun mengapa kita tidak dapat menggunakan fungsi INI standar untuk mendapatkan nilai item konfigurasi myapptempdir? Saya melakukan riset dan menemukan bahwa dalam banyak kasus, item konfigurasi khusus tidak dapat diperoleh menggunakan metode ini. Namun, ini dapat diakses menggunakan fungsi get_cfg_var.
Untuk membuat pendekatan ini lebih sederhana, rangkum akses ke variabel dalam fungsi kedua yang menggunakan nama kunci konfigurasi dan nilai default sebagai parameter, seperti yang ditunjukkan di bawah ini.
Daftar 2.
fungsi ini2.php get_ini_value( $n, $dv )
{
$c = get_cfg_var( $n );
kembali ( $c == nol ) ? $dv : $c;
}
fungsi get_template_directory()
{
return get_ini_value( "myapptempdir", "tempdir" );
}
Ini adalah ikhtisar yang bagus tentang cara mengakses file INI, jadi jika Anda ingin menggunakan mekanisme lain atau menyimpan file INI di tempat lain, Anda tidak perlu bersusah payah mengubah banyak fungsi.
Saya tidak menyarankan penggunaan file INI untuk konfigurasi aplikasi, karena dua alasan. Pertama, meskipun hal ini memudahkan untuk membaca file INI, hal ini membuat hampir tidak mungkin untuk menulis file INI dengan aman. Jadi ini hanya cocok untuk item konfigurasi read-only. Kedua, file php.ini dibagikan ke semua aplikasi di server, jadi menurut saya item konfigurasi khusus aplikasi tidak harus ditulis dalam file itu.
Apa yang perlu Anda ketahui tentang file INI? Yang terpenting adalah cara mereset path include untuk menambahkan item konfigurasi, seperti gambar di bawah ini.
Daftar 3. ini3.php
<?php
echo( ini_get("include_path")."n" );
ini_set("sertakan jalur_",
ini_get("include_path").":./mylib" );
echo( ini_get("include_path")."n" );
?>
Dalam contoh ini, saya menambahkan direktori mylib lokal saya ke jalur penyertaan, sehingga saya dapat meminta file PHP dari direktori tersebut tanpa menambahkan jalur ke pernyataan require.
Konfigurasi dalam PHP
Alternatif umum untuk menyimpan entri konfigurasi dalam file INI adalah dengan menggunakan skrip PHP sederhana untuk menyimpan data. Di bawah ini adalah contohnya.
Daftar 4.config.php
<?php
# Tentukan lokasi direktori sementara
#
$TEMPLATE_DIRECTORY = "tempdir";
?>
Kode yang menggunakan konstanta ini adalah sebagai berikut.
Daftar 5.php.php
<?php
require_once 'config.php';
fungsi get_template_directory()
{
global $TEMPLATE_DIRECTORY;
kembalikan $TEMPLATE_DIRECTORY;
}
gema( get_template_directory()."n" );
?>
Kode pertama berisi file konfigurasi (config.php), dan kemudian Anda dapat menggunakan konstanta ini secara langsung.
Ada banyak keuntungan menggunakan teknologi ini. Pertama, jika seseorang hanya menelusuri file config.php, halamannya kosong. Jadi Anda bisa meletakkan config.php di file yang sama dengan root aplikasi web Anda. Kedua, dapat diedit di editor mana pun, dan beberapa editor bahkan memiliki fungsi pewarnaan sintaksis dan pemeriksaan sintaksis.
Kerugian dari teknologi ini adalah teknologinya hanya dapat dibaca seperti file INI. Mengekstrak data dari file ini sangatlah mudah, tetapi menyesuaikan data dalam file PHP sulit dilakukan, dan dalam beberapa kasus bahkan tidak mungkin.
Alternatif berikut menunjukkan cara menulis sistem konfigurasi yang bersifat dapat dibaca dan ditulis.
Dua contohfile teks
sebelumnyabaik untuk entri konfigurasi read-only, tapi bagaimana dengan parameter konfigurasi yang membaca dan menulis? Pertama, lihat file konfigurasi teks di Listing 6.
Listing 6. config.txt
# File konfigurasi aplikasi saya
Judul=Aplikasi Saya
TemplatDirectory=tempdir
Ini adalah format file yang sama dengan file INI, tetapi saya menulis alat pembantu saya sendiri. Untuk melakukan ini, saya membuat kelas Konfigurasi saya sendiri seperti yang ditunjukkan di bawah ini.
Daftar 7.text1.php
<?php
Konfigurasi kelas
{
pribadi $configFile = 'config.txt';
pribadi $item = array();
fungsi __konstruksi() { $ini->parse();
fungsi __get($id) { kembalikan $ini->item[ $id ] }
penguraian fungsi()
{
$fh = fopen( $ini->configFile, 'r' );
while( $l = fget( $fh ) )
{
jika ( preg_match( '/^#/', $l ) == salah )
{
preg_match( '/^(.*?)=(.*?)$/', $l, $ditemukan );
$ini->barang[ $ditemukan[1] ] = $ditemukan[2];
}
}
fclose( $fh );
}
}
$c = Konfigurasi baru();
echo( $c->TemplateDirectory."n" );
?>
Kode ini pertama-tama membuat objek Konfigurasi. Konstruktor selanjutnya membaca config.txt dan menyetel variabel lokal $items dengan konten file yang diuraikan.
Script kemudian mencari TemplateDirectory, yang tidak didefinisikan secara langsung dalam objek. Oleh karena itu, metode ajaib __get dipanggil dengan $id disetel ke 'TemplateDirectory', yang mengembalikan nilai dalam array $items untuk kunci tersebut.
Metode __get ini khusus untuk lingkungan PHP V5, jadi skrip ini harus dijalankan di bawah PHP V5. Faktanya, semua skrip dalam artikel ini harus dijalankan di bawah PHP V5.
Saat menjalankan skrip ini dari baris perintah, Anda akan melihat hasil berikut:
%php text1.php
tempdir
%
Semuanya diharapkan, objek membaca file config.txt dan mendapatkan nilai yang benar untuk item konfigurasi TemplateDirectory.
Namun apa yang harus Anda lakukan untuk menetapkan nilai konfigurasi? Dengan membuat metode baru dan beberapa kode pengujian baru di kelas ini, Anda bisa mendapatkan fungsionalitas ini, seperti yang ditunjukkan di bawah ini.
Daftar 8.text2.php
<?php
Konfigurasi kelas
{
...
fungsi __get($id) { kembalikan $ini->item[ $id ]; }
fungsi __set($id,$v) { $ini->item[ $id ] = $v }
fungsi mengurai() { ... }
}
$c = Konfigurasi baru();
echo( $c->TemplateDirectory."n" );
$c->TemplateDirectory = 'foobar';
echo( $c->TemplateDirectory."n" );
?>
Sekarang, ada fungsi __set, yang merupakan "sepupu" dari fungsi __get. Fungsi ini tidak mendapatkan nilai untuk variabel anggota. Fungsi ini dipanggil ketika variabel anggota akan ditetapkan. Kode pengujian di bagian bawah menetapkan nilai dan mencetak nilai baru.
Inilah yang terjadi ketika Anda menjalankan kode ini dari baris perintah:
% php text2.php
tempdir
foobar
%
Sangat bagus! Tapi bagaimana cara menyimpannya ke file sehingga perubahannya diperbaiki? Untuk melakukan ini, Anda perlu menulis file dan membacanya. Fungsi baru untuk menulis file seperti yang ditunjukkan di bawah ini.
Daftar 9.text3.php
<?php
Konfigurasi kelas
{
...
fungsi simpan()
{
$nf = '';
$fh = fopen( $ini->configFile, 'r' );
while( $l = fget( $fh ) )
{
jika ( preg_match( '/^#/', $l ) == salah )
{
preg_match( '/^(.*?)=(.*?)$/', $l, $ditemukan );
$nf .= $ditemukan[1]."=".$ini->item[$ditemukan[1]]."n";
}
kalau tidak
{
$nf.= $l;
}
}
fclose( $fh );
salin( $ini->configFile, $ini->configFile.'.bak' );
$fh = fopen( $ini->configFile, 'w' );
ftulis( $fh, $nf );
fclose( $fh );
}
}
$c = Konfigurasi baru();
echo( $c->TemplateDirectory."n" );
$c->TemplateDirectory = 'foobar';
echo( $c->TemplateDirectory."n" );
$c->simpan();
?>
Fungsi penyimpanan baru dengan cerdik memanipulasi config.txt. Daripada hanya menulis ulang file dengan item konfigurasi yang diperbarui (yang akan menghapus komentar), saya membaca file dan secara fleksibel menulis ulang konten array $items. Dengan cara ini, komentar dalam file dipertahankan.
Jalankan skrip pada baris perintah dan keluaran konten file konfigurasi teks. Anda dapat melihat keluaran berikut.
Listing 10. Menyimpan keluaran fungsi
%php text3.php
tempdir
foobar
% kucing config.txt
#File konfigurasi aplikasi saya
Judul=Aplikasi Saya
TemplatDirektori=foobar
%
File config.txt asli kini diperbarui dengan nilai baru.
File konfigurasi XML
Meskipun file teks mudah dibaca dan diedit, namun tidak sepopuler file XML. Selain itu, ada banyak editor yang tersedia untuk XML yang memahami markup, pelolosan simbol khusus, dan banyak lagi. Jadi seperti apa tampilan file konfigurasi versi XML? Listing 11 menunjukkan file konfigurasi dalam format XML.
Daftar 11. config.xml
<?xml version="1.0"?>
<konfigurasi>
<Judul>Aplikasi Saya</Judul>
<Direktori Templat>tempdir</Direktori Templat>
</config>
Listing 12 menunjukkan versi terbaru dari kelas Konfigurasi yang menggunakan XML untuk memuat pengaturan konfigurasi.
Daftar 12.xml1.php
<?php
Konfigurasi kelas
{
pribadi $configFile = 'config.xml';
pribadi $item = array();
fungsi __konstruksi() { $ini->parse();
fungsi __get($id) { kembalikan $ini->item[ $id ] }
penguraian fungsi()
{
$doc = DOMDocument baru();
$doc->load( $ini->configFile );
$cn = $doc->getElementsByTagName( "config" );
$nodes = $cn->item(0)->getElementsByTagName( "*" );
foreach( $node sebagai $node )
$ini->item[ $node->nodeName ] = $node->nodeValue;
}
}
$c = Konfigurasi baru();
echo( $c->TemplateDirectory."n" );
?>
Tampaknya XML memiliki keunggulan lain: kodenya lebih sederhana dan mudah dibandingkan versi teks. Untuk menyimpan XML ini, diperlukan versi lain dari fungsi simpan, yang menyimpan hasilnya dalam format XML, bukan format teks.
Daftar 13.xml2.php
...
fungsi simpan()
{
$doc = DOMDocument baru();
$doc->formatOutput = benar;
$r = $doc->createElement( "config" );
$doc->appendChild( $r );
foreach( $this->item sebagai $k => $v )
{
$kn = $doc->createElement( $k );
$kn->appendChild( $doc->createTextNode( $v ) );
$r->appendChild( $kn );
}
salin( $ini->configFile, $ini->configFile.'.bak' )
;
}
...
Kode ini membuat Model Objek Dokumen XML (DOM) baru dan kemudian menyimpan semua data dalam array $items ke dalam model ini. Setelah menyelesaikan ini, gunakan metode simpan untuk menyimpan XML ke file.
Alternatif terakhir
untuk menggunakan database
adalah dengan menggunakan database untuk menyimpan nilai elemen konfigurasi.Langkah pertama adalah menggunakan skema sederhana untuk menyimpan data konfigurasi. Di bawah ini adalah pola sederhana.
Listing 14. skema.sql
DROP TABLE JIKA ADA pengaturan;
BUAT pengaturan TABEL (
id SEDANG BUKAN NULL AUTO_INCREMENT,
nama TEKS,
nilai TEKS,
KUNCI UTAMA(id)
);
Hal ini memerlukan beberapa penyesuaian berdasarkan persyaratan aplikasi. Misalnya, jika Anda ingin elemen konfigurasi disimpan per pengguna, Anda perlu menambahkan ID pengguna sebagai kolom tambahan.
Untuk membaca dan menulis data, saya menulis kelas Konfigurasi yang diperbarui seperti yang ditunjukkan pada Gambar 15.
Daftar 15.db1.php
<?php
require_once( 'DB.php' );
$dsn = 'mysql://root:kata sandi@localhost/config';
$db =& DB::Hubungkan( $dsn, array() );
)
;
{
pribadi $configFile = 'config.xml';
pribadi $item = array();
fungsi __konstruksi() { $ini->parse();
fungsi __get($id) { kembalikan $ini->item[ $id ] }
fungsi __set($id,$v)
{
global $db;
$ini->barang[ $id ] = $v;
$sth1 = $db->prepare( 'HAPUS DARI pengaturan DIMANA nama=?' );
$db->eksekusi( $sth1, $id );
jika (PEAR::isError($db)) { mati($db->getMessage() }
$sth2 = $db->prepare('MASUKKAN KE pengaturan ( id, nama, nilai ) NILAI ( 0, ?, ? )' );
$db->eksekusi( $sth2, array( $id, $v ) );
jika (PEAR::isError($db)) { mati($db->getMessage() }
}
fungsi penguraian()
{
global $db;
$doc = DOMDocument baru();
$doc->load( $ini->configFile );
$cn = $doc->getElementsByTagName( "config" );
$nodes = $cn->item(0)->getElementsByTagName( "*" );
foreach( $node sebagai $node )
$ini->item[ $node->nodeName ] = $node->nodeValue;
$res = $db->query( 'PILIH nama,nilai DARI pengaturan' );
jika (PEAR::isError($db)) { mati($db->getMessage() }
while( $res->fetchInto( $baris ) ) {
$ini->barang[ $baris[0] ] = $baris[1];
}
}
}
$c = Konfigurasi baru();
echo( $c->TemplateDirectory."n" );
$c->TemplateDirectory = 'foo baru';
echo( $c->TemplateDirectory."n" );
?>
Ini sebenarnya adalah solusi teks/database hybrid. Silakan lihat lebih dekat metode parsingnya. Kelas ini terlebih dahulu membaca file teks untuk mendapatkan nilai awal, kemudian membaca database untuk memperbarui kunci ke nilai terbaru. Setelah menetapkan nilai, kunci dihapus dari database dan catatan baru ditambahkan dengan nilai yang diperbarui.
Sangat menarik untuk melihat bagaimana kelas Konfigurasi berfungsi melalui beberapa versi artikel ini. Kelas ini dapat membaca data dari file teks, XML, dan database, semuanya dengan tetap mempertahankan antarmuka yang sama. Saya mendorong Anda untuk menggunakan antarmuka dengan stabilitas yang sama dalam pengembangan Anda juga. Bagaimana tepatnya cara kerjanya tidak jelas bagi klien objek tersebut. Kuncinya adalah kontrak antara objek dan klien.
Apa itu konfigurasi dan bagaimana cara mengkonfigurasinya
Menemukan jalan tengah yang tepat antara terlalu banyak pilihan konfigurasi dan konfigurasi yang tidak cukup bisa jadi sulit. Yang pasti, konfigurasi database apa pun (misalnya, nama database, pengguna database, dan kata sandi) harus dapat dikonfigurasi. Selain itu, saya memiliki beberapa item konfigurasi dasar yang direkomendasikan.
Dalam pengaturan lanjutan, setiap fitur harus memiliki opsi aktifkan/nonaktifkan terpisah. Izinkan atau nonaktifkan opsi ini berdasarkan kepentingannya bagi aplikasi. Misalnya, dalam aplikasi forum Web, fitur penundaan diaktifkan secara default. Namun, pemberitahuan email dinonaktifkan secara default karena tampaknya memerlukan penyesuaian.
Opsi antarmuka pengguna (UI) semuanya harus disetel ke satu lokasi. Struktur antarmuka (misalnya, lokasi menu, item menu tambahan, URL yang menghubungkan ke elemen antarmuka tertentu, logo yang digunakan, dll.) semuanya harus diatur ke satu lokasi. Saya sangat menyarankan untuk tidak menentukan entri font, warna, atau gaya sebagai item konfigurasi. Ini harus diatur melalui Cascading Style Sheets (CSS), dan sistem konfigurasi harus menentukan file CSS mana yang akan digunakan. CSS adalah cara yang efisien dan fleksibel untuk mengatur font, gaya, warna, dan lainnya. Ada banyak alat CSS hebat di luar sana, dan aplikasi Anda harus memanfaatkan CSS dengan baik daripada mencoba menetapkan standarnya sendiri.
Dalam setiap fitur, saya sarankan mengatur 3 hingga 10 opsi konfigurasi. Opsi konfigurasi ini harus diberi nama dengan cara yang bermakna. Jika opsi konfigurasi dapat diatur melalui UI, nama opsi dalam file teks, file XML, dan database harus berhubungan langsung dengan judul elemen antarmuka. Selain itu, semua opsi ini harus memiliki nilai default yang jelas.
Secara umum, opsi berikut harus dapat dikonfigurasi: alamat email, CSS apa yang digunakan, lokasi sumber daya sistem yang direferensikan dari file, dan nama file elemen grafis.
Untuk elemen grafis, Anda mungkin ingin membuat tipe profil terpisah yang disebut skin, yang berisi pengaturan untuk profil, termasuk penempatan file CSS, penempatan grafik, dan hal-hal semacam itu. Kemudian, biarkan pengguna memilih dari beberapa file skin. Hal ini membuat perubahan skala besar pada tampilan dan nuansa aplikasi Anda menjadi sederhana. Hal ini juga memberikan pengguna kesempatan untuk melakukan skin aplikasi di antara instalasi produk yang berbeda. Artikel ini tidak membahas file skin ini, namun dasar-dasar yang Anda pelajari di sini akan membuat dukungan file skin menjadi lebih sederhana.
Kesimpulan
Konfigurasi adalah bagian penting dari setiap aplikasi PHP dan harus menjadi bagian utama dari desain sejak awal. Saya harap artikel ini memberikan bantuan dalam mengimplementasikan arsitektur konfigurasi Anda dan memberikan beberapa panduan tentang opsi konfigurasi apa yang harus Anda izinkan.