<轉(zhuǎn)>提高php代碼質(zhì)量 (一)

1.不要使用相對路徑

常常會看到:

require_once( '../../lib/some_class.php');

該方法有很多缺點:
它首先查找指定的php包含路徑, 然后查找當前目錄.
因此會檢查過多路徑.
如果該腳本被另一目錄的腳本包含, 它的基本目錄變成了另一腳本所在的目錄.
另一問題, 當定時任務運行該腳本, 它的上級目錄可能就不是工作目錄了.
因此最佳選擇是使用絕對路徑:

define('ROOT','/var/www/project/');
require_once(ROOT .'../../lib/some_class.php');
//rest of the code

我們定義了一個絕對路徑, 值被寫死了. 我們還可以改進它. 路徑 /var/www/project 也可能會改變, 那么我們每次都要改變它嗎? 不是的, 我們可以使用FILE常量, 如:

//suppose your script is /var/www/project/index.php

//Then __FILE__ will always have that full path.
define('ROOT',pathinfo(__FILE__, PATHINFO_DIRNAME));

require_once(ROOT .'../../lib/some_class.php');
//rest of the code

現(xiàn)在, 無論你移到哪個目錄, 如移到一個外網(wǎng)的服務器上, 代碼無須更改便可正確運行.

2. 不要直接使用 require, include, include_once, required_once

可以在腳本頭部引入多個文件, 像類庫, 工具文件和助手函數(shù)等, 如:

require_once('lib/Database.php');

require_once('lib/Mail.php');

require_once('helpers/utitlity_functions.php');

這種用法相當原始. 應該更靈活點. 應編寫個助手函數(shù)包含文件. 例如:

function load_class($class_name)
{
    //path to the class file
    $path= ROOT .'/lib/'.$class_name.'.php');
    require_once($path);
}   

load_class('Database');

load_class('Mail');

有什么不一樣嗎? 該代碼更具可讀性.
將來你可以按需擴展該函數(shù), 如:

function load_class($class_name)
{
    //path to the class file
    $path= ROOT .'/lib/'.$class_name.'.php');
    if(file_exists($path))
    {
        require_once($path);
    }
}

還可做得更多:
為同樣文件查找多個目錄
能很容易的改變放置類文件的目錄, 無須在代碼各處一一修改
可使用類似的函數(shù)加載文件, 如html內(nèi)容.

3. 為應用保留調(diào)試代碼

在開發(fā)環(huán)境中, 我們打印數(shù)據(jù)庫查詢語句, 轉(zhuǎn)存有問題的變量值, 而一旦問題解決, 我們注釋或刪除它們. 然而更好的做法是保留調(diào)試代碼.
在開發(fā)環(huán)境中, 你可以:

define('ENVIRONMENT','development');

if(!$db->query($query)
{    
    if(ENVIRONMENT =='development')
    {    
        echo "$query failed";
    }else{
        echo "Database error. Please contact administrator";
    }
}

在服務器中, 你可以:

define('ENVIRONMENT','production'); 
if(!$db->query($query)
{    
    if(ENVIRONMENT =='development')
    {       
        echo "$query failed";
    }else       {
        echo "Database error. Please contact administrator";
    }

}
4. 使用可跨平臺的函數(shù)執(zhí)行命令

system, exec, passthru, shell_exec 這4個函數(shù)可用于執(zhí)行系統(tǒng)命令. 每個的行為都有細微差別. 問題在于, 當在共享主機中, 某些函數(shù)可能被選擇性的禁用. 大多數(shù)新手趨于每次首先檢查哪個函數(shù)可用, 然而再使用它.
更好的方案是封成函數(shù)一個可跨平臺的函數(shù).

/**
    Method to execute a command in the terminal
    Uses :

    1. system
    2. passthru
    3. exec
    4. shell_exec

*/
function terminal($command)
{
    //system
    if(function_exists('system'))
    {
        ob_start();
        system($command , $return_var);
        $output = ob_get_contents();
        ob_end_clean();
    }
    //passthru
    else if(function_exists('passthru'))
    {
        ob_start();
        passthru($command , $return_var);
        $output = ob_get_contents();
        ob_end_clean();
    }

    //exec
    else if(function_exists('exec'))
    {
        exec($command , $output , $return_var);
        $output = implode("\n" , $output);
    }

    //shell_exec
    else if(function_exists('shell_exec'))
    {
        $output = shell_exec($command) ;
    }

    else
    {
        $output = 'Command execution not possible on this system';
        $return_var = 1;
    }

    return array('output' => $output , 'status' => $return_var);
}

terminal('ls');

上面的函數(shù)將運行shell命令, 只要有一個系統(tǒng)函數(shù)可用, 這保持了代碼的一致性.

5. 靈活編寫函數(shù)

function add_to_cart($item_id , $qty)
{
    $_SESSION['cart']['item_id'] = $qty;
}

add_to_cart( 'IPHONE3' , 2 );

使用上面的函數(shù)添加單個項目. 而當添加項列表的時候,你要創(chuàng)建另一個函數(shù)嗎? 不用, 只要稍加留意不同類型的參數(shù), 就會更靈活. 如:

function add_to_cart($item_id , $qty)
{
    if(!is_array($item_id))
    {
        $_SESSION['cart']['item_id'] = $qty;
    }

    else
    {
        foreach($item_id as $i_id => $qty)
        {
            $_SESSION['cart']['i_id'] = $qty;
        }
    }
}

add_to_cart( 'IPHONE3' , 2 );
add_to_cart( array('IPHONE3' => 2 , 'IPAD' => 5) );

現(xiàn)在, 同個函數(shù)可以處理不同類型的輸入?yún)?shù)了. 可以參照上面的例子重構(gòu)你的多處代碼, 使其更智能.

