首先,要先在電腦的某處建立屬於自己的工作區。未來我們的工作都會在這邊進行。
mkdir rafax
cd rafax
以 composer
建立 composer.json
(設定檔)
composer init # 依照自己的想法輸入設定檔,以下作為參考
# Package name (<vendor>/<name>): chivincent/rafax
# Description []: iThome 2018 ironman challenge.
# Author: Vincent Chi <song374561@chivincent.net>
# Minimum Stability []: stable
# Package Type []: project
# License []: MIT
# Would you like to define your dependencies (require) interactively: no
# Would you link to define your dev dependencies (require-dev) interactively: no
composer update # 建立 vendor/autoload.php
# 注意:此時可能會出現 "No locakfile found. Unable to read locked packages"
# 這是因為我們尚未安裝任何 package,故未能產生 composer.lock,忽略即可
至此,你的 composer.json
應該類似於下面的結構
{
"name": "chivincent/rafax",
"description": "iThome 2018 ironman challenge.",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "Vincent Chi",
"email": "song374561@chivincent.net"
}
],
"minimum-stability": "stable",
"require": {}
}
緊接著,我們先建立這個框架第一個程式,依照慣例通常要是 Hello World 。建立 index.php
作為程式的入口點。
// rafax/index.php
<?php
echo 'Hello World'.PHP_EOL;
我們可以啟動 PHP 內置的網頁服務器(Built-in Web Server)來瀏覽其結果
php -S localhost:10000
我們發現,如果連接到 http://localhost:10000/composer.json
即可看到我們專案的 composer.json
,而且可以存取 .git/
,這會造成過度的資訊洩露。(儘管現在沒有什麼資訊可以洩露)
一般而言,我們會建立一個獨立的資料夾,用來作為公開的根目錄,在此我們取名為 public
,然後將 index.php
移至 public/
資料夾下,並且在 public/
資料夾中重新啟動 PHP 內置網頁伺服器
mkdir public
mv index.php public/
php -S localhost:10000 -t public
為了確保我們未來可以使用 composer
的套件,所以必須在應用程式的入口點(此案例中目前僅有 public/index.php
一個入口點)中優先引入 vendor/autoload.php
。
// rafax/public/index.php
<?php
require __DIR__ . '/../vendor/autoload.php';
echo 'Hello World'.PHP_EOL;
require
而不是 include
;為什麼要用 require
而不是 require_once
require
會在引入時發生錯誤時(例如被引入目標不存在)拋出 Error 且終止應用程式,但 include
僅會拋出 Warning 且會讓程式繼續向下執行。
對於 composer autoloader 這類無論如何都必須被引入的腳本而言,如果其中發生錯誤應該被提前得知,並且中止應用程式。
composer autoloader 無論在什麼情況下,都應該只被引入一次,以這層意義來看的話其實用 require
或 require_once
都是可以接受的。
然而隨著專案規模的擴大,未來可能會搞不清楚目前位置是否已經引用過 autoload.php
,若一直都是靠著使用 require_once
,因為在執行時期完全沒有任何警告或錯誤,以致於造成冗餘程式碼。
為了避免這樣的情況,當引用 autoload.php
時都建議使用 require
,如果有重複定義時就會由 PHP 直譯器拋出 Fatal error,進而提醒自己避免冗餘程式碼的出現。
__DIR__
,而不是使用 dirname(__FILE__)
__DIR__
出現於 PHP 5.3 之後,基本上功能與 dirname(__FILE__)
是完全相同的。
但是這邊要考量一點:__DIR__
是屬於魔術常數(Magic constants),會在編譯時期(compile-time)被解析,而 dirname(__FILE__)
則是屬於函式呼叫(function-call),是在執行時期(execution-time)被解析。
就以理論角度而言,__DIR__
的效率應該要比 dirname(__FILE__)
來得高,然而站在編譯器優化的角度來看,其實兩者效率是差不多,甚至是相同的,不過站在程式設計的觀點,它並非一個需要用 function call 解析的路徑,因為 autoload.php
一直都在同一個位置,所以通常是採用 __DIR__
做路徑的設定。
__DIR__
and dirname(__FILE__)
in PHP?