首頁 php教程 php手册 用 PHP 开发健壮的代码(二):有效地使用变量

用 PHP 开发健壮的代码(二):有效地使用变量

Jun 21, 2016 am 09:10 AM
file name php quot

变量

“用 PHP 开发健壮的代码”是关于解决大中型应用程序中的实际问题的系列文章。在本文中,PHP 老手 Amol Hatwar 讨论了如何有效地使用变量。他还演示了如何通过使用 PHP 中可变的变量名来构造配置文件解析器,以便简化脚本配置。
在我的前一篇文章中,我研究了在规划、设计甚至编写代码期间必须考虑的一些因素。在本文中,您将真正接触到实际代码,并可以看到实际运行中的一些东西。如果您还没有看过前一篇文章,那么最好现在就看一看。

正确处理变量
变量与函数是任何计算机语言必不可少的要素。有了变量,您可以将数据抽象化;有了函数,您可以将几行代码抽象化。正如 Bruce Eckel 在他的书籍《C++ 编程思想》中所说的那样,所有编程语言都提供抽象。汇编语言是对底层机器的小抽象。随后的许多所谓的命令式语言(如 Fortran、BASIC 和 C)是对汇编语言的抽象。

编程语言提供的抽象的种类和质量直接关系到您所能解决的问题的复杂程度。理解 PHP 如何处理变量和函数,将有助于您有效地使用它们。

名称里有什么?
就象我在前一篇文章中提到的那样,命名约定和编码约定是重要的。无论您使用什么命名约定,请记住要在项目中严格遵守它。如果您使用应用得最广泛的命名约定,那么您的代码将被更多的人所接受。

对变量进行命名时,在包括脚本时要特别注意不要覆盖正在使用的变量。在大型应用程序中,当增加新的功能时,这是常见的错误根源。防止这一问题的最佳办法就是使用前缀。把变量所在模块的名称缩写作为前缀来使用。例如,如果一个处理投票的模块中有一个保存用户标识的变量,那么您可以将该变量命名为 $poll_userID 或 $pollUserID。

理解 PHP 变量
PHP 是解释型语言。这有许多好处,很快您将学习利用其中的一些。第一个很明显的好处是:它使您省掉了设计-编码-编译-测试周期 — 您在编辑器中编写的任何代码都立即可使用。然而,最重要的好处是您不用担心变量的类型以及如何在内存中管理这些变量。所有分配给脚本的内存在执行完脚本后都由 PHP 自动收回。此外,可以对变量执行许多操作而不必知道变量的类型。清单 1 中的代码在 PHP 中工作十分正常,但在 C 和 Java 语言中会抛出一大堆错误消息:

清单 1. 带变量的样本 PHP 代码

$myStr = 789696; // An integer.
$myVar = 2; // Another integer.
$myStr = "This is my favorite band: "; // Strings are more fun.
$myStr = $myStr . "U" . $myVar; // Doing this is OK, too.
echo "$myVar\n";
?>



安装完 PHP 后,如要运行运行代码,可首先将该代码保存为一个 .php 文件,再将该文件放置在 Web 服务器上,然后将浏览器指向该文件。更好的办法是安装 PHP 的 CGI 版本。然后,通过在 shell 或命令提示符下输入以下命令,并用包含您的脚本的文件名替代 script-name,这样就可以运行该脚本了。

path-to-php/php script-name




该代码能够正常工作,因为 PHP 是类型宽松的语言。用通俗易懂的英语,可以不考虑变量类型,可以把字符串赋值给整数,以及毫不费力地用较大的字符串替代较小的字符串。这在象 C 这样的语言中是不可能的事情。在内部,PHP 将变量所拥有的数据与类型分开存储。类型存储在单独的表中。每当出现包含不同类型的表达式时,PHP 自动确定程序员想要做什么,接着更改表中的类型,然后自动对表达式求值。

