Indonesian (Bahasa Indonesia) translation by ⚡ Rova Rindrata (you can also view the original English article)
Di tutorial sebelumnya, saya telah menunjukkan cara membuat sistem pengelolaan konten (CMS) sistem file flat menggunakan Go, Node.js, dan Ruby.
Dalam tutorial ini, saya akan mengambil model desain yang sama dan membangun server dengan menggunakan PHP. Karena PHP bukanlah server dengan sendirinya, tapi biasanya dipasangkan dengan server web Apache, saya akan menunjukkan cara menyiapkan server web Apache di dalam sistem virtual Vagrant.
Pengaturan dan Memuat Perpustakaan
Untuk memulai, Anda harus menginstal PHP di sistem Anda. Pergi ke situs PHP dan download versi untuk sistem Anda. Sebagian besar distribusi Linux dan semua sistem Mac OS X telah diinstal PHP.
Selanjutnya, instal Composer, manajer paket untuk PHP yang mirip dengan npm untuk Node.js. Untuk menginstal Composer, ketik berikut ini di terminal:
php -r “readfile(‘https://getcomposer.org/installer’);” | php
Dengan Composer terinstal, selanjutnya adalah menginstal perpustakaan untuk server. Pertama, buatlah sebuah direktori untuk proyek dengan file dari Membangun CMS: Struktur and Styling atau ekstrak download untuk tutorial ini. Setelah diatur, masuklah ke direktori dan ketik:
composer require slim/slim “^3.0” composer require erusev/parsedown composer require zordius/lightncandy:dev-master composer require “talesoft/tale-jade:*” composer install
Baris-baris ini menginstal empat perpustakaan yang membentuk server: Slim Router adalah perpustakaan routing untuk memproses permintaan server yang masuk, Parsedown menerjemahkan Markdown ke HTML, Handlebars adalah perpustakaan template, dan Jade Library adalah bentuk singkatan pendek dari HTML yang saya gunakan untuk membuat halaman indeks untuk posting.
Membuat index.php
Di bagian atas direktori proyek, buat file index.php. Server Apache mengharapkan halaman utama situs agar memiliki nama ini. Dalam file ini, letakkan kode berikut ini:
<?php // // Program: phpPress // // Description: This is a full flat file // system CMS that mimics the // organization of goPress. // Since goPress server can not // be run on a shared server, // phpPress will work there and // offer easy migration to // goPress if the site is moved // to a VPS. // require ‘vendor/autoload.php’; // // Load libraries used. // // // HandleBars: https://github.com/zordius/lightncandy // use LightnCandy\LightnCandy; // // Jade Library: https://github.com/Talesoft/tale-jade // use Tale\Jade;
Pernyataan require memungkinkan PHP tahu cara memuat berbagai perpustakaan yang terinstal dengan Composer. Kemudian Anda memberitahu PHP untuk menggunakan perpustakaan LightnCandy dan Jade.
// // Slim Router: http://www.slimframework.com/ // use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ResponseInterface as Response; $app = new \Slim\App; // // Set an Error Handler. // $c = $app->getContainer(); $c[‘errorHandler’] = function ($c) { return function ($request, $response, $exception) use ($c) { return $c[‘response’]->withStatus(400) ->withHeader(‘Content-Type’, ‘text/html’) ->write(ProcessPage($parts[‘layout’],“ErrorPage”)); }; }; // // This line will cause Slim not to catch errors. Please commit out for // production server. // unset($app->getContainer()[‘errorHandler’]);
Selanjutnya, Anda mengatur router Slim dengan membuat instance dari objek aplikasi Slim dan menyetel penangan kesalahan. Dengan mengatur penangan kesalahan, Anda tidak akan pernah mendapatkan informasi debug saat terjadi kesalahan. Karena itu, saat pengembangan, Anda perlu unset penangan kesalahan. Tapi untuk produksi, komentari baris terakhir dengan unset.
// // Get the server.json information in to global site variables. // $site = __DIR__ . ‘/site’; $style = “Basic”; $layout = “SingleCol”; $styleDir = ‘./themes/styling/’ . $style; $layoutDir = ‘./themes/layouts/’ . $layout; $parts = Array(); $parts[“CurrentLayout”] = “SingleCol”; $parts[“CurrentStyling”] = “Basic”; $parts[“ServerAddress”] = “http://localhost:8080”; $parts[“SiteTitle”] = “Test Site”; $parts[“Sitebase”] = “./site/“; $parts[“TemplatBase”] = “./themes/“; $parts[“Cache”] = false; $parts[“MainBase”] = ““; // // Load relevant items in the layouts directory. // $parts[“layout”] = file_get_contents($layoutDir . ‘/template.html’); // // Load relevant items in the styles directory. // $parts[“404”] = file_get_contents($styleDir . ‘/404.html’); $parts[“footer”] = file_get_contents($styleDir . ‘/footer.html’); $parts[“header”] = file_get_contents($styleDir . ‘/header.html’); $parts[“sidebar”] = file_get_contents($styleDir . ‘/sidebar.html’); $parts[“ErrorPage”] = “<h1 class=‘Error’>There was a server error!</h1>“; // // Load everything in the parts directory. // $d = dir($site . ‘/parts/‘); while (false !== ($entry = $d->read())) { if((strcmp($entry,“..“)!=0)&&(strcmp($entry,“.“)!=0)) { $pathparts = pathinfo($entry); $parts[basename($pathparts[‘filename’])] = figurePage($site . ‘/parts/’ . $pathparts[‘filename’]); } } $d->close();
Bagian kode selanjutnya adalah pembuatan tabel hash $parts
untuk menyimpan potongan informasi yang digunakan dalam template. Program kemudian menambahkan semuanya di direktori parts dari situs ke tabel hash. Dengan begitu, Anda bisa membuat potongan yang dapat digunakan kembali untuk ditambahkan ke halaman manapun.
// // Function: SetBasicHeader // // Description: This function will set the basic header // information needed. // // Inputs: // $response The response object to be // sent to the browser. // function SetBasicHeader($response) { $newResponse = $response->withAddedHeader(“Cache-Control”, “max-age=2592000, cache”); $newResponse = $newResponse->withAddedHeader(“Server”, “phpPress - a CMS written in PHP from Custom Computer Tools: http://customct.com.“); return($newResponse); }
Fungsi SetBasicHeader()
menetapkan header yang dikembalikan untuk semua halaman. Ini mengatur fungsi kontrol cache dan nama server. Jika Anda membutuhkan lebih banyak informasi header, ini adalah tempat dimana Anda akan mengaturnya.
// // Array of shortcodes and their functions. // $shcodes = Array( ‘box’ => function($args, $inside) { return(“<div class=‘box’>” . $inside . “</div>“); }, ‘Column1’ => function($args, $inside) { return(“<div class=‘col1’>” . $inside . “</div>“); }, ‘Column2’ => function($args, $inside) { return(“<div class=‘col2’>” . $inside . “</div>“); }, ‘Column1of3’ => function($args, $inside) { return(“<div class=‘col1of3’>” . $inside . “</div>“); }, ‘Column2of3’ => function($args, $inside) { return(“<div class=‘col2of3’>” . $inside . “</div>“); }, ‘Column3of3’ => function($args, $inside) { return(“<div class=‘col3of3’>” . $inside . “</div>“); }, ‘php’ => function($args, $inside) { return(“<div class=‘showcode’><pre type=‘syntaxhighlighter’ class=‘brush: php’>” . $inside . “</pre></div>“); }, ‘js’ => function($args, $inside) { return(“<div class=‘showcode’><pre type=‘syntaxhighlighter’ class=‘brush: javascript’>” . $inside . “</pre></div>“); }, ‘html’ => function($args, $inside) { return(“<div class=‘showcode’><pre type=‘syntaxhighlighter’ class=‘brush: html’>” . $inside . “</pre></div>“); }, ‘css’ => function($args, $inside) { return(“<div class=‘showcode’><pre type=‘syntaxhighlighter’ class=‘brush: css’>” . $inside . “</pre></div>“); } );
Tabel hash $shcodes
berisi semua fungsi shortcode untuk memproses item di halaman web. Fungsi yang saya tulis di sini sederhana, tapi bisa lebih kompleks jika dibutuhkan. Ini memberi cara untuk menyematkan kode dinamis ke dalam halaman web Anda.
// // Function: processShortcodes // // Description: This function will expand all // shortcodes in the page given to // it. // function processShortcodes($page) { global $shcodes; $result = ““; while(preg_match(“/\-\[(\w+)(.*)\]\-/i”, $page, $match) == 1) { $num = count($match); $command = $match[1]; $cmdarg = ““; if($num > 2) { $cmdarg = $match[2]; } $spos = strpos($page,“-[{$command}“); $result .= substr($page, 0, $spos); $page = substr($page,$spos + 4 + strlen($command) + strlen( $cmdarg)); $sepos = strpos($page,“-[/{$command}]-“); $inside = trim(substr($page, 0, $sepos)); if(strcmp($inside,““) != 0) { $inside = processShortcodes($inside); } $page = substr($page, $sepos + 5 + strlen($command)); // // If the command name exists in the // shortcodes hash table, then run the // function. // if( array_key_exists($command, $shcodes) ) { $result .= call_user_func($shcodes[$command], $cmdarg, $inside); } } $result .= $page; return($result); }
Fungsi processShortCodes()
akan menemukan, mengeksekusi, dan memasukkan hasil shortcode. Fungsi ini menemukan semua shortcode dalam sebuah halaman dengan memanggil dirinya secara rekursif pada konten yang terlampir dan bagian halaman lainnya.
Sebuah shortcode memiliki sintaks berikut:
-[name arg]- contents -[/name]-
name adalah nama shortcode, arg
adalah argumen yang dikirimkan ke shortcode, dan contents
adalah bagian dari halaman yang dilampirkan shortcode. Tanda -[
dan ]-
bertindak seperti <
dan >
dalam HTML.
// // Create the HandleBar helpers array. // $helpers = Array( ‘flags’ => LightnCandy::FLAG_HANDLEBARS | LightnCandy::FLAG_ADVARNAME | LightnCandy::FLAG_EXTHELPER, ‘helpers’ => Array( ‘save’ => ‘save_helper’, ‘date’ => ‘date_helper’, ‘cdate’ => ‘cdate_helper’ ) ); // // Function: save_helper // // Description: This helper will save the given text to // the given name. That name can be use // latter in the document. // // Inputs: // $args The arguments sent to the // helper function. // function save_helper($args) { global $parts; $arg = implode(” “, $args); $hparts = explode(“|“, $arg); if(count($hparts) == 2) { $parts[$hparts[0]] = $hparts[1]; return $hparts[1]; } else { return $parts[$hparts[0]]; } } // // Function: date_helper // // Description: This function formats the current date // according to the formatting string given. // // Inputs: // $args The arguments sent to the helper // function date_helper($args) { $dateFormat = implode(” “, $args); return date($dateFormat); } // // Function: cdate_helper // // Description: This function formats the date given // according to the formatting string given. // // Inputs: // $args The arguments sent to the helper // function cdate_helper($args) { return date($args[0], $args[1]); }
Bagian selanjutnya berisi fungsi pembantu untuk menambahkan pembantu ke mesin template Handlebars. Fungsi pembantu adalah save
, date
, dan cdate
. Fungsi save
mengambil nama dan beberapa teks. Dimana saja nama yang diberikan ada di makro, teks yang diberikan akan menggantikannya. Fungsi tanggal mengambil tanggal sekarang dan memformatnya sesuai dengan string format yang diberikan. Fungsi cdate
mengambil tanggal dan format string. Ini akan menempatkan tanggal yang diberikan ke format yang diberikan.
// // Function: ProcessPage // // Description: This function will process a page into // the template, process all Mustache // macros, and process all shortcodes. // // Inputs: // $layout The layout for the page // $page The pages main contents // function ProcessPage( $layout, $page ) { global $site, $parts, $helpers; // // We need a temporary file for creating the // Handlebars rendering function. You might // need to change this depending on your system. // $php_inc = “/var/tmp/handlebarsTemp.php”; // // Get the page contents. // $parts[‘content’] = figurePage($page); // // First pass on Handlebars. // $phpStr = LightnCandy::compile($layout, $helpers); file_put_contents($php_inc, $phpStr); $renderer = include($php_inc); $page = $renderer($parts); // // Process the shortcodes. // $pageShort = processShortcodes($page); // // Second pass Handlebars. // $phpStr = LightnCandy::compile($pageShort, $helpers); file_put_contents($php_inc, $phpStr); if($phpStr != ““) { $renderer = include($php_inc); $page = $renderer($parts); } // // Return the results. // return($page); }
Fungsi selanjutnya adalah ProcessPage()
. Fungsi ini mengambil tata letak untuk halaman dan isi dari halaman. Yang akan menggabungkan mereka menggunakan mesin template LightnCandy Handlebars. Halaman yang dihasilkan kemudian mencari shortcode. Halaman yang dihasilkan setelah itu dijalankan melalui LightnCandy lagi. Browser menerima output dari LightnCandy.
// // Setup the routes routines. // function page( $pageAddress ) { global $site, $parts; $page = ProcessPage( $parts[‘layout’], “{$site}/pages/{$pageAddress}“); return($page); }
Fungsi page()
menentukan halaman yang akan dikirim ke pengguna. Fungsi menerima alamat halaman dari router dan memanggil ProcessPage()
untuk membuat halaman.
function posts($postType, $blog, $pageAddress ) { global $site, $parts; $page = ProcessPage( $parts[‘layout’],“{$site}/posts/{$postType}/{$blog}/{$pageAddress}“); return($page); }
Fungsi posts()
berfungsi seperti fungsi page()
untuk konten posting. Router mengirimkan jenis posting, blog, dan nilai alamat halaman dari rute. Fungsi ini kemudian menggunakan ProcessPage()
untuk membuat halaman dikembalikan.
function figurePage( $page ) { global $site, $parts; $result = ““; if(isset($parts[$page])) { // // A site partial was specified. Use it. // $result = $parts[$page]; }else if(file_exists(“{$page}.html”)) { // // It is a html piece. Just get it and pass it on. // $result = file_get_contents(“{$page}.html”); } else if(file_exists(“{$page}.md”)) { // // It is a markdown piece. Process into HTML and pass // it on. // $Parsedown = new Parsedown(); $result = file_get_contents(“{$page}.md”); $result = $Parsedown->text($result); $result = str_replace(“"“,“\““,$result); } else if(file_exists(“{$page}.amber”)) { // // It is a Jade (using the golang name for the // extension) page. // $jade = new Jade\Renderer(); $jade->addPath(dirname($page)); $result = $jade->render(basename($page)); } else { $result = $parts[“404”] ; } // // give the resulting page content. // return($result); }
Fungsi figurePage()
mendapatkan konten halaman yang benar berdasarkan nama yang diberikan. Fungsi akan mencari file dengan ekstensi .html. Jika ada, ia membacanya dan mengirimkannya ke rutinitas pemanggilan.
Selanjutnya, fungsinya mencari ekstensi .md. Jika ada, ia membacanya, mengubah Markdown menjadi HTML, dan mengembalikannya ke rutinitas pemanggilan. Selanjutnya, fungsi melihat apakah ada salah satu dengan ekstensi .amber. Jika ada, ia membacanya, mengubah sintaks Jade menjadi HTML, dan mengembalikannya ke fungsi pemanggilan.
// // This route handles the main or home page. // $app->get(‘/‘, function(Request $request, Response $response) { $newResponse = SetBasicHeader($response); $newResponse = $newResponse->getBody()->write(page(‘main’)); return($newResponse); });
Fungsi rute ini memetakan halaman utama atau beranda untuk situs web. Ini akan menjalankan semua permintaan ke nama domain dengan atau tanpa '/'.
// // This route handles the favicon loading. // $app->get(‘/favicon.ico’, function(Request $request, Response $response){ global $site; $newResponse = SetBasicHeader($response); $newResponse = $newResponse->withAddedHeader(“Content-type”, “image/ico”); $newResponse->getBody()->write(file_get_contents(“{$site}/images/favicon.ico”)); return($newResponse); });
Definisi rute ini memetakan permintaan spesifik: /favicon.ico. Ini memberi favicon untuk situs web. Ini mengembalikan gambar "/images/favicon.ico" di direktori situs.
// // This route handles all the stylesheets loading as one // sheet. // $app->get(‘/stylesheets’, function(Request $request, Response $response) { global $site; $newResponse = $response->withHeader(“Content-type”, “text/css”); $newResponse = SetBasicHeader($newResponse); $newResponse->getBody()->write(file_get_contents(“{$site}/css/final/final.css”)); return($newResponse); });
Rute ini mendapatkan style sheet yang dikompilasi dan mengembalikannya ke pemohon. Style sheet yang dikompilasi selalu "/css/final/final.css".
// // This route handles the loading of the scripts. // $app->get(‘/scripts’, function(Request $request, Response $response) { global $site; $newResponse = $response->withAddedHeader(“Content-type”, “text/javascript”); $newResponse = SetBasicHeader($newResponse); $newResponse->getBody()->write(file_get_contents(“{$site}/js/final/final.js”)); return($newResponse); });
Rute ini selalu mengembalikan file JavaScript terkompilasi yang ditemukan di "/js/final/final.js".
// // This route handles all the image routes. // $app->get(‘/images/{image}‘, function(Request $request, Response $response) { global $site; $ext = pathinfo($request->getAttribute(‘image’), PATHINFO_EXTENSION); $newResponse = SetBasicHeader($response); $newResponse = $newResponse->withAddedHeader(“Content-type”, “image/$ext”); $newResponse->getBody()->write(file_get_contents(“{$site}/images/” . $request->getAttribute(‘image’))); return($newResponse); });
Rute ini mengolah semua permintaan untuk gambar. {image}
memberitahu kode router untuk memberi nama gambar pada fungsinya. Panggilan ke fungsi $request->getAttribute()
mengambil nilainya.
// // This route handles all the video items. // $app->get(‘/videos/{video}‘, function(Request $request, Response $response) { global $site; $newResponse = SetBasicHeader($response); $newResponse = $response->withAddedHeader(“Content-type”, “video/mp4”); $newResponse->getBody()->write(file_get_contents(“{$site}/video/” . $request->getAttribute(‘video’))); return($newResponse); });
Rute ini mendapatkan semua permintaan video dan mengirimnya ke browser.
// // This route handles all the blog posts pages. // $app->get(‘/posts/blogs/{blog}‘, function( Request $request, Response $response) { $newResponse = SetBasicHeader($response); $newResponse->getBody()->write(posts(“blogs”,$request->getAttribute(‘blog’), “index”)); return($newResponse); });
Rute ini mengembalikan daftar entri blog dan ringkasannya. Variabel {blog}
akan menjadi nama blog yang mana untuk mencantumkan entri.
$app->get(‘/posts/blogs/{blog}/{post}‘, function( Request $request, Response $response) { $newResponse = SetBasicHeader($response); $newResponse->getBody()->write(posts(“blogs”,$request->getAttribute(‘blog’), $request->getAttribute(‘post’))); return($newResponse); });
Rute ini mendapat entri blog tersendiri. {blog}
adalah nama blog, dan {post}
adalah entri blog untuk mendapatkan.
// // This route handles all the news posts pages. // $app->get(‘/posts/news/{news}‘, function( Request $request, Response $response) { $newResponse = SetBasicHeader($response); $newResponse->getBody()->write(posts(“news”,$request->getAttribute(‘news’), “index”)); return($newResponse); }); $app->get(‘/posts/news/{news}/{post}‘, function( Request $request, Response $response) { $newResponse = SetBasicHeader($response); $newResponse->getBody()->write(posts(“news”,$request->getAttribute(‘news’), $request->getAttribute(‘post’))); return($newResponse); });
Permintaan router news bekerja seperti permintaan router blog.
// // This route will process all the pages. Since this should // catch all types of routes other than the home page, this // route should handle the unknown pages as well. // $app->get(‘/{page}‘, function( Request $request, Response $response) { $newResponse = SetBasicHeader($response); $newResponse->getBody()->write(page($request->getAttribute(‘page’))); return($newResponse); });
Ini adalah rute halaman umum. Semua permintaan yang tidak sesuai dengan permintaan sebelumnya akan memicu permintaan ini.
// // Respond to requests. // $app->run(); ?>
Potongan kode terakhir ini memulai server. Fungsi ini akan melakukan semua pengolahan untuk permintaannya. Setelah pengembalian, interpreter PHP akan mengakhiri dan menutup koneksi ke browser pengguna.
Server PHP ini bekerja sama sekali berbeda dari server lain dalam seri ini. Rutinitas ini dimulai dan berakhir untuk setiap permintaan, sementara server lainnya terus memproses permintaannya. Oleh karena itu, server PHP ini membutuhkan waktu lebih lama untuk memproses permintaan karena rutinitas bongkar muat.
Menjalankan Server
Sekarang untuk mengatur server. Salah satu cara termudah untuk mendapatkan stack Apache dan PHP adalah dengan menggunakan Vagrant. Untuk menginstal di Mac, gunakan Homebrew dengan perintah ini:
brew cask install vagrant
Jika Anda memiliki sistem Windows atau Linux, gunakan installer dari situs web Vagrant. Situs ini juga memiliki installer mandiri untuk Mac, namun dengan menginstal Homebrew, Anda bisa mendapatkan pembaruan otomatis dengan menjalankan:
brew update
Setelah terinstal, buatlah sebuah file bernama Vagrant di direktori project. Dalam file ini, letakkan kode berikut ini:
Vagrant.configure(“2”) do |config| config.vm.box = “ubuntu/trusty64” config.vm.provision :shell, path: “bootstrap.sh” config.vm.network :forwarded_port, host: 8080, guest: 8080 config.vm.synced_folder “/full/path/to/code/directory”, “/vagrant” end
Ini adalah file konfigurasi Vagrant. Ini memberitahu Vagrant box mesin virtual apa yang untuk membangun, skrip yang menjalankan untuk menyiapkan box untuk server Anda, port apa di mesin virtual untuk memetakan ke port di komputer utama Anda, dan folder untuk disinkronkan ke folder /vagrant di Mesin virtual. Anda perlu mengatur path lengkap ke direktori di komputer Anda bukannya /full/path/to/code/directory
.
Selanjutnya, buat file bootstrap.sh
dan tambahkan skrip ini ke sana:
sudo apt-get update sudo apt-get install -y apache2 # # Setup modules in apache that will be needed. # sudo ln -s /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load sudo ln -s /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled/rewrite.load # # Setup apache on port 8080 and configure apache to read the .htaccess files for # access changes. # sudo cat /etc/apache2/sites-available/000-default.conf | sed ‘s/80/8080/g’ > /var/tmp/sites.conf sudo mv /var/tmp/sites.conf /etc/apache2/sites-available/000-default.conf sudo cat /etc/apache2/ports.conf | sed ‘s/80/8080/g’ > /var/tmp/ports.conf sudo mv /var/tmp/ports.conf /etc/apache2/ports.conf sudo cat /etc/apache2/apache2.conf | sed ‘s/AllowOverride None/AllowOverride All/’ >/var/tmp/apache2.conf sudo mv /var/tmp/apache2.conf /etc/apache2/apache2.conf # # setup php5 # sudo apt-get install -y php5 # # Setup the server root directory # sudo rm -rf /var/www/html sudo ln -fs /vagrant /var/www/html # # reload apache # sudo service apache2 reload
Skrip ini akan dimuat di web server Apache dan mengkonfigurasinya. Dengan Apache telah dikonfigurasi, kemudian menginstal PHP versi 5, mengatur direktori root untuk server, dan meluncurkan service Apache. Semua ini akan mengkonfigurasi mesin virtual sesuai kebutuhan untuk proyek ini dan memiliki direktori root dari server yang mendapatkan file dari direktori proyek Anda. Setiap hasil edit yang Anda buat di direktori proyek Anda langsung tersedia ke server.
Dalam direktori proyek, buatlah sebuah file bernama .htaccess dan letakkan kode ini:
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [QSA,L] # 1 YEAR <FilesMatch “\.(ico|pdf|flv)$“> Header set Cache-Control “max-age=29030400, public” </FilesMatch> # 1 WEEK <FilesMatch “\.(jpg|jpeg|png|gif|swf)$“> Header set Cache-Control “max-age=604800, public” </FilesMatch> # 2 DAYS <FilesMatch “\.(xml|txt|css|js)$“> Header set Cache-Control “max-age=172800, proxy-revalidate” </FilesMatch> # 1 MIN <FilesMatch “\.(html|htm|php)$“> Header set Cache-Control “max-age=60, private, proxy-revalidate” </FilesMatch>
Ini memberitahu server Apache bagaimana menangani permintaan untuk situs ini dan untuk caching permintaan secara otomatis. File index.php mendapatkan setiap permintaan ke server.
Menjalankan Server
Untuk memulai server, jalankan perintah berikut di direktori proyek:
vagrant up
Ini akan mendownload mesin virtual jika belum ada di sistem Anda, menjalankan skrip provisioning, dan meluncurkan server. Untuk melihat situsnya, buka browser Anda ke http://localhost:8080.



Browser harus menampilkan halaman di atas. Server sekarang online dan siap untuk penambahan Anda.
Jika situs web tidak dapat dilihat, Anda harus memeriksa perizinan untuk semua file di situs. OS X sering membuat mereka hanya bisa dibaca. Anda perlu menjadikannya terbaca di dunia dengan perintah berikut di direktori proyek:
chmod -R a+r .
Itu akan memastikan bahwa server Apache di mesin virtual mampu membaca file-nya.
Untuk menghentikan server, jalankan perintah berikut di direktori proyek:
vagrant halt
Untuk mempelajari lebih lanjut tentang penggunaan Vagrant, bacalah Dokumentasi Vagrant. Anda juga bisa melihat banyak tutorial Vagrant di Envato Tuts+. Saya menggunakan alat Hobo untuk membuat file Vagrant saya. Ini adalah alat yang hebat untuk mengonfigurasi, menjalankan, dan mengelola sistem Vagrant di OS X.
Kesimpulan
Sekarang setelah Anda tahu bagaimana membangun sebuah web server sederhana namun kuat dengan menggunakan bahasa PHP, saatnya bagi Anda untuk bereksperimen. Buat halaman baru, posting, bagian yang dapat disematkan, dan shortcode. Platform sederhana ini jauh lebih cepat daripada menggunakan WordPress, dan ini benar-benar terkendali.
Berbeda dengan server web lainnya di seri ini, CMS berbasis PHP ini dapat berjalan di akun shared hosting manapun. Saya menggunakannya untuk situs web pelayanan saya di Dreamhost. Saya belum mengoptimalkan gambarnya, tapi itu masih cukup bagus. Ceritakan tentang server Anda di komentar di bawah ini.