将多个参数传递给刀片指令

Cai*_*aki 8 php laravel blade laravel-blade laravel-5.3

我正在尝试创建一个刀片指令,以突出显示将从我的搜索查询返回的一些单词.

这是我的刀片指令:

class AppServiceProvider extends ServiceProvider

{
    public function boot()
    {
        Blade::directive('highlight', function($expression, $string){

            $expressionValues = preg_split('/\s+/', $expression);

            foreach ($expressionValues as $value) {
                $string = str_replace($value, "<b>".$value."</b>", $string);
            }

            return "<?php echo {$string}; ?>";
        });
    }

    public function register()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我用这样的方式调用刀片:

@highlight('ho', 'house')
Run Code Online (Sandbox Code Playgroud)

但是,这个错误跟随着我:

Missing argument 2 for App\Providers\AppServiceProvider::App\Providers\{closure}()
Run Code Online (Sandbox Code Playgroud)

怎么解决?

小智 8

Blade::directive('custom', function ($expression) {
    eval("\$params = [$expression];");
    list($param1, $param2, $param3) = $params;

    // Great coding stuff here
});
Run Code Online (Sandbox Code Playgroud)

在刀片模板中:

@custom('param1', 'param2', 'param3')
Run Code Online (Sandbox Code Playgroud)


Eve*_*ett 7

我一直在寻找这个确切的解决方案,然后在阅读完所有内容后决定尝试不同的方法,最终得出了你和我都在寻找的解决方案。

不需要 JSON 解决方法、分解、关联数组等...除非您希望以后使用该功能来实现更复杂的功能。

因为 Blade 只是写出稍后解释的 PHP 代码,所以您在 @highlight 指令中放入的内容都是字符串格式的确切 PHP 代码,稍后将被解释。

该怎么办:

创建并注册一个可以在整个应用程序中调用的辅助函数。然后在 Blade 指令中使用辅助函数。

助手定义:

if(!function_exists('highlight')){

    function highlight($expression, $string){
        $expressionValues = preg_split('/\s+/', $expression);

        foreach ($expressionValues as $value) {
            $string = str_replace($value, "<b>".$value."</b>", $string);
        }

        return $string;
    }
}
Run Code Online (Sandbox Code Playgroud)

刀片指令:

Blade::directive('highlight', function ($passedDirectiveString){
        return "<?php echo highlight($passedDirectiveString);?>";
    });
Run Code Online (Sandbox Code Playgroud)

用法(示例):

<div>
    @highlight('ho', 'house')
</div>
Run Code Online (Sandbox Code Playgroud)

理解:

这相当于写出:

<div>
    {! highlight('ho', 'house') !}
</div>
Run Code Online (Sandbox Code Playgroud)


Moh*_*lal 5

对于关联数组,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 ..";
});
Run Code Online (Sandbox Code Playgroud)

没关系 关于eval()和性能没有什么可谈的(已经完成并缓存了,生成的php代码将一遍又一遍地运行(只要确保指令返回的php代码不包含eval(), ,除非有原因)直接使用eval()(将反复用于不同的请求)会影响性能(我想谈谈eval(),我认为这些都是有用的信息)

因为我们可以解析数组形式[“ sometin” =>“我应该被刺”,“” =>“”,...]。

eval("\$array = $expression;");
// then we can do what we want with $array 
Run Code Online (Sandbox Code Playgroud)

但是我们不能传递变量。例如: @directive(["s" => $var]) 如果我们使用eval,则$ var将在指令函数范围内未定义。(别忘了该指令只是一种漂亮地生成tempalte的方法,并将丑陋的(而不是真正丑陋的)php代码转换成这样的指令。实际上,相反,我们正在将漂亮的指令转换为php代码,最后执行。您在这里要做的就是生成,构建,编写将构成最终php页面或文件的表达式。)

您可以做的是以这种方式传递变量[“ s” =>“ $ var”],这样它将通过eval传递。然后在您的return语句中,使用它作为示例:

return "<?php echo ".$array['s'].";?>";
Run Code Online (Sandbox Code Playgroud)

当模板生成的时候<?php echo $var;?>;

请记住,如果您决定使用eval,请不要在返回的字符串中使用它!也许您想在某些情况下。

另一种解决方案

(这很容易)连同建议的解析解决方案一起使用,是使用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()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我需要这样做的一个示例:目标是使它自动化

@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 ...
Run Code Online (Sandbox Code Playgroud)

所以我写了这个指令:

 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;
        });
    }
