使用 PHP

本節(jié)匯集了你在寫(xiě) PHP 腳本時(shí)可能碰到的大多數(shù)普通錯(cuò)誤。

  1. 我忘了 PHP 函數(shù)的參數(shù)順序,它們是隨機(jī)的嗎?
  2. 我想寫(xiě)一個(gè)可以處理任何表單來(lái)的數(shù)據(jù)的通用 PHP 腳本。我怎么知道哪個(gè) POST 方法變量可用呢?
  3. 我需要在所有的單引號(hào)(')前加一個(gè)反斜線(\),使它們變成(\')。我如何能夠通過(guò)正則表達(dá)式來(lái)實(shí)現(xiàn)? 我同樣希望能夠?qū)?" 轉(zhuǎn)換成 \",將 \ 轉(zhuǎn)換成 \\。
  4. 當(dāng)我這樣做時(shí),輸出顯示的次序是錯(cuò)的: <?php function myfunc($argument) { echo $argument + 10; } $variable = 10; echo "myfunc($variable) = " . myfunc($variable); ?> 這是怎么回事?
  5. 下面代碼怎么沒(méi)有分成兩行顯示? <pre> <?php echo "This should be the first line."; ?> <?php echo "This should show up after the new line above."; ?> </pre>
  6. 我得到消息 “Warning: Cannot send session cookie - headers already sent...” 或者 “Cannot add header information - headers already sent...”。
  7. 我需要直接訪問(wèn)請(qǐng)求報(bào)頭中的信息,怎么能辦到?
  8. 當(dāng)我用 IIS 進(jìn)行 HTTP 認(rèn)證時(shí)得到 “No Input file specified” 消息。
  9. Windows:不能訪問(wèn)另一臺(tái)電腦上用 IIS 共享的文件。
  10. 我怎樣混合使用 XML 和 PHP?它不認(rèn)我的 <?xml 標(biāo)記!
  11. 哪里可以找到所有可用的 PHP 預(yù)定義變量的完整列表?
  12. 怎樣才能不用非免費(fèi)的商業(yè)庫(kù)(例如 PDFLib) 來(lái)生成 PDF 文檔?我想要個(gè)免費(fèi)的并且不需要再連接別的 PDF 庫(kù)。
  13. 有些 PHP 選項(xiàng)可以接受縮寫(xiě)的字節(jié)值,與僅能接受 int 字節(jié)值相反。都有哪些縮寫(xiě)字節(jié)值?
我忘了 PHP 函數(shù)的參數(shù)順序,它們是隨機(jī)的嗎?

PHP 是一個(gè)將數(shù)百個(gè)外部庫(kù)連接在一起的粘合劑,盡管有時(shí)候會(huì)有一些混亂。這里有一些簡(jiǎn)單的經(jīng)驗(yàn)法則:

數(shù)組函數(shù) 參數(shù)的順序?yàn)? "needle, haystack", 字符串函數(shù) 則相反,順序?yàn)? "haystack, needle"。

我想寫(xiě)一個(gè)可以處理任何表單來(lái)的數(shù)據(jù)的通用 PHP 腳本。我怎么知道哪個(gè) POST 方法變量可用呢?

PHP 提供很多“ 預(yù)定義變量”,例如超全局變量 $_POST??梢员闅v $_POST變量,因?yàn)樗且粋€(gè)和所有通過(guò) POST 方法傳遞數(shù)據(jù)相聯(lián)系的數(shù)組。例如,可以用 foreach簡(jiǎn)單地遍歷它,檢查 empty()值,以及將它們輸出。

<?php
$empty 
$post = array();
foreach (
$_POST as $varname => $varvalue) {
    if (empty(
$varvalue)) {
        
$empty[$varname] = $varvalue;
    } else {
        
$post[$varname] = $varvalue;
    }
}

print 
"<pre>";
if (empty(
$empty)) {
    print 
"None of the POSTed values are empty, posted:\n";
    
var_dump($post);
} else {
    print 
"We have " count($empty) . " empty values\n";
    print 
"Posted:\n"var_dump($post);
    print 
"Empty:\n";  var_dump($empty);
    exit;
}
?>

