在PHP 中, sprintf函數是一個強大的字符串格式化工具,能夠將變量以指定格式插入字符串中。例如:
$name = "Alice";
$age = 30;
echo sprintf("我的名字是 %s,今年 %d 歲。", $name, $age);
輸出為:
我的名字是 Alice,今年 30 歲。
雖然sprintf已經非常實用,但有時我們可能希望更靈活地控制格式化方式,或者在某些框架或環境下實現一個“輕量版”或者“可定製版”的格式化函數。本文將介紹如何用PHP 自定義一個類似sprintf的格式化函數。
我們希望實現一個函數my_sprintf($template, $args) ,其支持以下功能:
替換佔位符,如%s 、 %d ;
支持順序傳參或數組傳參;
保持良好的可讀性與可維護性。
我們從一個簡單的實現開始,僅支持%s和%d :
function my_sprintf($template, ...$args) {
$argIndex = 0;
$result = preg_replace_callback('/%[sd]/', function($matches) use (&$args, &$argIndex) {
$placeholder = $matches[0];
$value = $args[$argIndex++] ?? '';
if ($placeholder === '%d') {
return intval($value);
} elseif ($placeholder === '%s') {
return strval($value);
} else {
return $placeholder;
}
}, $template);
return $result;
}
echo my_sprintf("歡迎 %s,您有 %d 條新消息。", "Alice", 5);
輸出:
歡迎 Alice,您有 5 條新消息。
如果我們想讓這個函數也支持將參數以數組形式傳入,可以稍作修改:
function my_sprintf_array($template, array $args) {
$argIndex = 0;
$result = preg_replace_callback('/%[sd]/', function($matches) use (&$args, &$argIndex) {
$placeholder = $matches[0];
$value = $args[$argIndex++] ?? '';
return match ($placeholder) {
'%d' => intval($value),
'%s' => strval($value),
default => $placeholder,
};
}, $template);
return $result;
}
echo my_sprintf_array("請訪問 https://gitbox.net/user/%s,積分:%d", ["alice", 100]);
輸出:
請訪問 https://gitbox.net/user/alice,積分:100
我們還可以進一步支持格式如%05d (寬度為5,左側補零):
function my_sprintf_extended($template, ...$args) {
$argIndex = 0;
$result = preg_replace_callback('/%0?(\d*)([sd])/', function($matches) use (&$args, &$argIndex) {
$width = (int)($matches[1] ?? 0);
$type = $matches[2];
$value = $args[$argIndex++] ?? '';
if ($type === 'd') {
$formatted = str_pad(intval($value), $width, '0', STR_PAD_LEFT);
} else {
$formatted = strval($value);
}
return $formatted;
}, $template);
return $result;
}
echo my_sprintf_extended("訂單號:%05d,用戶:%s", 42, "bob");
輸出:
訂單號:00042,用戶:bob
通過上述幾個版本的實現,我們可以看到:
自定義格式化函數讓我們可以根據業務需要靈活控制;
利用正則表達式結合回調函數,是實現類似sprintf的關鍵;
若需更複雜格式(如浮點、進制、佔位順序等),可繼續擴展正則表達式的解析規則。
在實際項目中,這類函數也常用於自定義模板引擎、日誌記錄系統或DSL(領域特定語言)開發中,為開髮帶來更多便利與控制力。
你可以將這個函數封裝進自己的工具庫中,在類似https://gitbox.net這樣的項目中使用,提升開發效率。