介绍一个常见的小问题
不用担心类型固然很好,但有时那也会使您陷入真正的麻烦。怎么回事呢?这里有一个实际的示例:我常常必须把在基于 Windows 的 PC 上创建的内容移到 Linux 系统,以便能在 Web 上使用它们。基于 Windows 的文件系统在处理文件名时是不区分大小写的。文件名 DefParser.php 和 defparser.php 指向 Windows 上的同一文件。在 Linux 操作系统上,它们指向不同的文件。您可能提倡文件名要么全用大写,要么全用小写,但最好的做法应该是使大小写保持不变。

解决这个小问题
假设您想要一个函数,它能在不考虑大小写的情况下检查给定文件是否存在于某个目录中。首先,将这个任务分解成一些简单的步骤。分解代码可能听起来有些可笑,但它确实有助于您在编写代码时将主要精力放在这段代码上。另外,在纸上重写步骤始终比重写代码容易得多:

获取源目录中的所有文件名
过滤掉 . 和 .. 目录
检查目标文件是否存在于该目录中
如果文件存在,则获取具有正确大小写的文件名
如果名称不匹配,则返回 false
要读取目录的内容,需要使用 readdir() 函数。可以在 PHP 手册(请参阅参考资料)中获取有关该函数的更多细节。至于现在,只要知道:readdir() 在每次调用时会逐个返回给定目录中所有文件的名称。在列出了所有的文件名后,它返回 false。您将使用一个循环,该循环在 readdir() 返回 false 时终止。

但这样就够了吗?请记住,PHP 是类型宽松的语言,这意味着会将整型值 0 与 false 视为相同(甚至 C 也把 0 和布尔值 false 视为等价)。问题不是该代码是否能正常工作;想象一下,如果文件的名称是 0 会如何!该脚本会过早终止。可以使用以下脚本(清单 2)来确定 0 与布尔值 false 的等价性:

清单 2. 确定 0 与布尔值 false 是否等价的脚本

$file_name = 0;
if (0 == $file_name ) {
echo "The code is in trouble ...\n"; // This text prints on the screen.
}

else {
echo "Phew ... The code is safe"; // This text never prints.
}
?>




那么您可以做什么呢?您知道 PHP 会在内部存储类型,而如果能够访问这些类型的话,问题就解决了。布尔值 false 和整型值 0 明显是不同的。

PHP 有一个 gettype() 函数,但让我们在这里选择更简单的方法。您可以使用 === 运算符(是的,有三个等号)。不同之处在于该运算符同时比较数据的值和类型。如果您对此觉得有些疑惑,PHP 还有 !== 运算符。只有 PHP 4 中才有这些新型运算符和 gettype() 函数。清单 3 显示了解决该问题的完整代码:

清单 3. 完整代码

/* This is the function where the action takes place */
function chk_file_name( $name, $path="." ) {
$fileList = get_file_list($path);
foreach ($fileList as $file) {
if (eregi($name, $file)) {
return $file;
}
}
return false;
}

/* Return the list of files in a given directory in an array.
Uses the current directory as default. */
function get_file_list($dirName=".") {
$list = array();
$handle = opendir($dirName);
while (false !== ($file = readdir($handle))) {

/* Omit the '.' and the '..' directories. */
if ((".."== $file) || ("."== $file)) continue;
array_push($list, $file);
}

closedir($handle);
return $list;
}

?>




观察中得到的经验
我不打算对清单 3 中各个函数的功能加以说明,相反,我鼓励您查阅 PHP 手册(请参阅参考资料)。当您使用不熟悉的函数时,假设的参数与返回值的类型会是另一个错误根源。我没有对 PHP 中的内置函数加以说明,而是打算说明一些不太一目了然的事情。

当终止条件中涉及不同的变量类型时,通过使用 === 和 !== 运算符进行强类型检查是很重要的。

