Twig 将字符串变量渲染为数组
Twig render string variable as array
我们正在使用 twig 渲染引擎,用负载数据填充 json。
或者换句话说:
{
"payload": {
"sld": "{{sld}}",
"tld": "{{tlds}}"
}
}
我正在循环所有变量并“呈现”值。当一切都是字符串时,它工作完美
{
"payload": {
"sld": "test",
"tld": "com"
}
}
但是,如果任何 twig 变量是数组,它就会崩溃。
或者换句话说:
{{tlds}} 是数组 === ["com", "net"]
因为是存放在json里,所以没有字符串引号"".
是写不出来的
预期结果应该是:
{
"payload": {
"sld": "test",
"tld": ["com", "net"]
}
}
你能帮我解决问题吗?
, you should use the built in json_encode
过滤器。
这就是说,这样做只会导致你的 JSON 对象的 HTML 编码版本。为了克服这个问题,您还必须使用 raw
过滤器。
所以有了 Twig 的这一衬里:
{{ data | json_encode() | raw }}
数据如下:
$data = [
[
"payload" => [
"sld" => "test",
"tld" => "com"
]
],
[
"payload" => [
"sld" => "test",
"tld" => [
"com",
"net"
]
]
]
];
这将为您提供此 JSON(为了可读性而美化):
[
{
"payload":{
"sld":"test",
"tld":"com"
}
},
{
"payload":{
"sld":"test",
"tld":[
"com",
"net"
]
}
}
]
所有这些都可以在这里测试:https://twigfiddle.com/i604iv
经过一些测试和集思广益,我决定删除树枝渲染器并将其迁移到更简单的版本。
长话短说,这将呈现所有类似 {{variable.something}} 的语法,并使用有效负载中的相应值填充它。
如果该值是一个数组,它将json对其进行编码,然后对其进行解码,以实现请求的功能。
private function renderVariables(array $variables = [], array $payload = [])
{
$rendered = [];
foreach ($variables as $key => $value) {
if (is_array($value)) {
$rendered[$key] = $this->renderVariables($value, $payload);
} else {
$rendered[$key] = $this->replaceMarkdown($value, $payload);
if (strpos($rendered[$key], '[') !== false || strpos($rendered[$key], '{') !== false) {
$rendered[$key] = json_decode($rendered[$key]);
}
}
}
return $rendered;
}
public function replaceMarkdown(string $param, array $argv)
{
return preg_replace_callback('/\{\%\s*(.*)\s*\%\}|\{\{(?!%)\s*((?:[^\s])*)\s*(?<!%)\}\}/i',
function ($field) use ($argv) {
$field = $field[2];
if (strpos($field, '.') !== false) {
$fields = explode('.', $field);
} else {
$fields = array($field);
}
$currentData = $argv; # we should take care for magic before foreach
foreach ($fields as $currentField) {
if (isset($currentData[$currentField])) {
$currentData = $currentData[$currentField];
} else {
return $field . '-not-found';
}
}
if (is_array($currentData)) {
$currentData = json_encode($currentData);
}
return (string)$currentData;
}, $param);
}
我们正在使用 twig 渲染引擎,用负载数据填充 json。
或者换句话说:
{
"payload": {
"sld": "{{sld}}",
"tld": "{{tlds}}"
}
}
我正在循环所有变量并“呈现”值。当一切都是字符串时,它工作完美
{
"payload": {
"sld": "test",
"tld": "com"
}
}
但是,如果任何 twig 变量是数组,它就会崩溃。 或者换句话说:
{{tlds}} 是数组 === ["com", "net"]
因为是存放在json里,所以没有字符串引号"".
是写不出来的预期结果应该是:
{
"payload": {
"sld": "test",
"tld": ["com", "net"]
}
}
你能帮我解决问题吗?
json_encode
过滤器。
这就是说,这样做只会导致你的 JSON 对象的 HTML 编码版本。为了克服这个问题,您还必须使用 raw
过滤器。
所以有了 Twig 的这一衬里:
{{ data | json_encode() | raw }}
数据如下:
$data = [
[
"payload" => [
"sld" => "test",
"tld" => "com"
]
],
[
"payload" => [
"sld" => "test",
"tld" => [
"com",
"net"
]
]
]
];
这将为您提供此 JSON(为了可读性而美化):
[
{
"payload":{
"sld":"test",
"tld":"com"
}
},
{
"payload":{
"sld":"test",
"tld":[
"com",
"net"
]
}
}
]
所有这些都可以在这里测试:https://twigfiddle.com/i604iv
经过一些测试和集思广益,我决定删除树枝渲染器并将其迁移到更简单的版本。
长话短说,这将呈现所有类似 {{variable.something}} 的语法,并使用有效负载中的相应值填充它。
如果该值是一个数组,它将json对其进行编码,然后对其进行解码,以实现请求的功能。
private function renderVariables(array $variables = [], array $payload = [])
{
$rendered = [];
foreach ($variables as $key => $value) {
if (is_array($value)) {
$rendered[$key] = $this->renderVariables($value, $payload);
} else {
$rendered[$key] = $this->replaceMarkdown($value, $payload);
if (strpos($rendered[$key], '[') !== false || strpos($rendered[$key], '{') !== false) {
$rendered[$key] = json_decode($rendered[$key]);
}
}
}
return $rendered;
}
public function replaceMarkdown(string $param, array $argv)
{
return preg_replace_callback('/\{\%\s*(.*)\s*\%\}|\{\{(?!%)\s*((?:[^\s])*)\s*(?<!%)\}\}/i',
function ($field) use ($argv) {
$field = $field[2];
if (strpos($field, '.') !== false) {
$fields = explode('.', $field);
} else {
$fields = array($field);
}
$currentData = $argv; # we should take care for magic before foreach
foreach ($fields as $currentField) {
if (isset($currentData[$currentField])) {
$currentData = $currentData[$currentField];
} else {
return $field . '-not-found';
}
}
if (is_array($currentData)) {
$currentData = json_encode($currentData);
}
return (string)$currentData;
}, $param);
}