6. 有意忽略php關閉標簽

我很想知道為什么這么多關于php建議的博客文章都沒提到這點.

<?php

echo "Hello";

//Now dont close this tag

這將節(jié)約你很多時間. 我們舉個例子:
一個 super_class.php 文件

<?php
class super_class
{
    function super_function()
    {
        //super code
    }
}
?>
//super extra character after the closing tag

//super extra character after the closing tag

index.php

require_once('super_class.php');

//echo an image or pdf , or set the cookies or session data

這樣, 你將會得到一個 Headers already send error. 為什么? 因為 “super extra character” 已經(jīng)被輸出了. 現(xiàn)在你得開始調(diào)試啦. 這會花費大量時間尋找 super extra 的位置.
因此, 養(yǎng)成省略關閉符的習慣:

<?php
class super_class
{
    function super_function()
{
    //super code
}
}

//No closing tag

這會更好.

7. 在某地方收集所有輸入, 一次輸出給瀏覽器

這稱為輸出緩沖, 假如說你已在不同的函數(shù)輸出內(nèi)容:

function print_header()
{
    echo "<div id='header'>Site Log and Login links</div>";
}

function print_footer()
{
    echo "<div id='footer'>Site was made by me</div>";
}

print_header();
for($i = 0 ; $i < 100; $i++)
{
    echo "I is : $i <br />";
}
print_footer();

替代方案, 在某地方集中收集輸出. 你可以存儲在函數(shù)的局部變量中, 也可以使用ob_start和ob_end_clean. 如下:

function print_header()
{
    $o = "<div id='header'>Site Log and Login links</div>";
    return $o;
}

function print_footer()
{
    $o = "<div id='footer'>Site was made by me</div>";
    return $o;
}

echo print_header();
for($i = 0 ; $i < 100; $i++)
{
    echo "I is : $i <br />';
}
echo print_footer();

為什么需要輸出緩沖:

  • 可以在發(fā)送給瀏覽器前更改輸出. 如 str_replaces 函數(shù)或可能是 preg_replaces 或添加些監(jiān)控/調(diào)試的html內(nèi)容.
  • 輸出給瀏覽器的同時又做php的處理很糟糕. 你應該看到過有些站點的側(cè)邊欄或中間出現(xiàn)錯誤信息. 知道為什么會發(fā)生嗎? 因為處理和輸出混合了.
結(jié)尾

文章太長嗤栓,有興趣請持續(xù)關注费彼,后續(xù)會繼續(xù)更新。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芽世,一起剝皮案震驚了整個濱河市黔酥,隨后出現(xiàn)的幾起案子藻三,更是在濱河造成了極大的恐慌洪橘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棵帽,死亡現(xiàn)場離奇詭異熄求,居然都是意外死亡,警方通過查閱死者的電腦和手機逗概,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門弟晚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逾苫,你說我怎么就攤上這事卿城。” “怎么了隶垮?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵藻雪,是天一觀的道長。 經(jīng)常有香客問我狸吞,道長勉耀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任蹋偏,我火速辦了婚禮便斥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘威始。我一直安慰自己枢纠,他們只是感情好,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布黎棠。 她就那樣靜靜地躺著晋渺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脓斩。 梳的紋絲不亂的頭發(fā)上木西,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音随静,去河邊找鬼八千。 笑死,一個胖子當著我的面吹牛燎猛,可吹牛的內(nèi)容都是我干的恋捆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼重绷,長吁一口氣:“原來是場噩夢啊……” “哼沸停!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起论寨,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤星立,失蹤者是張志新(化名)和其女友劉穎爽茴,沒想到半個月后葬凳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绰垂,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年火焰,在試婚紗的時候發(fā)現(xiàn)自己被綠了劲装。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡昌简,死狀恐怖占业,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纯赎,我是刑警寧澤谦疾,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站犬金,受9級特大地震影響念恍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晚顷,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一峰伙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧该默,春花似錦瞳氓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至裹刮,卻和暖如春音榜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背必指。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工囊咏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人塔橡。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓梅割,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葛家。 傳聞我的和親對象是個殘疾皇子户辞,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • php.ini設置,上傳大文件: post_max_size = 128Mupload_max_filesize ...
    bycall閱讀 6,763評論 3 64
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)癞谒,斷路器底燎,智...
    卡卡羅2017閱讀 134,661評論 18 139
  • 生命不能承受之輕刃榨,怎樣去解讀這個命題,我苦苦思索著双仍,尊嚴枢希、榮譽、地位朱沃、情感是不是構(gòu)成莊重的生命所必須的元...
    靜思齋主人閱讀 361評論 1 3
  • 蔚藍的天空苞轿, 點綴著抹抹的白色, 仿佛柔柔的手兒逗物, 不敢重重的涂抹搬卒! 一道道的光線, 在車窗前略過翎卓, 仿佛時間的軌...
    秀秀王子閱讀 193評論 0 1