关于php:在字符串中替换占位符变量

1,889次阅读
2 条评论

Replacing Placeholder Variables in a String

刚完成此功能。 基本上,假设要遍历一个字符串并尝试找到任何占位符变量,这些变量将位于两个大括号{}之间。 它获取大括号之间的值,并使用它查看应与键匹配的数组。 然后,它将字符串中的花括号变量替换为匹配键数组中的值。

但是它有一些问题。 首先是当我var_dump($matches)时,将结果放入数组中的数组中。 因此,我必须使用两个foreach()才能达到正确的数据。

我也觉得它很重,我一直在寻找它,试图使其变得更好,但我有些沮丧。 我错过了任何优化吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function dynStr($str,$vars) {
 preg_match_all(“/\{[A-Z0-9_]+\}+/”, $str, $matches);
 foreach($matches as $match_group) {
 foreach($match_group as $match) {
 $match = str_replace(“}”,””, $match);
 $match = str_replace(“{“,””, $match);
 $match = strtolower($match);
 $allowed = array_keys($vars);
 $match_up = strtoupper($match);
 $str = (in_array($match, $allowed)) ? str_replace(“{“.$match_up.”}”, $vars[$match], $str) : str_replace(“{“.$match_up.”}”, ”, $str);
 }
 }
 return $str;
}$variables = array(“first_name”=>”John”,”last_name”=>”Smith”,”status”=>”won”);
$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;
echo dynStr($string,$variables);
//Would output: ‘Dear John Smith, we wanted to tell you that you won the competition.’

 相关讨论

  • 请向我们提供数据样本($ str和$ vars)
  • 您的方法效率很低。考虑另一种方法:a)使用preg_replace_callback从$vars返回匹配的令牌值,而无需进行一百万次str_replace调用; b)转换$vars中的每个条目以包括前导/后括号,然后将$vars馈入strtr。
  • 您是作为学习练习还是为生产而做的?如果用于生产,您可能想要查看类似smarty的模板库
  • @DCoder:您能提供一些例子吗?我对你说的话感到困惑。
  • @ dm03514供生产使用,但就像初稿一样。不是最终产品。它也不是模板。它是新闻通讯。
  • @TylerDusty:我的第一个建议与下面发布的fireeyedboy相同。
  • @TylerDusty smarty是一个模板库,旨在完全满足您的需求,但是smarty是一个大型成熟项目。它现在就可以使用,并且可以处理项目开发过程中遇到的所有疯狂情况,而且它既快速又可靠。

我认为对于这样一个简单的任务,您无需使用RegEx:

1
2
3
4
5
6
7
8
$variables = array(“first_name”=>”John”,”last_name”=>”Smith”,”status”=>”won”);
$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;foreach($variables as $key => $value){
 $string = str_replace(‘{‘.strtoupper($key).’}’, $value, $string);
}echo $string; // Dear John Smith, we wanted to tell you that you won the competition.

 相关讨论

  • 实际上,这甚至比我的答案还要简单,甚至可能足够。
  • 哇,是的我想我们都考虑得太多了。不良运行一些测试,看是否更快,并告知您。足够。
  • @fireeyedboy我喜欢您的preg_replace_callback()解决方案,我试图弄清楚如何使用匿名函数以及如何在范围内包含$allowed变量,然后我看到了您的答案。 +1:D
  • @HamZaDzCyber??DeV我太挂了,想变得漂亮,以至于没有想到像您这样的解决方案。有时先退后一步会有所帮助。我对您的解决方案只发生了一点小小的警告,那就是它不利于从输入字符串中删除无效的占位符(但这并不是开始时的要求)。
  • 提示:str_replace可以使用字符串数组来查找/替换。一个str_replace呼叫可能会快于一百。
  • @DCoder是的,您是对的,这里的问题是$variables中的键不能以正确的格式(用{}和大写字母包围)。

我希望我加入该聚会还为时不晚-这是我的工作方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function template_substitution($template, $data) {
 $placeholders = array_keys($data);
 foreach ($placeholders as &$placeholder) {
 $placeholder = strtoupper(“{{$placeholder}}”);
 }
 return str_replace($placeholders, array_values($data), $template);
}$variables = array(
 ‘first_name’ => ‘John’,
 ‘last_name’ => ‘Smith’,
 ‘status’ => ‘won’,
);$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you have {STATUS} the competition.’;echo template_substitution($string, $variables);

而且,只要有机会使您的$variables键与占位符完全匹配,解决方案就变得非常简单:

1
2
3
4
5
6
7
8
9
$variables = array(
 ‘{FIRST_NAME}’ => ‘John’,
 ‘{LAST_NAME}’ => ‘Smith’,
 ‘{STATUS}’ => ‘won’,
);$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you have {STATUS} the competition.’;echo strtr($string, $variables);

