覆盖 laravel 5 辅助函数

Posted

技术标签:

【中文标题】覆盖 laravel 5 辅助函数【英文标题】:Overwrite laravel 5 helper function 【发布时间】:2015-04-13 00:31:12 【问题描述】:

我经常使用response() 助手,我只是将数据和消息一起返回给用户。现在我还必须包含 http 状态代码,但我不想更改每个响应(无论如何这可能很糟糕)。

所以我试图通过在app/Http/helpers.php 中创建我自己的helpers.php 来覆盖response() 辅助函数。

当我将它添加到我的作曲家文件时,它会首先从框架中自动加载当前的 helpers.php,当我在 bootstrap/global.php 中的 autload 包含之前添加它时,我将无法使用 app() 和其他 Laravel功能。

我该如何解决这个问题?我只想在响应数组中包含状态代码。

【问题讨论】:

【参考方案1】:

在 Laravel 5.5+ 中,laravel 没有 bootstrap/autoload.php 你必须使用像https://github.com/funkjedi/composer-include-files这样的包

怎么做:

第一次运行命令

composer require funkjedi/composer-include-files

然后在 composer.json 中添加你的辅助函数文件路径


    "extra": 
        "include_files": [
            "/path/to/file/you/want/to/include",
            "/path/to/another/file/you/want/to/include"
        ]
    ,

那就做吧

composer dump-autoload

【讨论】:

查看相关的laravel想法问题:github.com/laravel/ideas/issues/1569【参考方案2】:

我只需要这样做才能覆盖now() 帮助器,这样我就可以控制运行测试时的明显时间。我按照 regular advice 创建 app/Http/helpers.php 然后将其添加到 bootstrap/autoload.php 如下:

require __DIR__.'/../app/Http/helpers.php'; // added
require __DIR__.'/../vendor/autoload.php';

这通常是有效的,因为正如 Marty 所说,只有在没有具有该名称的现有函数时才定义所有帮助程序。所以上面两行加载了你的自定义助手,然后执行所有供应商自动加载,包括 Laravel 的助手,你已经定义的函数优先。

但不幸的是,autoload.php 在使用 Behat 进行测试时似乎没有被使用,这正是我正在使用的。所以我需要一个替代解决方案。长话短说,确保在供应商文件之前自动加载文件的唯一简单方法是使用 https://github.com/funkjedi/composer-include-files 包。引用自述文件:

在过去,只需修改 bootstrap/autoload.php 以包含帮助程序就足够了。然而,新版本的 PHPUnit 在执行 PHPUnit 引导文件之前包含 Composer Autoloader。因此,这种覆盖帮助程序的方法不再可行,因为在包含引导文件时会触发致命错误。

所以我使用composer require funkjedi/composer-include-files 安装了这个包,然后将它添加到composer.json

"extra": 
    "include_files": [
        "app/Http/helpers.php"
    ]
,

完成后,运行composer dump-autoload 以重新生成自动加载文件。现在,覆盖在常规应用操作期间和运行测试时都有效!

【讨论】:

这是我能够强制 Lumen 中的 url() 助手生成 https URL 的唯一可能方式。【参考方案3】:

使用此逻辑编写的所有 Laravel 辅助函数

if ( ! function_exists('response'))

    function response($content = '', $status = 200, array $headers = array())
    
         // function body
    

Laravel 首先检查这个函数是否存在,如果存在,Laravel 将不再定义这个函数(否则会抛出致命错误)。 因此,如果您要在自动加载器包含 vendor/laravel/framework/src/Illuminate/Foundation/helpers.php 文件之前定义您的函数, 您可以定义您的自定义响应函数。

不幸的是,没有办法说作曲家首先加载你的 autoload.files 部分,然后是 laravel autoload.files。但是你可以做一些小技巧......

打开bootstrap/autoload.php 文件并在自动加载器之前包含您的文件

// file with your custom helper functions
require __DIR__.'/../app/app/Http/helpers.php'; 
require __DIR__.'/../vendor/autoload.php';

【讨论】:

您可以在函数中使用应用实例,因为您稍后会在应用实例存在时调用函数。【参考方案4】:

我不打算直接回答您的问题,因为我不知道是否有解决方案(无需更改 Laravel helpers.php 或重命名您的函数)

但是,对于这个常见的用例,框架有一个解决方案。 Response Macros

您可以定义一个宏(这是在服务提供者中完成的)

Response::macro('foo', function($value)
    // do some stuff
    return Response::make($value);
);

你可以这样使用它:

return response()->foo('bar');

【讨论】:

如果您需要更多帮助来编写实际的宏,我需要知道它到底应该做什么...... 嗯,我知道可以这样做,但我想知道是否有人有解决方案,而不是仅仅更改每种方法或创建另一种方法。 Laravel 对于这类东西应该是灵活的.. 无论哪种方式,这都是解决问题的好方法。像这样的助手对于大多数使用 Laravel 的人来说是无关紧要的。响应门面和具体的响应类比助手要好得多。

以上是关于覆盖 laravel 5 辅助函数的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5:app() 辅助函数

辅助函数未加载 laravel 5 - 调用未定义函数

Laravel 5.4 和 WordPress 4.7 的辅助函数 __() 冲突

Laravel 辅助函数 base_path() 失败

我应该在 Laravel 5.7 中更好地使用 session() 或 collect() 辅助函数吗?

Laravel 常用辅助函数