PHP 7.1 用动态变量替换多个值
PHP 7.1 replace multiple values with dynamic variables
我是 PHP 的新手,虽然我找到了解决问题的方法,但我觉得肯定有更简单的方法来实现相同的结果:
这是我需要做的:
我有一个这样的字符串(在真实的字符串中有大约 25 个值要替换)
"We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##"
在这个字符串中我必须替换
##AMOUNT##
具有名为 $AMOUNT
的变量的值
##CURRENCY##
变量值为 $CURRENCY
##ORDER_ID##
变量值 $ORDER_ID
目前我创建了一个数组:
$flds=['AMOUNT','CURRENCY','ORDER_ID'];
我使用循环和动态变量替换:
但我看到 str_replace 也接受数组,因此可以构建一个更优雅(和高效)的解决方案
但是...我找不到它
可以给点提示吗?
谢谢
更优雅的方式是printf
函数。
vsprintf("We have received %s %s for your OrderID n. %s", array($AMOUNT, $CURRENCY, $ORDER_ID));
您可以对两个数组使用 str_replace 函数,一个是搜索词,另一个是替换词:
$words = ["##AMOUNT##", "##CURRENCY##", "##ORDER_ID##"];
$replaces = [$AMOUNT,$CURRENCY,$ORDER_ID];
$newString = str_replace($words, $replaces, $string);
echo $newString;
您可以使用str_replace(), if you got arbitrary variables you can use compact()将它们放在一个数组中。
<?php
$str = "We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##";
$AMOUNT = 123;
$CURRENCY = 'GBP';
$ORDER_ID = 20123;
$find = ['##AMOUNT##','##CURRENCY##','##ORDER_ID##'];
$replace = compact('AMOUNT', 'CURRENCY', 'ORDER_ID');
echo str_replace($find, $replace, $str);
结果:
我们已收到您的 OrderID n 的 123 英镑。 20123
如果您正在寻找一种方法来定义 variables/placeholders 一次,然后进行匹配和替换,您可以这样做:
<?php
$str = "We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##";
$AMOUNT = 123;
$CURRENCY = 'GBP';
$ORDER_ID = 20123;
$find = ['AMOUNT', 'CURRENCY', 'ORDER_ID'];
echo str_replace(
array_map(function($v){ return '##'.$v.'##'; }, $find),
compact(...$find),
$str
);
我会制作一个简单的模板 class 来解析它,
class SimpleTemplate
{
protected $src;
protected $vars;
public function __construct($src)
{
$this->src = $src;
}
public function assign($key, $value)
{
$this->vars[$key] = $value;
}
public function out()
{
return str_replace(array_keys($this->vars),$this->vars,$this->src);
}
}
$T = new SimpleTemplate("We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##");
$T->assign('##AMOUNT##', 'foo');
$T->assign('##CURRENCY##', 'bar');
$T->assign('##ORDER_ID##', 'hello');
echo $T->out();
输出:
"We have received foo bar for your OrderID n. hello"
可以看到here live:
而且您可以随时对其进行扩展并添加功能,例如从作业中删除 ##
,以及删除任何未使用的标签。等...
基本上它只是一个变量的数组管理工具。因为我们正在构建一个这样的数组:
[
'##AMOUNT##' => 'foo',
'##CURRENCY##' => 'bar',
'##ORDER_ID##' => 'hello'
];
然后使用 str_replace
我们使用键作为搜索,值作为替换值。
如果您想从标签分配中删除 ##
,只需更改此:
public function assign($key, $value)
{
$this->vars['##'.$key.'##'] = $value;
}
然后这样调用:
$T->assign('AMOUNT', 'foo');
这里的真正好处是有一个 class 来实现您的逻辑。它保持清洁和可重复使用。
更新
正如@LawrenceCherone 在评论中提到的,您可以通过使用一些神奇的方法来获得更简洁的界面。
class SimpleTemplate
{
protected $src;
protected $vars;
public function __construct($src)
{
$this->src = $src;
}
public function __set($key, $value)
{
$this->vars['##'.strtoupper($key).'##'] = $value;
}
public function __toString()
{
return str_replace(array_keys($this->vars),$this->vars,$this->src);
}
}
$T = new SimpleTemplate("We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##");
$T->Amount = 'foo'; //any casing works because of the transforms, in __set
$T->CURRENCY = 'bar';
$T->order_id = 'hello';
echo $T; //using __toString() lets us just output the class as our result string.
特别是 __set
和 __toString
。对于这个,我在 key
上做了一些转换,以使其更不容易出错,也更不难看。例如,为动态属性使用混合大小写。通过使用 strtoupper
它们可以在任何情况下输入,并且删除 #
可以避免像这样包装它们 $T->{'##AMOUNT##'} = 'foo';
我要添加的最后一件事是,如果您可以拥有未分配但希望删除它们的“标签”,您可以使用此 regx 删除它们。
public function __toString()
{
$str = str_replace(array_keys($this->vars),$this->vars,$this->src);
return preg_replace(['/##\w+##/', '/\s{2,}/'], ['', ' '], $str); //remove any left over ##{word}## tags, and compress any run-on spaces.
}
你可以看到这个例子here
数组 /\s{2,}/
中的第二个
只是在 space 上取 运行 并将它们压缩为单个 space,所以如果你有 4 spaces 它变成了一个 space。它没有很好的记录,但 preg_replace
可以像 str_replace
一样接受数组。
这就是为什么我建议构建一个 class,它为您提供了一个很好的地方来实现所有这些“东西”(如果您愿意),而不必一直重写它。
str_replace
将使用数组。如果 $find
是一个数组并且 $replace
是一个字符串,它将用 $replace
中的字符串替换 $find
中的所有内容,如果两者都是数组,它将替换每个对应的元素 $find[index]
及其相应的 $replace[index]
示例:
$find = ["find1", "find2" ];
$replace = [ "replace1", "replace2" ];
$string = "Find find1 and find2";
echo str_replace($find, $replace, $string); // "Find replace1 and replace2"
但是有一个小问题,即替换是按顺序完成的。通常这不是问题,直到您遇到类似的情况:
$find = [ "find", "find2" ];
$replace = [ "replace", "replaceXX2" ];
$string = "Find find1 and find2";
echo str_replace($find, $replace, $string); // "Find replace1 and replace2"
为什么?因为它会在查找 "find2".
之前用 replace 替换 "find" 单词和 find2 的一部分 "find"
如果你想避免这种情况,你可以使用 strtr
如下:
$find = [ "find" => "replace" , "find2" => "replaceXX" ];
$string = "Find find1 and find2";
echo strtr($string, $find); // "Find replace1 and replaceXX"
@Lawrence Cherone 回答的另一种方式。也许您想使用 key => value
列表。
<?php
$message = "We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##";
$messageParameters = [
'AMOUNT' => 83,
'CURRENCY' => 'USD',
'ORDER_ID' => 3271096
];
$parsedMessage = str_replace(
array_map(function($v){ return '##'.$v.'##'; }, array_keys($messageParameters)),
array_values($messageParameters),
$message
);
echo $parsedMessage;
结果:
We have received 83 USD for your OrderID n. 3271096
我是 PHP 的新手,虽然我找到了解决问题的方法,但我觉得肯定有更简单的方法来实现相同的结果:
这是我需要做的:
我有一个这样的字符串(在真实的字符串中有大约 25 个值要替换)
"We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##"
在这个字符串中我必须替换
##AMOUNT##
具有名为 $AMOUNT
的变量的值
##CURRENCY##
变量值为 $CURRENCY
##ORDER_ID##
变量值 $ORDER_ID
目前我创建了一个数组:
$flds=['AMOUNT','CURRENCY','ORDER_ID'];
我使用循环和动态变量替换:
但我看到 str_replace 也接受数组,因此可以构建一个更优雅(和高效)的解决方案
但是...我找不到它
可以给点提示吗?
谢谢
更优雅的方式是printf
函数。
vsprintf("We have received %s %s for your OrderID n. %s", array($AMOUNT, $CURRENCY, $ORDER_ID));
您可以对两个数组使用 str_replace 函数,一个是搜索词,另一个是替换词:
$words = ["##AMOUNT##", "##CURRENCY##", "##ORDER_ID##"];
$replaces = [$AMOUNT,$CURRENCY,$ORDER_ID];
$newString = str_replace($words, $replaces, $string);
echo $newString;
您可以使用str_replace(), if you got arbitrary variables you can use compact()将它们放在一个数组中。
<?php
$str = "We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##";
$AMOUNT = 123;
$CURRENCY = 'GBP';
$ORDER_ID = 20123;
$find = ['##AMOUNT##','##CURRENCY##','##ORDER_ID##'];
$replace = compact('AMOUNT', 'CURRENCY', 'ORDER_ID');
echo str_replace($find, $replace, $str);
结果:
我们已收到您的 OrderID n 的 123 英镑。 20123
如果您正在寻找一种方法来定义 variables/placeholders 一次,然后进行匹配和替换,您可以这样做:
<?php
$str = "We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##";
$AMOUNT = 123;
$CURRENCY = 'GBP';
$ORDER_ID = 20123;
$find = ['AMOUNT', 'CURRENCY', 'ORDER_ID'];
echo str_replace(
array_map(function($v){ return '##'.$v.'##'; }, $find),
compact(...$find),
$str
);
我会制作一个简单的模板 class 来解析它,
class SimpleTemplate
{
protected $src;
protected $vars;
public function __construct($src)
{
$this->src = $src;
}
public function assign($key, $value)
{
$this->vars[$key] = $value;
}
public function out()
{
return str_replace(array_keys($this->vars),$this->vars,$this->src);
}
}
$T = new SimpleTemplate("We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##");
$T->assign('##AMOUNT##', 'foo');
$T->assign('##CURRENCY##', 'bar');
$T->assign('##ORDER_ID##', 'hello');
echo $T->out();
输出:
"We have received foo bar for your OrderID n. hello"
可以看到here live:
而且您可以随时对其进行扩展并添加功能,例如从作业中删除 ##
,以及删除任何未使用的标签。等...
基本上它只是一个变量的数组管理工具。因为我们正在构建一个这样的数组:
[
'##AMOUNT##' => 'foo',
'##CURRENCY##' => 'bar',
'##ORDER_ID##' => 'hello'
];
然后使用 str_replace
我们使用键作为搜索,值作为替换值。
如果您想从标签分配中删除 ##
,只需更改此:
public function assign($key, $value)
{
$this->vars['##'.$key.'##'] = $value;
}
然后这样调用:
$T->assign('AMOUNT', 'foo');
这里的真正好处是有一个 class 来实现您的逻辑。它保持清洁和可重复使用。
更新
正如@LawrenceCherone 在评论中提到的,您可以通过使用一些神奇的方法来获得更简洁的界面。
class SimpleTemplate
{
protected $src;
protected $vars;
public function __construct($src)
{
$this->src = $src;
}
public function __set($key, $value)
{
$this->vars['##'.strtoupper($key).'##'] = $value;
}
public function __toString()
{
return str_replace(array_keys($this->vars),$this->vars,$this->src);
}
}
$T = new SimpleTemplate("We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##");
$T->Amount = 'foo'; //any casing works because of the transforms, in __set
$T->CURRENCY = 'bar';
$T->order_id = 'hello';
echo $T; //using __toString() lets us just output the class as our result string.
特别是 __set
和 __toString
。对于这个,我在 key
上做了一些转换,以使其更不容易出错,也更不难看。例如,为动态属性使用混合大小写。通过使用 strtoupper
它们可以在任何情况下输入,并且删除 #
可以避免像这样包装它们 $T->{'##AMOUNT##'} = 'foo';
我要添加的最后一件事是,如果您可以拥有未分配但希望删除它们的“标签”,您可以使用此 regx 删除它们。
public function __toString()
{
$str = str_replace(array_keys($this->vars),$this->vars,$this->src);
return preg_replace(['/##\w+##/', '/\s{2,}/'], ['', ' '], $str); //remove any left over ##{word}## tags, and compress any run-on spaces.
}
你可以看到这个例子here
数组 /\s{2,}/
中的第二个
只是在 space 上取 运行 并将它们压缩为单个 space,所以如果你有 4 spaces 它变成了一个 space。它没有很好的记录,但 preg_replace
可以像 str_replace
一样接受数组。
这就是为什么我建议构建一个 class,它为您提供了一个很好的地方来实现所有这些“东西”(如果您愿意),而不必一直重写它。
str_replace
将使用数组。如果 $find
是一个数组并且 $replace
是一个字符串,它将用 $replace
中的字符串替换 $find
中的所有内容,如果两者都是数组,它将替换每个对应的元素 $find[index]
及其相应的 $replace[index]
示例:
$find = ["find1", "find2" ];
$replace = [ "replace1", "replace2" ];
$string = "Find find1 and find2";
echo str_replace($find, $replace, $string); // "Find replace1 and replace2"
但是有一个小问题,即替换是按顺序完成的。通常这不是问题,直到您遇到类似的情况:
$find = [ "find", "find2" ];
$replace = [ "replace", "replaceXX2" ];
$string = "Find find1 and find2";
echo str_replace($find, $replace, $string); // "Find replace1 and replace2"
为什么?因为它会在查找 "find2".
之前用 replace 替换 "find" 单词和 find2 的一部分 "find"如果你想避免这种情况,你可以使用 strtr
如下:
$find = [ "find" => "replace" , "find2" => "replaceXX" ];
$string = "Find find1 and find2";
echo strtr($string, $find); // "Find replace1 and replaceXX"
@Lawrence Cherone 回答的另一种方式。也许您想使用 key => value
列表。
<?php
$message = "We have received ##AMOUNT## ##CURRENCY## for your OrderID n. ##ORDER_ID##";
$messageParameters = [
'AMOUNT' => 83,
'CURRENCY' => 'USD',
'ORDER_ID' => 3271096
];
$parsedMessage = str_replace(
array_map(function($v){ return '##'.$v.'##'; }, array_keys($messageParameters)),
array_values($messageParameters),
$message
);
echo $parsedMessage;
结果:
We have received 83 USD for your OrderID n. 3271096