(请参阅PHP手册中的strtr()。)

考虑到PHP语言的性质,我认为这种方法应该在该线程中列出的所有方法中产生最佳性能。

 相关讨论

  • 我同意-除了性能,这也是最具可读性和可维护性的恕我直言。我对另一个问题的回答(stackoverflow.com/a/36781566/224707)也显示了此方法的其他优点,例如能够在处理之前以编程方式增强替换值(例如对它们进行编码或主题化)…

我认为您可以通过以下方式大大简化您的代码(除非我误解了一些要求):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$allowed = array(“first_name”=>”John”,”last_name”=>”Smith”,”status”=>”won”);$resultString = preg_replace_callback// the pattern, no need to escape curly brackets
 // uses a group (the parentheses) that will be captured in $matches[ 1 ]
 ‘/{([A-Z0-9_]+)}/’, // the callback, uses $allowed array of possible variables
 function( $matches ) use ( $allowed )
 {
 $key = strtolower( $matches[ 1 ] );
 // return the complete match (captures in $matches[ 0 ]) if no allowed value is found
 return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : $matches[ 0 ];
 }, // the input string
 $yourString
);

PS .:如果要删除输入字符串中不允许的占位符,请替换

1 return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : $matches[ 0 ];

1 return array_key_exists( $key, $allowed ) ? $allowed[ $key ] : ”;

 相关讨论

  • 看起来可能更好,但是我对function( $matches ) use ( $allowed )是什么感到好奇吗?我从来没有见过使用,我的代码编辑器(dreamweaver)说它不正确。
  • @TylerDusty:其匿名函数,需要PHP 5.3。
  • @TylerDusty回调是一个闭包。 use构造用于从定义范围导入变量,以便可以在闭包内部使用它。确实,正如DCoder已经提到的那样,它具有PHP 5.3+功能。

只是提醒将来进入此页面的人:使用foreach循环和/或str_replace方法的所有答案(包括接受的答案)都容易用OL’Johnny {STATUS}的名字替换Johnny won。

我看到,目前发布的仅有的几个方法不错,如Decent Dabbler的preg_replace_callback方法和U-D13的第二个选项(但不是第一个),对此并不容易,但是由于我没有足够的声誉来添加评论,因此我想就是写一个完全不同的答案。

如果替换值包含用户输入,则一种更安全的解决方案是使用strtr函数而不是str_replace以避免重新替换可能出现在您的值中的任何占位符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$string = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;
$variables = array(
“first_name”=>”John”,
 // Note the value here
“last_name”=>”{STATUS}”,
“status”=>”won”
);// bonus one-liner for transforming the placeholders
// but it’s ugly enough I broke it up into multiple lines anyway :)
$replacement = array_combine(
 array_map(function($k) { return ‘{‘.strtoupper($k).’}’; }, array_keys($variables)),
 array_values($variables)
);echo strtr($string, $replacement);

输出:Dear John {STATUS}, we wanted to tell you that you won the competition.
而str_replace输出:Dear John won, we wanted to tell you that you won the competition.

 相关讨论

  • strtr()是此问题的正确答案。

这是我使用的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function searchAndReplace($search, $replace){
 preg_match_all(“/\{(.+?)\}/”, $search, $matches); if (isset($matches[1]) && count($matches[1]) > 0){
 foreach ($matches[1] as $key => $value) {
 if (array_key_exists($value, $replace)){
 $search = preg_replace(“/\{$value\}/”, $replace[$value], $search);
 }
 }
 }
 return $search;
}$array = array(
‘FIRST_NAME’ => ‘John’,
‘LAST_NAME’ => ‘Smith’,
‘STATUS’ => ‘won’
);$paragraph = ‘Dear {FIRST_NAME} {LAST_NAME}, we wanted to tell you that you {STATUS} the competition.’;// outputs: Dear John Smith, we wanted to tell you that you won the competition.

只需将其传递一些文本来进行搜索,然后输入包含替换项的数组即可。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
   replace placeholders with object
**/

$user = new stdClass();
$user->first_name = ‘Nick’;
$user->last_name = ‘Trom’;$message = ‘This is a {{first_name}} of a user. The user\’s {{first_name}} is replaced as well as the user\’s {{last_name}}.’;preg_match_all(‘/{{([0-9A-Za-z_]+)}}/’, $message, $matches);foreach($matches[1] as $match)
{
 if(isset($user->$match))
 $rep = $user->$match;
 else
 $rep = ”; $message = str_replace(‘{{‘.$match.’}}’, $rep, $message);
}echo $message;
正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 
评论(2 条评论)
2024-04-25 19:32:55 回复

Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.

     泰国
2024-07-17 04:33:20 回复

มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง

     美国新泽西