2024 年日本 PHP 研討會

函式處理函式

目錄

新增註釋

使用者貢獻的註釋 5 則註釋

michael dot bommarito at gmail dot com
19 年前
我使用這些函式開發了一個易於使用的技巧來模擬函式重載。它對於建構函式和/或 C++ 樣式的模板特別方便。

以下是一個小範例,可以幫助您入門。這在大部分情況下都能奏效,如果您需要更智慧的解析,使用正規表示式或更合適的分類方案也不難實現。

注意:在字串的情況下,變數類型之間沒有空格。

class Matrix {

...

function Matrix() {
$args = func_get_args();
$argmatch = implode(",", array_map('gettype', $args));

switch( $argmatch ) {
case 'integer,integer'
//初始化 m x n 矩陣
break;

case 'integer,integer,integer'
//以常數 c 初始化 m x n 矩陣
break;

case 'integer,integer,float'
//以常數 c 初始化 m x n 矩陣
break;

case 'array'
//從陣列初始化 (2D....)
break;

case 'array,integer'
//從陣列初始化 (1D,包含 m 列)
break;

default
//(void) 重載?
//錯誤處理?
break;
}
}

...

}
php dot spamguard at pulseforce dot com
15 年前
PHP 的優點在於它允許您使用 func_* 函式將可變長度的引數列表傳送給函式。然而,遺憾的是(這在 PHP 錯誤報告/功能請求中多次被提出),它不支援透過引用傳遞引數,如果支援的話,只需執行 somefunction($a, $b, $c) 並讓它們被處理,而無需執行任何額外的賦值,就可以大大簡化一次處理多個變數的過程。

然而,我發現了一種利用 PHP 多項功能的方法,並建立了一個非常好的範例,展示了如何一次性處理多個變數!

用法是(使用我的範例函式/類別)
"list($a, $b, $c, $d, $e) = TextEscape::escape_multi($a, $b, $c, $d, $e);"

如果 PHP 實際上能夠在使用可變長度引數列表時透過引用傳遞變數,則可以簡化為
"TextEscape::escape_multi($a, $b, $c, $d, $e);"

不過,它在簡潔性和速度方面都非常接近。只需務必確保該語句兩側的引數數量和順序始終相同。

使用靜態類只是為了使程式碼更清晰、更容易查看。這可以應用於任何函式!

現在,來看程式碼,享受其卓越的設計,並享受只需一個語句即可一次修改多個變數的樂趣! ;-)

<?php

class TextEscape
{
public static function
escape_string($sString)
{
/* 可以是任何東西,此範例使用 htmlspecialchars() */
return htmlspecialchars($sString);
}

public static function
escape_multi()
{
/* 取得所有傳遞給函式的變數 */
$aVariables = func_get_args();

/* 迴圈處理陣列,跳脫每個變數 */
foreach ($aVariables as $iKey => $sValue)
{
$aVariables[$iKey] = TextEscape::escape_string($sValue);
}

/* 回傳跳脫後的數值 */
return $aVariables;
}
}

// 建立測試變數
$a = "A<bar";
$b = "B>bar";
$c = "C<bar";
$d = "D>bar";
$e = "E<bar";

// 變數處理前:
// 陣列
// (
// [0] => A<bar
// [1] => B>bar
// [2] => C<bar
// [3] => D>bar
// [4] => E<bar
// )
print_r(array($a, $b, $c, $d, $e));

// 一次處理所有變數,
// 我們利用 list() 和
// 可變長度參數列表來
// 讓程式碼更簡潔! ;-)
list($a, $b, $c, $d, $e) = TextEscape::escape_multi($a, $b, $c, $d, $e);

// 變數處理後:
// 陣列
// (
// [0] => A&lt;bar
// [1] => B&gt;bar
// [2] => C&lt;bar
// [3] => D&gt;bar
// [4] => E&lt;bar
// )
print_r(array($a, $b, $c, $d, $e));

?>

這是程式碼的簡潔版本,清楚地展現了程式碼的運作方式。

我還製作了一個速度極快的版本,但由於它較難閱讀,因此不希望將其作為主要範例發佈。

但它更快,速度提升許多!它盡可能地使用傳參考的方式,並以更有效率的方式進行迴圈。

只要用這個函式取代上面的函式,結果相同,但速度更快

<?php