我需要在所有的單引號(hào)(')前加一個(gè)反斜線(\),使它們變成(\')。我如何能夠通過(guò)正則表達(dá)式來(lái)實(shí)現(xiàn)? 我同樣希望能夠?qū)?" 轉(zhuǎn)換成 \",將 \ 轉(zhuǎn)換成 \\。

假設(shè)是針對(duì)數(shù)據(jù)庫(kù),請(qǐng)使用數(shù)據(jù)庫(kù)自帶的轉(zhuǎn)義機(jī)制。比如,針對(duì) MySQL 使用 mysql_real_escape_string() 函數(shù),針對(duì) PostgreSQL 則使用 pg_escape_string() 函數(shù)。還有兩個(gè)標(biāo)準(zhǔn)函數(shù) addslashes()stripslashes() 可以在舊的 PHP 版本中實(shí)現(xiàn)類(lèi)似的操作。

當(dāng)我這樣做時(shí),輸出顯示的次序是錯(cuò)的:
<?php
function myfunc($argument)
{
    echo 
$argument 10;
}
$variable 10;
echo 
"myfunc($variable) = " myfunc($variable);
?>
這是怎么回事?

要在一個(gè)表達(dá)式中(例如在上面的例子中和其它字符串連接)使用函數(shù)的結(jié)果,需要 return 這個(gè)值,而不是 echo 它。

下面代碼怎么沒(méi)有分成兩行顯示?
<pre>
<?php echo "This should be the first line."?>
<?php 
echo "This should show up after the new line above."?>
</pre>

在 PHP 中,一段代碼的結(jié)束標(biāo)記要么是“?>”要么是“?>\n”(\n 表示換行)。因此在上面的例子中,輸出的句子將顯示在同一行中,因?yàn)? PHP 忽略了代碼結(jié)束標(biāo)記后面的換行。這意味著如果要輸出一個(gè)換行符,需要在每段 PHP 代碼的結(jié)束標(biāo)記后面多加一個(gè)換行。

PHP 為什么這么做呢?因?yàn)樵诟袷交5? HTML 時(shí),這樣通常會(huì)更容易。假如輸出了換行而你不需要這個(gè)換行時(shí),就不得不用一個(gè)非常長(zhǎng)的行來(lái)達(dá)到這樣的效果,或者讓產(chǎn)生的 HTML 頁(yè)面的源文件的格式很難讀。

我得到消息 “Warning: Cannot send session cookie - headers already sent...” 或者 “Cannot add header information - headers already sent...”。

函數(shù) header(), setcookie()session 函數(shù)需要在輸出流中添加頭信息。但是頭信息只能在其它任何輸出內(nèi)容之前發(fā)送。在使用這些函數(shù)前不能有任何(如 HTML)的輸出。函數(shù) headers_sent() 能夠檢查腳本是否已經(jīng)發(fā)送了頭信息。請(qǐng)參閱 輸出控制函數(shù)

我需要直接訪問(wèn)請(qǐng)求報(bào)頭中的信息,怎么能辦到?

如果以 Apache 的模塊方式運(yùn)行 PHP,那么函數(shù) getallheaders() 可以做這件事。因此下面的代碼可以顯示所有的請(qǐng)求報(bào)頭:

<?php
$headers 
getallheaders();
foreach (
$headers as $name => $content) {
    echo 
"headers[$name] = $content<br />\n";
}
?>

請(qǐng)參閱函數(shù) apache_lookup_uri()、 apache_response_headers()fsockopen()。

當(dāng)我用 IIS 進(jìn)行 HTTP 認(rèn)證時(shí)得到 “No Input file specified” 消息。

