如何在Blade模板中使用类?

11

我创建了一个名为Helper的类,其路径为App\Http\Helpers\

<?php

namespace App\Http\Helpers;

class Helper 
{
    public static function applyClass($user) {
        return "new";
    }

}

然后我在 app.php 文件的 aliases 部分进行了注册:

'Helper' =>   App\Http\Helpers\Helper::class

当我尝试从Blade中调用静态方法时:

<tr class="{{ \Helper::applyClass($user) }}">
<tr class="{{ Helper::applyClass($user) }}">

我遇到了一个错误:

Class 'Helper' not found

1
try composer dump-autoload - dparoli
1
请查看 Blade 服务注入 https://laravel.com/docs/master/blade#service-injection - Joaquin Javi
1
调用静态方法时不需要进行注入。 - Namoshek
我尝试了:composer dump-autoload,但没有结果。 - user3573738
抱歉,让我花了一点时间把所有东西写下来。 :) - Namoshek
@user3573738,您不需要添加任何别名。请看我的答案。它已在我的机器上测试过并且可以运行。 - Udo E.
3个回答

27
这不是门面模式的工作方式。需要创建一个自定义门面来扩展`Illuminate\Support\Facades\Facade`,这基本上只需要自定义门面实现`protected static function getFacadeAccessor()`方法。此方法应返回门面所需解析的名称(或类或接口)。
门面允许您以静态方式调用实例方法(即非静态方法)。这是因为门面知道如何将对静态方法的调用重定向到门面背后的实例。这是通过实现`__callStatic($method, $args)`完成的,该方法简单地将静态方法调用重定向到由`getFacadeAccessor()`返回名称的实现。
假设您在服务容器中注册了名为“helper”的服务。您可以使用`app('helper')->getColor()`或`app()->make('helper')->getColor()`执行其上的`getColor()`方法。
使用名为`Helper`的门面并从`getFacadeAccessor()`方法中返回它的字符串形式来解析您的`helper`,然后可以使用`Helper::getColor()`执行相同操作。
对于您的情况,现在有几个选项: 1) 使用具有静态方法的类: 与您已经完成的类似,您可以定义具有静态方法的类。然后,通过使用完全限定的类名(FQCN)在您的 blade 视图中静态调用这些方法:
// app/Helpers/Helper.php
class Helper
{
    public static function getColor(): string
    {
        return 'blue';
    }
}

// resources/views/some/page.blade.php
<div style="color:{{ \App\Helpers\Helper::getColor() }}"> ... </div>

2) 使用非静态类与门面模式:

您可以使用与上述相似的非静态方法类,并为其添加门面模式:

// app/Helpers/Helper.php
class Helper
{
    public function getColor(): string
    {
        return 'blue';
    }
}

// app/Facades/Helper.php
class Helper extends \Illuminate\Support\Facades\Facade
{
    protected static function getFacadeAccessor()
    {
        return \App\Helpers\Helper::class;
    }
}

// config/app.php -> 'aliases' array
[
    // ... other facades ...
    'Helper' => \App\Facades\Helper::class,
]

// resources/views/some/page.blade.php
<div style="color:{{ \Helper::getColor() }}"> ... </div>

3)使用全局非类帮助文件:

您还可以定义一个基本的PHP文件,其中包含一些辅助函数,这些函数被全局注册。这些函数不是类方法,因此不需要使用类前缀来调用:

// app/Helpers/color_utils.php
if (!function_exists('get_color')) {
    function get_color()
    {
        return 'blue';
    }
}

// app/Providers/HelperServiceProvider.php
class HelperServiceProvider extends \Illuminate\Support\ServiceProvider
{
    public function register(): void
    {
        $filenames = glob(app_path('Helpers/*.php'));

        if ($filenames !== false && is_iterable($filenames)) {
            foreach ($filenames as $filename) {
                require_once $filename;
            }
        }
    }
}

// config/app.php -> 'providers' array
[
    // ... other providers ...
    \App\Providers\HelperServiceProvider::class,
]

// resources/views/some/page.blade.php
<div style="color:{{ get_color() }}"> ... </div>

4)使用类和服务注入:

还有一个不错的选择是使用服务容器将服务注入到 Blade 模板中。 Laravel 提供了一个名为 @inject($var, $fqdn) 的 Blade 指令来实现它。

// app/Helpers/Helper.php
class Helper
{
    public static function getColor(): string
    {
        return 'blue';
    }
}

// resources/views/some/page.blade.php
@inject('helper', \App\Helpers\Helper::class)

<div style="color:{{ $helper->getColor() }}"> ... </div>

我希望代码本身说明问题。文件的命名空间是有意省略的,当然你应该根据目录使用命名空间(符合 PSR-4)。

如果您不需要任何依赖项,并且基本上只需要静态访问某些内容,则我个人更喜欢全局助手函数(选项3)。


2
这就是答案,解释得很好,应该毫不犹豫地接受。我想要一个双倍赞。 - dparoli
是的,“这不是门面的工作方式”,但 OP 并没有试图创建一个门面,只是一个类别名。他们的方法很好用,可能他们遇到了缓存问题或其他问题。使用别名条目与使用 use 语句设置类别名是相同的。大多数内置别名是门面只是巧合。例如,请参见 Illuminate\Support\Str - miken32
1
感谢详细的解释。关于选项2,需要注意的是,在Laravel 8中,您需要将方法更改为:protected static function getFacadeAccessor() { return \App\Helpers\Helper::class; } - DAMIEN JIANG
@DAMIENJIANG 很好的发现。事实上,一直都是这样,我的回答是错误的。立即进行了修正,谢谢。 - Namoshek
更好的解释就像 Laravel 文档一样!感谢这种方法! - lortschi

7
您可以按照以下步骤简单地实现这一点。 第一步 在您想要的路径中创建您的类文件(例如: app/Helpers/Helper.php ),并定义该类。
<?php

class Helper 
{
    public static function applyClass($user) {
        return "call from helper to " . $user;
    }

}

第二步

通过将文件添加到autoload键的条目中,修改composer.json文件

"autoload": {
    "prs-4": {
        "App\\": "app/"
    },
    "files": [
        "app/Helpers/Helper.php"
    ]
}

请注意,您并没有改变任何内容,只需包含以下条目:"files": ["app/Helpers/Helper.php"]。保存文件。

步骤3

从根目录运行以下命令:

composer dump-autoload

它刷新了自动加载缓存。

第4步

现在您可以在任何地方使用您的类,包括blade模板。

<tr class="{{ Helper::applyClass("user") }}">

这样,您也可以创建全局函数。


0
虽然其它解决方案(如注入指令)都工作得很好,但你觉得从一个 Blade 页面访问服务是一个好的实践吗?我认为你需要这样做是因为控制器或服务没有向 Blade 提供所需的信息。因此,回到控制器并发送 Blade 页面所需的信息可能是一个不错的主意。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接