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ù)更新。