由各部分组成的代码
我本来可以将整个脚本编写为一个函数,但这里我却把代码分割成两个函数。还记得前一篇文章中的“分而治之”规则吗?我这么做正是因为每个函数所起的作用不同。如果您用其它脚本获取某个目录的内容,那么现在就可以使用方便的实现。我希望您考虑一些事情:想象一下将整个脚本作为一个函数来实现,然后想象调试、测试和重用代码所需的工作。

正确使用循环
现在看看 foreach 循环,想想为什么不用 for 循环?使用 for 循环要求您知道数组中项的数目 — 需要一个额外的步骤。此外,在处理 PHP 数组时,有可能超出数组边界。也就是说,在数组只有 10 个元素时,试图访问它的第 15 个元素。PHP 的确会给出一个小警告,但据我所知,在一些情况下,当反复运行某个脚本时,CPU 活动率会突然上升到 100% 而服务器性能则连续下降。我建议您尽可能地避免使用 for 循环。

断言性的 if
最后,我希望您研究一下那个在 get_file_list() 函数中用于忽略 . 和 .. 目录的较大的 if 条件。显然,我可以采用传统的方法,根据常数来检查变量。但在我自己的许多编码昏招中,我经常会遗漏等号并且在以后找不到哪里出了问题。当然,PHP 不会报错,因为它认为我想进行赋值而不是比较。当您根据变量来比较常数并且又遗漏了一个等号时,PHP 会抛出错误消息。

可变的变量名
现在来讨论一些奇妙的事情。作为新手的开发人员认为,使用可变变量来完成任务是一种令人费解的方法,所以常常回避它。实际上,很容易理解和使用可变变量。它们已经不止一次地帮我摆脱困境,而且它们是一种重要的语言元素。事实上,在有些情况下,使用可变变量在所难免。很快我将研究一种此类现实情况,但首先让我们看看可变变量到底是什么。让我们先尝试一下清单 4 中的代码:

清单 4. 具有可变变量的代码

$myStr = "I";
$$myStr = "am";
$$$myStr = "great.";

// These are new variables.
echo "$myStr ";
echo "$I ";
echo "$am\n";

// Now for the moment of truth ...";

$am = "exaggerating.";

// Does it work the other way?
echo "$myStr ";
echo "${$myStr} ";
echo "${${$myStr}}\n ";
?>




首先,清单 4 中的代码声明了名为 $myStr 的变量,并将字符串 I 赋给它。接下来的语句定义了另一个变量。但这次,变量的名称是 $myStr 中的数据。$$myStr 是一种告诉 PHP 产生另一个变量的方法,其意思是“我想要一个变量,可以在变量 $myStr 中找到这个变量的名称”。当然,为做到这一点,必须定义 $myStr。所以,现在您有一个名为 I 的变量,并用字符串 am 给它赋值。接下来的语句做了同样的事情,并将字符串 great 赋给名为 am 的变量。而 am 只是变量 I 中的数据。

那澄清了一些事,但 echo 语句中那些奇怪的花括号是怎么回事呢?那就是您打印可变变量的方法。如果您省略花括号,那么 PHP 在打印时会将美元符号($)附加到变量的内容上。这些花括号告诉 PHP 首先对它们里面的变量求值。

试着这样考虑:变量可以做什么?简单地说,它们抽象或表示数据,这些数据可以变化,而它们的名称保持不变。可变变量做的是同样的事情;它们抽象数据。但在本例中,它们包含的数据实际上是另一个变量的名称。

我在清单 4 中所给的例子是为了让您熟悉可变变量。可变变量名的实际功能来自这样的事实:您可以在运行时动态地生成可变的变量名。您将在构造一个配置文件解析器时用到这一特性。

配置文件解析器
按照我的经验,在配置应用程序以使其运行期间,用 PHP 编辑配置文件时,用户常有所抱怨。配置只不过是全局变量的一个列表,应用程序中的其它脚本依靠它来查找文件、URL 和其它控制应用程序行为的设置。一个遗漏的美元符号、分号或一段未封闭的注释常常会破坏整个代码。有什么能帮助用户呢?

