mejor - ¿PHP tiene una característica como las cadenas de plantilla de Python?
python web (4)
Creo que hay muchas maneras de hacer esto ... pero esto me viene a la mente.
$search = array(''%who%'', ''%what_id%'');
$replace = array(''tim'', ''kung pao'');
$conference_target = str_replace(
$search,
$replace,
"%who% likes %what%"
);
Ja, incluso teníamos uno en nuestro marco usando 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));
}
}
Lo que parece que vino de la página de sprintf
Esto permite llamadas como:
sprintfn(''second: %(second)s ; first: %(first)s'', array(
''first'' => ''1st'',
''second''=> ''2nd''
));
ACTUALIZAR
Aquí hay una actualización para hacer lo que quieras ... aunque no está completamente probado
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);
SALIDA
Los espacios ahora funcionan con una ligera modificación.
Python tiene una característica llamada cadenas de plantillas .
>>> from string import Template
>>> s = Template(''$who likes $what'')
>>> s.substitute(who=''tim'', what=''kung pao'')
''tim likes kung pao''
Sé que PHP te permite escribir:
"Hello $person"
¿Se ha sustituido a $person
, pero las plantillas se pueden reutilizar en varias secciones del código?
Hice una función para hacer lo que quieras. Lo hice "quck-and-dirty" porque no tengo mucho tiempo para refactorizarlo, tal vez lo subo a mi github.
EDITAR: una corrección de errores ...
Utilízalo como
formattemplatter(
''$who likes $what''
, array(
''who'' => ''Tim''
, ''what'' => ''Kung Pao''
)
);
Las variables pueden ser [a-zA-Z0-9_] solamente.
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) // A-Z
|| ($a >= 97 && $a <= 122) // a-z
)
)) {
$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;
}
Otro enfoque más simple sería este:
$s = function ($vars) {
extract($vars);
return "$who likes $what";
};
echo $s([''who'' => ''Tim'', ''what'' => ''King Pao'']); // Tim likes King Pao
Y sí, PHPStorm se quejará ...