对于关联数组,eval()可能是最简单的。但它的使用被认为是危险的,因为它就像你打开一个洞,一根用于执行代码的针。在同一时间eval() 在运行时执行,好吧将要执行的代码存储在数据库中(缓存[这意味着它缓存编译的字节代码])。这是额外的开销,所以性能会受到打击。这是一篇关于该主题的好论文[没有阅读或深入细节])https://link.springer.com/chapter/10.1007%2F978-981-10-3935-5_12 https://link.springer.com/chapter/10.1007%2F978-981-10-3935-5_12.
好吧,我可能已经找到你了!,服务器服务性能没有任何性能差异,因为视图被缓存,并且仅在您更改视图时才生成。指令被转换为 php 代码,并在另一个进程中被缓存。 (您可以在中找到生成的视图存储/框架/视图)
So for
Blade::directive('custom', function ($expression) {
eval("\$myarray = [$expression];");
// do something with $myarray
return "<?php echo ..";
});
没关系。对于 eval() 和性能没有什么可谈的(它已完成并缓存,生成的 php 代码是会一遍又一遍地运行的代码(只需确保指令返回的 php 代码不包含 eval() ,除非有原因)。直接使用 eval() (将一遍又一遍地用于不同的请求)会影响性能。
(我想谈谈 eval(),我认为这些都是有用的信息)
事实上,我们可以从 ["something" => "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_解码。 (我刚刚想到的)
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);
});
}
or
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 删除诸如 () ...等之类的东西[简而言之,我们锻炼自己的解析。正则表达式可能会有所帮助。并取决于我们想要实现的目标。
以上所有都是解析条目并将它们分成用于生成模板的变量的方法。制作退货声明也是如此。
如果您想要的只是让您的指令采用包含视图范围中的变量的数组,该怎么办:
like in @section('', ["var" => $varValue])
这里特别是我们使用多参数解析,然后我们分别恢复 ["" => ..] 表达式(这不是重点)。
关键是当您想要传递要在代码中使用的数组(视图范围)时。您只需按原样使用它即可。 (这可能会令人困惑)。
ex:
Blade::directive("do", function ($expr) {
return "<?php someFunctionFromMyGlobalOrViewScopThatTakeArrayAsParameter($expr); ?>
});
这将评估为
<?php someFunctionFromMyGlobalOrViewScopThatTakeArrayAsParameter(["name" => $user->name, .......]); ?>
所以一切都会好起来的。我举了一个例子,我们使用一个函数,你可以放置所有的逻辑。指令只是一种以更美观的方式编写视图的方法。它还允许预览处理和生成。安静真好。