IIS 的安全模型這里有毛病。這是所有 IIS 下運(yùn)行的 CGI 程序所共有的問(wèn)題。一個(gè)解決辦法是建立一個(gè)純 HTML 文件(不經(jīng)過(guò) PHP 解析)作為要進(jìn)入認(rèn)證目錄的登錄頁(yè)面,然后用 META 標(biāo)記來(lái)重定向到 PHP 頁(yè)面,或者用一個(gè)連接到 PHP 頁(yè)面。然后 PHP 就可以正確識(shí)別認(rèn)證信息了。如果是用 ISAPI 模塊,那沒(méi)有這個(gè)問(wèn)題。其它 NT 下的 web 服務(wù)器不受此影響。更多信息見(jiàn) ? http://support.microsoft.com/kb/q160422/HTTP 認(rèn)證 一章。

Windows:不能訪問(wèn)另一臺(tái)電腦上用 IIS 共享的文件。

必須要做些修改。打開(kāi) Internet 信息服務(wù),找到你的 PHP 文件并打開(kāi)屬性頁(yè),選擇 文件安全性標(biāo)簽,點(diǎn)擊 匿名訪問(wèn)和身份驗(yàn)證控制的“編輯”按鈕。

解決此問(wèn)題有兩個(gè)方法,一是不要選中 匿名訪問(wèn)并且選中 集成 Windows 身份驗(yàn)證,二是選中 匿名訪問(wèn)并編輯匿名訪問(wèn)使用的帳戶,改成一個(gè)有權(quán)限的。

我怎樣混合使用 XML 和 PHP?它不認(rèn)我的 <?xml 標(biāo)記!

要能夠在 PHP 代碼中直接嵌入 <?xml,需要將 PHP 設(shè)置項(xiàng) short_open_tags設(shè)置為 0以關(guān)閉短標(biāo)記格式。無(wú)法通過(guò)函數(shù) ini_set()來(lái)更改這項(xiàng)設(shè)置。不管 short_open_tags是開(kāi)或者關(guān),都可以用類(lèi)似于 <?php echo '<?xml'; ?>的方法達(dá)到目的。該項(xiàng)設(shè)置的默認(rèn)值為開(kāi)。

哪里可以找到所有可用的 PHP 預(yù)定義變量的完整列表?

請(qǐng)閱讀手冊(cè)中的 預(yù)定義變量 一章,該部分的文檔已經(jīng)包含了一部分可以用于你的腳本的預(yù)定義變量的列表。可用變量的完整列表(及更多信息)可以通過(guò)調(diào)用 phpinfo() 函數(shù)來(lái)查閱。請(qǐng)務(wù)必閱讀手冊(cè)中 來(lái)自 PHP 之外的變量 一節(jié),這部分文檔闡述了外部變量的概念,例如來(lái)自 HTML 表單、Cookie 和 URL 的變量。

怎樣才能不用非免費(fèi)的商業(yè)庫(kù)(例如 PDFLib) 來(lái)生成 PDF 文檔?我想要個(gè)免費(fèi)的并且不需要再連接別的 PDF 庫(kù)。

有幾個(gè)選擇,例如 ? FPDF? TCPDF 模塊。

有些 PHP 選項(xiàng)可以接受縮寫(xiě)的字節(jié)值,與僅能接受 int 字節(jié)值相反。都有哪些縮寫(xiě)字節(jié)值?

可用的選擇有 K(對(duì)應(yīng) Kilobytes),M(對(duì)應(yīng) Megabytes)和 G(對(duì)應(yīng) Gigabytes),區(qū)分大小寫(xiě)。其余的都認(rèn)為是字節(jié)。 1M等于一個(gè) Megabyte,即 1048576 字節(jié)。 1K 等于一個(gè) Kilobyte,即 1024 字節(jié)。不能在 php.ini 之外使用這些符號(hào),最好用整數(shù)的 int 字節(jié)值。參見(jiàn) ini_get() 文檔中的轉(zhuǎn)換示例。要注意,數(shù)字類(lèi)型為 int 會(huì)自動(dòng)取整,這意味著 0.5M0 是等價(jià)的。

注意: kilobyte 和 kibibyte 的區(qū)別

PHP 將一個(gè)千字節(jié)(kilobyte)描述為等于 1024 字節(jié)(bytes),而 IEC 標(biāo)準(zhǔn)則認(rèn)為這是一個(gè) kibibyte。結(jié)論:k 和 K = 1024 bytes.