如何用PHP中的值replacestring中的variables?
我在数据库中有这样的string(实际string包含100个字和10个variables)
i am a {$club} fan
我回声这样的string
$club = "Barcelona"; echo $data_base[0]['body'];
我的输出是i am a {$club} fan
。 我想i am a Barcelona fan
我该怎么做?
使用strtr
它将翻译一个string的部分。
$club = "Barcelona"; echo strtr($data_base[0]['body'], array('{$club}' => $club));
对于多个值( Demo ):
$data_base[0]['body'] = 'I am a {$club} fan.'; // Tests $vars = array( '{$club}' => 'Barcelona', '{$tag}' => 'sometext', '{$anothertag}' => 'someothertext' ); echo strtr($data_base[0]['body'], $vars);
节目输出:
I am a Barcelona fan.
if (preg_match_all('#\$([a-zA-Z0-9]+)#', $q, $matches, PREG_SET_ORDER)); { foreach ($matches as $m) { eval('$q = str_replace(\''.$m[0].'\',$'.$m[1].',$q);'); } }
这匹配所有的$variables,并用它们replace它们。 我不包括{}的,但不应该太难以添加像这样的东西…
if (preg_match_all('#\{\$([a-zA-Z0-9]+)\}#', $q, $matches, PREG_SET_ORDER)); { foreach ($matches as $m) { eval('$q = str_replace(\''.$m[0].'\',$'.$m[1].',$q);'); } }
虽然看起来比硬编码每个variables慢一点。 它引入了一个eval的安全漏洞。 这就是为什么我的正则expression式如此有限。 限制eval可以抓取的范围。
我用ajax写了自己的正则expression式testing器,所以我可以看到,如果我的expression式正常工作。 我有我喜欢在我的expression式中使用的variables,以便我不需要为每个expression式重新键入相同的位。
我会build议sprintf()
函数。
而不是存储i am a {$club} fan
使用i am a %s fan
,所以你的回声命令会像这样:
$club = "Barcelona"; echo sprintf($data_base[0]['body'],$club);
输出:我是巴塞罗那球迷
这将给你自由使用相同的代码与任何其他variables(你甚至不必记住variables名称)。
所以这段代码对于同一个string也是有效的:
$food = "French Fries"; echo sprintf($data_base[0]['body'],$food);
输出:我是一个炸薯条的粉丝
$language = "PHP"; echo sprintf($data_base[0]['body'],$language);
输出:我是一个PHP粉丝
/** * A function to fill the template with variables, returns filled template. * * @param string $template A template with variables placeholders {$varaible}. * @param array $variables A key => value store of variable names and values. * * @return string */ public function replaceVariablesInTemplate($template, array $variables){ return preg_replace_callback('#{(.*?)}#', function($match) use ($variables){ $match[1]=trim($match[1],'$'); return $variables[$match[1]]; }, ' '.$template.' '); }
你正在寻找的是嵌套的string插值。 一个理论可以阅读在这个职位: http : //thehighcastle.com/blog/21/wanted-php-core-function-for-dynamically-performing-double-quoted-string-variable-interpolation
主要的问题是你并不知道所有可用的variables,或者可能有太多可以列出的variables。
考虑下面的testing代码片段。 我从mohammad mohsenipur偷了正则expression式。
$testA = '123'; $testB = '456'; $testC = '789'; $t = '{$testA} adsf {$testB}adf 32{$testC} fddd{$testA}'; echo 'before: '.$t."\n"; preg_match_all('~\{\$(.*?)\}~si',$t,$matches); if ( isset($matches[1])) { $r = compact($matches[1]); foreach ( $r as $var => $value ) { $t = str_replace('{$'.$var.'}',$value,$t); } } echo 'after: '.$t."\n";
您的代码可能是:
$club = 'Barcelona'; $tmp = $data_base[0]['body']; preg_match_all('~\{\$(.*?)\}~si',$tmp,$matches); if ( isset($matches[1])) { $r = compact($matches[1]); foreach ( $r as $var => $value ) { $tmp = str_replace('{$'.$var.'}',$value,$tmp); } } echo $tmp;
这里是我的解决scheme:
$club = "Barcelona"; $string = 'i am a {$club} fan'; preg_match_all("/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/",$string,$matches); foreach ($matches[0] as $key => $var_name) { if (!isset($GLOBALS[$matches[1][$key]])) $GLOBALS[$matches[1][$key]] = 'default value'; $string = str_replace($var_name, $GLOBALS[$matches[1][$key]], $string); }
你可以使用一个简单的parsing器,如果它存在的话,它将用一个来自映射的值replace{$ key}。 像使用$text = templateWith('hello $item}',array('item'=>'world'...));
我的第一个版本是:
/** * Template with a string and simple map. * @param string $template * @param array $substitutions map of substitutions. * @return string with substitutions applied. */ function templateWith(string $template, array $substitutions) { $state = 0; // forwarding $charIn = preg_split('//u', $template, -1, PREG_SPLIT_NO_EMPTY); $charOut = array(); $count = count($charIn); $key = array(); $i = 0; while ($i < $count) { $char = $charIn[$i]; switch ($char) { case '{': if ($state === 0) { $state = 1; } break; case '}': if ($state === 2) { $ks = join('', $key); if (array_key_exists($ks, $substitutions)) { $charOut[] = $substitutions[$ks]; } $key = array(); $state = 0; } break; case '$': if ($state === 1) { $state = 2; } break; case '\\': if ($state === 0) { $i++; $charOut[] = $charIn[$i]; } continue; default: switch ($state) { default: case 0: $charOut[] = $char; break; case 2: $key[] = $char; break; } } $i++; } return join('', $charOut); }
试试preg_replace
php函数。
http://php.net/manual/en/function.preg-replace.php
<?php $club = "barcelona"; echo $string = preg_replace('#\{.*?\}#si', $club, 'i am a {$club} fan'); ?>
像这样的东西应该可以解决你的问题:
$club = "Barcelona"; $var = 'I am a {$club} fan'; $res = preg_replace('/\{\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/e', "$$1", $var); echo "$res\n";
这是一个单行的preg_replace
。
更新:与PHP 5.5 /e
修饰符已弃用。 你可以使用callback代替:
$club = "Barcelona"; $var = 'I am a {$club} fan'; $res = preg_replace_callback('/\{\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/', create_function( '$matches', 'extract($GLOBALS, EXTR_REFS | EXTR_SKIP); return $$matches[1];'), $var); echo "$res\n";
请注意,这使用导入所有全局variables的黑客。 这可能不是你想要的。 可能使用闭包将是一个更好的主意。
你可以使用preg_replace_callback来获取variables名称
$data_base[0]['body'] = preg_replace_callback( '#{(.*?)}#', function($m) { $m[1]=trim($m[1],'$'); return $this->$m[1]; }, ' '.$data_base[0]['body'].' ' );
注意我写的代码是为class($this);
你可以在类中声明variables。 然后使用这个代码检测variables,并将其replace
<?php class a{ function __construct($array){ foreach($array as $key=>$val){ $this->$key=$val; } } function replace($str){ return preg_replace_callback('#{(.*?)}#',function($m){$m[1]=trim($m[1],'$');return $this->$m[1];},' '.$str.' '); } } $obj=new a(array('club'=>3523)); echo $obj->replace('i am a {$club} fan');
输出:
i am a 3523 fan