class TextEscape
{
public static function
escape_string(&$sString) // 修改:現在傳遞參數至實際的文字處理函式時使用傳參考方式
{
/* 可以是任何東西,此範例使用 htmlspecialchars() */
$sString = htmlspecialchars($sString);
}

public static function
escape_multi()
{
/* 取得所有傳遞給函式的變數 */
$aVariables = func_get_args();

/* 迴圈處理陣列,跳脫每個變數 */
for ($i=(count($aVariables)-1); $i>=0; $i--) // 修改:使用更有效率的 for 迴圈取代 foreach;對於計數器宣告方式感到疑惑的人,這是一個常見的優化技巧,藉由將計數器初始化為最後一個元素的索引值(陣列大小減 1),然後向下迭代直到 0(第一個元素),只需檢查一次陣列大小。
{
TextEscape::escape_string($aVariables[$i]); // 修改:已改為使用傳參考方式修改變數
}

/* 回傳跳脫後的數值 */
return $aVariables;
}
}

?>

盡情使用!
Michael T. McGrew
19 年前
使用函式的一個有趣的方式是在其中放入 PHP 以外的其他東西,例如 HTML、CSS。如果您要在許多頁面中使用相同的格式,這會很有用。當然,也可以使用 include 函式,但將它們定義在函式中可以使其在某種程度上更具可攜性,並且避免您必須建立許多 include 檔案。當您要放入大量的 PHP、HTML 和/或 CSS 並在許多頁面中使用它們時,可以使用 include()。而當程式碼量較小且只希望在少數頁面上使用時,則可以在函式中使用 PHP、HTML 和/或 CSS。

在我早期撰寫 PHP 程式碼時,我一直在使用 include() 來處理 HTML 和 CSS,但現在我會更多地使用函式來做到這一點。

<?php function a() { ?>
<style type="text/css">
table {
border: 1px dashed black;
background: #95EAFE;
text-align:left;
width:610px;
}
.linkbar {
font-family:sans-serif;
line-height:40px;
top:1px;
text-align:center;
width:200px;
height:10px;
}
</style>
<?php } ?>

現在執行
<?php a(); ?>
會回傳所有 CSS,就像您直接在頁面上撰寫或使用 include() 一樣。在函式中使用 HTML 程式碼也是一樣的。有無限的可能性...
php-note-2003-june-18 at ryandesign dot com
21 年前
Xavier 的例子相當複雜,他的任務使用類別會更容易完成。定義一個基底類別來執行基本的 open、dump 和 close 函式,並建立擴展類別來覆寫任何行為。

class foo {
function open() {
// open() 的預設功能
}
function dump() {
// dump() 的預設功能
}
function close() {
// close() 的預設功能
}
}

class bar extends foo {
function open() {
// 覆寫 open() 的功能
}
// dump() 和 close() 保持與 foo 類別相同
}
xmontero at dsitelecom dot com
22 年前
您可以使用 "function_exists" 在 PHP 中進行某種函式覆載。

假設您希望一個腳本調用 php 檔案形式的插件,並且您希望插件「覆寫」未被覆寫時使用的預設行為。

例如,您可以編寫一個「MySQL 表格檢視器」,它顯示一個表格,並「開啟表格」、「轉儲標題」、「逐行轉儲」,然後「關閉表格」。

假設您需要一個「股票」插件,它以紅色顯示負股票,因此您想覆寫「逐行轉儲」來實現該行為。您不希望在插件中重複所有「預設行為」。

您可以執行以下操作

1) 定義一個預設插件(例如:"default.php")

2) 將所有函式寫入 default.php 以進行開啟、轉儲和關閉,但添加一個後綴

open_table_default()
dump_header_default()
dump_row_default()
close_table_default()

3) 使用包裝器調用您的函式:不要這樣寫
open_table() 或 open_table_default() 而是這樣寫

plugincall("open_table");

4) 然後編寫一個名為 plugincall 的函式,它使用 function_exists() 來查看您調用的是哪個函式

function plugincall($desired_function_name)
{

if( function_exists( $desired_function_name))
{
//調用插件
//注意名稱前的 $
$desired_function_name();
}
else
{
$desired_function_name = $desired_function_name . "_default";
if( function_exists($desired_function_name))
{
//調用預設函式
//注意名稱前的 $
$desired_function_name();
}
else
{
// 插件和預設函式都未定義
}
}

因此,現在,如果 require_once(plugin.php) 包含一個名為 "open_table()" 的函式,則會使用它。否則,將使用 "open_table_default()"。

它不像函式覆載,但對於編寫可由其他程式設計師擴展的腳本非常有用:如果他們編寫了一個函式,則使用該函式,否則使用預設函式。

再見!
Xavier Montero.
To Top