对于关联数组,eval() 可能是最简单的。但是它的使用被宣传为危险的,因为它就像你打开一个洞,一根用于执行代码的针。同时eval()在运行时执行,它将要执行的代码存储在数据库中(缓存[嗯,它意味着它缓存编译的字节码])。这是额外的开销,因此性能会受到影响。这是一篇关于该主题的好论文[没有阅读或了解细节])https://link.springer.com/chapter/10.1007%2F978-981-10-3935-5_12。
好吧,我可能已经明白了!,在服务器服务性能方面没有性能差异,因为视图是缓存的,并且只有在您更改它们时才会生成。指令被翻译成 php 代码并在另一个进程中被缓存。 (您可以在 storage/framework/views 中找到生成的视图)
所以对于
Blade::directive('custom', function ($expression) {
eval("\$myarray = [$expression];");
// do something with $myarray
return "<?php echo ..";
});
没关系。 eval() 和性能没有什么可谈的(它已经完成并缓存了,生成的 php 代码将一遍又一遍地运行(只需确保指令返回的 php 代码不包含 eval() , 除非有原因). 直接使用 eval() (将反复用于不同的请求)会影响性能。
(我想谈谈 eval(),我认为这些是有用的信息)
我们可以解析数组形式 ["sometin" => "i should be sting", "" => "", ...]。
eval("\$array = $expression;");
// then we can do what we want with $array
但是我们不能传递变量。例如:@directive(["s" => $var])
如果我们使用 eval,$var 将在指令函数范围内未定义。 (不要忘记指令只是一种漂亮地生成模板的方法,并将丑陋(不是真的丑陋)的 php 代码变成这样的指令。事实上它是相反的,我们正在将美丽的指令变成将是的 php 代码最后执行。而您在这里所做的只是生成、构建、编写将形成最终 php 页面或文件的表达式。)
您可以做的是以这种方式传递变量
["s" => "$var"] ,所以它将通过 eval。然后在你的 return 语句中,使用它的例子:
return "<?php echo ".$array['s'].";?>";
当模板生成时,这将是<?php echo $var;?>;
记住,如果你决定使用 eval,千万不要在返回的字符串中使用它!或者在某些情况下你可能想要。
另一种解决方案
(easy)与建议的解析解决方案一样,是使用 json 格式 将数据传递给您的指令,并且只需使用 json_decode。 (它刚刚来到我身边)
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Blade::directive('highlight', function($json_expression){
$myArray = json_decode($json_expression)
// do something with the array
});
}
public function register()
{
}
}
这是一个我需要这样做的例子:
我们的目标是自动化这个
@php
$logo = !empty($logo) ? $logo : 'logo';
$width = !empty($width) ? $width : 'logo';
//... // wait i will not always keep doing that ! h h
@endphp // imaging we do that for all different number of view components ...
所以我写了这个指令:
public function boot()
{
Blade::directive('varSet', function ($expr) {
$array = json_decode($expr, true);
$p = '<?php ';
foreach ($array as $key => $val) {
if (is_string($val)) {
$p .= "\$$key = isset(\$$key) && !empty(\$$key) ? \$$key : '$val'; ";
} else {
$p .= "\$$key = isset(\$$key) && !empty(\$$key) ? \$$key : $val; ";
}
}
$p .= '?>';
return $p;
});
}
我们这样使用它:
@varSet({
"logo": "logo",
"width": 78,
"height": 22
})// hi my cool directive. that's slick.
为什么这个表格有效?它像这样作为字符串模板传递
"""
{\n
"logo": "logo",\n
"width": 78,\n
"height": 22\n
}
"""
对于在模板变量中使用,将它们作为“$var”之类的字符串传递,就像我们对 eval 所做的一样。
对于从 ["" => "", ..] 格式进行解析,可能 eval() 是最好的选择。请记住,这是在模板生成时完成的,这些模板稍后会被缓存,并且不会更新,直到我们再次进行更改。记住不要在 return 中使用 eval() ;指示性指令。 (仅当您的应用程序需要时)
仅用于多个参数,因此不是数组:
像这样的函数可以完成这项工作:
public static function parseMultipleArgs($expression)
{
return collect(explode(',', $expression))->map(function ($item) {
return trim($item);
});
}
或
public static function parseMultipleArgs($expression)
{
$ar = explode(',', $expression);
$l = len($ar);
if($l == 1) return $ar[0];
for($i = 0; $i < $l; $i++){$ar[$i] = trim($ar[$i])}
return $ar;
}
您可以随意调整它们,使用 str_replace 删除 () ...等内容 [简而言之,我们锻炼自己的解析。正则表达式可能会有所帮助。并且取决于我们想要实现的目标。
以上所有方法都是解析条目并将它们分成用于生成模板的变量的方法。因此,您的退货声明也是如此。
如果您只想让您的指令从视图范围中获取一个包含变量的数组:
点赞@section('', ["var" => $varValue])
这里特别是我们使用多参数解析,然后我们分别恢复 ["" => ..] 表达式(这不是重点)。
关键是当您想要传递要在代码中使用的数组时(视图范围)。您只需按原样使用它。 (这可能会令人困惑)。
例如:
Blade::directive("do", function ($expr) {
return "<?php someFunctionFromMyGlobalOrViewScopThatTakeArrayAsParameter($expr); ?>
});
这将评估为
<?php someFunctionFromMyGlobalOrViewScopThatTakeArrayAsParameter(["name" => $user->name, .......]); ?>
所以一切都会好起来的。我举了一个例子,我们使用一个函数,你可以把所有的逻辑。指令只是以更漂亮的方式编写视图的一种方式。它还允许预览处理和生成。安静好听。