Run Code Online (Sandbox Code Playgroud)

我们这样使用它:

@varSet({
    "logo": "logo",
    "width": 78,
    "height": 22
})// hi my cool directive. that's slick.
Run Code Online (Sandbox Code Playgroud)

为什么这种形式有效?它像这样作为字符串模板传递

"""
{\n
    "logo": "logo",\n
    "width": 78,\n
    "height": 22\n
}
"""
Run Code Online (Sandbox Code Playgroud)

对于在模板变量中使用,请将其作为字符串传递,例如“ $ var”,与我们对eval所做的相同。

对于从[“” =>“”进行解析,..]格式可能是eval()是最佳选择。请记住,这是在模板生成时完成的,该模板稍后会缓存,并且不会更新,直到我们再次进行更改。并记住不要在return中使用eval();指令说明。(仅在您的应用程序需要时)

仅用于多个参数,而不用于数组: 像这样的函数将完成此工作:

 public static function parseMultipleArgs($expression)
{
    return collect(explode(',', $expression))->map(function ($item) {
        return trim($item);
    });
}
Run Code Online (Sandbox Code Playgroud)

要么

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;
    }
Run Code Online (Sandbox Code Playgroud)

然后您可以根据需要对其进行调整,使用str_replace删除()... etc之类的内容[总之,我们进行自己的解析。正则表达式可能会有所帮助。并取决于我们要实现的目标。

以上所有方法都是解析条目并将其分成用于生成模板的变量的方法。因此,使您的退货声明。

如果您只想让自己的指令与视图范围的变量进行比较,请执行以下操作:

@section('', ["var" => $varValue])

好吧,这里我们特别使用多参数解析,然后分别恢复[“” => ..]表达式(这里不是重点)。

关键是当您想要传递要在代码中使用的数组(查看范围)时。您可以按原样使用它。(这可能会造成混淆)。

例如:

Blade::directive("do", function ($expr) {
    return "<?php someFunctionFromMyGlobalOrViewScopThatTakeArrayAsParameter($expr); ?>
});
Run Code Online (Sandbox Code Playgroud)

这将评估为

<?php someFunctionFromMyGlobalOrViewScopThatTakeArrayAsParameter(["name" => $user->name, .......]); ?>
Run Code Online (Sandbox Code Playgroud)

因此,一切都会正常进行。我举了一个例子,我们使用一个函数,可以放所有逻辑。指令只是一种以更优美的方式编写视图的方式。它还允许预览处理和生成。安静点


San*_*rez 1

我认为你只能传递一个参数。它并不漂亮,但您可以将参数作为数组传递,如下所示:

@highlight(['expression' => 'ho', 'string' => 'house'])
Run Code Online (Sandbox Code Playgroud)

所以你的指令可能是

class AppServiceProvider extends ServiceProvider

{
    public function boot()
    {
        Blade::directive('highlight', function($array){

            $expressionValues = preg_split('/\s+/', $array['expression']);

            foreach ($expressionValues as $value) {
                $array['string'] = str_replace($value, "<b>".$value."</b>", $array['string']);
            }

            return "<?php echo {$array['string']}; ?>";
        });
    }

    public function register()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里找到它:https ://laracasts.com/discuss/channels/laravel/how-to-do-this-blade-directive

  • 错误:“非法字符串偏移‘表达式’” (2认同)