У Python есть функция, называемая строками шаблона .
>>> from string import Template >>> s = Template('$who likes $what') >>> s.substitute(who='tim', what='kung pao') 'tim likes kung pao'
Я знаю, что PHP позволяет писать:
"Hello $person"
и заменить $person
, но шаблоны могут быть повторно использованы в разных разделах кода?
Я думаю, что есть множество способов сделать это … но это приходит на ум.
$search = array('%who%', '%what_id%'); $replace = array('tim', 'kung pao'); $conference_target = str_replace( $search, $replace, "%who% likes %what%" );
Ха, у нас даже был один в наших рамках, используя vsprintf :
class Helper_StringFormat { public static function sprintf($format, array $args = array()) { $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1); for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_]\w*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) { $arg_pos = $match[0][2]; $arg_len = strlen($match[0][0]); $arg_key = $match[1][0]; if (! array_key_exists($arg_key, $arg_nums)) { user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING); return false; } $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len); $pos = $arg_pos + strlen($replace); } return vsprintf($format, array_values($args)); } }
Похоже, что это произошло на странице sprintf
Это позволяет использовать такие вызовы, как:
sprintfn('second: %(second)s ; first: %(first)s', array( 'first' => '1st', 'second'=> '2nd' ));
ОБНОВИТЬ
Вот обновление, чтобы сделать то, что вы хотите … не полностью протестировано
class Helper_StringFormat { public static function sprintf($format, array $args = array()) { $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1); for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_][\w\s]*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) { $arg_pos = $match[0][1]; $arg_len = strlen($match[0][0]); $arg_key = $match[1][0]; if (! array_key_exists($arg_key, $arg_nums)) { user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING); return false; } $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len); $pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration } return vsprintf($format, array_values($args)); } } $str = "%(my var)s now work with a slight %(my var2)s"; $repl = array("my var" => "Spaces", "my var2" => "modification."); echo Helper_StringFormat::sprintf($str, $repl);
ВЫВОД
Пространства теперь работают с небольшой модификацией.
Я сделал функцию, чтобы делать то, что вы хотите. я сделал это «quck-and-грязным», потому что у меня мало времени на его рефакторинг, возможно, я загружу его в свой github.
EDIT: исправление ошибок …
Используйте его как
formattemplatter( '$who likes $what' , array( 'who' => 'Tim' , 'what' => 'Kung Pao' ) );
Переменные могут быть [a-zA-Z0-9_].
function formattemplater($string, $params) { // Determine largest string $largest = 0; foreach(array_keys($params) as $k) { if(($l=strlen($k)) > $largest) $largest=$l; } $buff = ''; $cp = false; // Conditional parenthesis $ip = false; // Inside parameter $isp = false; // Is set parameter $bl = 1; // buffer length $param = ''; // current parameter $out = ''; // output string $string .= '!'; for($sc=0,$c=$oc='';isset($string{$sc});++$sc,++$bl) { $c = $string{$sc}; if($ip) { $a = ord($c); if(!($a == 95 || ( // underscore ($a >= 48 && $a <= 57) // 0-9 || ($a >= 65 && $a <= 90) // AZ || ($a >= 97 && $a <= 122) // az ) )) { $isp = isset($params[$buff]); if(!$cp && !$isp) { trigger_error( sprintf( __FUNCTION__.': the parameter "%s" is not defined' , $buff ) , E_USER_ERROR ); } elseif(!$cp || $isp) { $out .= $params[$buff]; } $isp = $isp && !empty($params[$buff]); $oc = $buff = ''; $bl = 0; $ip = false; } } if($cp && $c === ')') { $out .= $buff; $cp = $isp = false; $c = $buff = ''; $bl = 0; } if(($cp && $isp) || $ip) $buff .= $c; if($c === '$' && $oc !== '\\') { if($oc === '(') $cp = true; else $out .= $oc; $ip = true; $buff = $c = $oc = ''; $bl = 0; } if(!$cp && $bl > $largest) { $buff = substr($buff, - $largest); $bl = $largest; } if(!$ip && ( !$cp || ($cp && $isp))) { $out .= $oc; if(!$cp) $oc = $c; } } return $out; }
Другим более простым подходом было бы следующее:
$s = function ($vars) { extract($vars); return "$who likes $what"; }; echo $s(['who' => 'Tim', 'what' => 'King Pao']); // Tim likes King Pao
И да, PHPStorm будет жаловаться …