假设您给用户一个文件,让用户使用由等号分开的简单的名称-值对来编辑该文件。配置文件类似于清单 5。以 # 开头的行的文本被作为注释处理。

清单 5. 样本配置文件

# This is sample a configuration file.
admin_fname = Amol
admin_lname = Hatwar
admin_email = amolhatwar@consultant.com
admin_login = admin
admin_pass = secretstring
# File Ends




意思清楚吗?是的,的确如此……既然可以用 PHP 解析文件,为什么让用户编辑配置文件呢?事实上,这是人们非常期望的。请记住,您的应用程序必须在对用户隐藏所有复杂性的同时,仍然让他知道他能控制该应用程序。

您可以编写负责解析工作的函数,这样您可以在任何地方使用它而不用做任何修改。让我们将该任务分为一些更简单的步骤:

逐行地读取文件
丢弃一行中 # 号字符后的所有内容
以等号为界,将一行分为两个字符串,并丢弃等号
除去字符串中的额外空格
相应声明变量
要编写最后一步,只有使用可变变量才行。清单 6 显示了代码:

清单 6. 解析函数

/* conf_parser.php */

/* Give the filename with path info whenever possible. */
function conf_parse($file_name) {

// @ in front makes the function quiet. Error messages are not printed.
$fp = @fopen($file_name, "r") or die("Cannot open $file_name");

while ($conf_line = @fgets($fp, 1024)) {
$line = ereg_replace("#.*$", "", $line); // Do stripping after hashes.
if ($line == "") continue; // Drop blank lines resulting from the previous step.
list($name, $value) = explode ('=', $line); // Drop '=' and split.
$name = trim($name); // Strip spaces.
$$name= trim($value); // Define the said variable.
}
fclose($fp) or die("Can't close file $file_name");
}
?>




用正则表达式除去 # 号。尽管这里的表达式很简单,但要知道复杂的正则表达式会消耗大量的 CPU 时间。此外,为每页反复地解析配置文件不是一个好的决策。更好的选择是:使用变量或定义语句将已解析的输出存储为 PHP 脚本。我倾向于使用 define() 函数进行定义,因为一旦设置了值就不能在运行时更改它。可以在参考资料中找到一个能够根据您的需要加以修改的实现。

结束语
既然知道了如何有效地使用变量,那么您可以着手编写一些较大的程序了。在本系列的下一篇文章中,我将研究函数和 API 设计。在下次见面以前,希望您编程愉快!

参考资料

下载 def_parser.zip 文件,其中包含配置文件解析器的实现,您可以将该解析器写的文件包括在您的脚本中。


请访问 PHPBuilder.com 和 Developer Shed,以获取更多有关在 PHP 中使用可变变量名称的示例。


请阅读了解 Free Energy,这是一个对 Web 应用程序进行编码的简单方法。


下载或在线查阅 PHP 手册。


参加“Writing efficient PHP”教程,学习如何编写有效的 PHP 代码(developerWorks,2002 年 7 月)。


请阅读本系列文章中的第一篇“奠定基础”,了解有关设计和规划 Web 应用程序的要点(developerWorks,2002 年 8 月)。

关于作者
Amol Hatwar 从能记事起就开始接触计算机。作为 GNU/Linux 的绝对拥护者,他为过去在 Microsoft 平台上编程感到内疚。他现在作为独立顾问帮助众多公司迁移到 GNU/Linux。作为开发 Web 应用程序领域的专家,他把所剩无几的空余时间花在研究没人听说过的技术上。他现在的兴趣包括开放源码软件、Web 服务、对等计算以及高可用性群集。您可以通过 amolhatwar@consultant.com 与 Amol 联系。



本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1318
25
PHP教程
1269
29
C# 教程
1248
24
在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

See all articles