Skip to content

Instantly share code, notes, and snippets.

@rc1021
Last active December 23, 2024 08:22
Show Gist options
  • Save rc1021/04fc4a1308b8b416400fe43b99475cbd to your computer and use it in GitHub Desktop.
Save rc1021/04fc4a1308b8b416400fe43b99475cbd to your computer and use it in GitHub Desktop.
將 SQL 中的函數占位符 {function:params} 識別並替換為相應的結果

說明

將 SQL 中的函數占位符 {function:params} 識別並替換為相應的結果

$sql = "SELECT * FROM users 
WHERE created_at >= {date:Y-m-d H:i:s,strtotime:value:first day of last month}
AND created_at < {date:Y-m-d H:i:s,strtotime:first day of this month}
";

$queryBindngs = (new FunctionStrService)->parseAndReplaceFunctionsFromSql($sql);
DB::select(data_get($queryBindngs, 'query'), data_get($queryBindngs, 'params', []));
// output: 
// SELECT * FROM users WHERE created_at >= '2024-11-01 07:54:34' AND created_at < '2024-12-01 07:54:34'

多個 params 可以使用 {function1:param1,param2,function2:param3,param4,...}

<?php
class FunctionStrService
{
/**
* 解析 SQL 並替換函數佔位符為預處理的參數
*
* @param string $sql
* @return array ['query' => string, 'params' => array]
*/
function parseAndReplaceFunctionsFromSql($sql)
{
// 匹配模式:{function:params}
$pattern = '/\{([\w]+:[^}]+)\}/';
$params = [];
// 使用正則匹配替換函數字符串
$query = preg_replace_callback($pattern, function ($matches) use (&$params) {
// 解析函數字符串
$result = $this->parseFunctionString($matches[1]);
// 為參數綁定生成唯一鍵名
$params[] = $result;
// 返回佔位符
return '?';
}, $sql);
return ['query' => $query, 'params' => $params];
}
/**
* 將字串解析並執行,支援內嵌函數
*
* @param string $string 字串,格式為 "function:param1,param2"
* @return mixed 函數執行結果或原始字串
*/
function parseFunctionString($string) {
// 檢查字串是否符合 "function:param1,param2" 格式
if (preg_match('/^(\w+):(.+)$/', $string, $matches)) {
$function = $matches[1]; // 提取函數名稱
$args = explode(',', $matches[2]); // 提取參數
// 處理參數中的內嵌函數
foreach ($args as &$arg) {
if (preg_match('/^([\w]+):(.+)$/', $arg)) {
$arg = $this->parseFunctionString($arg); // 遞歸解析內嵌函數
}
}
// 確認函數是否存在並執行
if (function_exists($function)) {
return call_user_func_array($function, $args); // 返回函數執行結果
}
}
// 如果字串不符合格式或函數不存在,返回原始字串
return $string;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment