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

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

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

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

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

【问题讨论】:

    标签: php laravel laravel-5


    【解决方案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
    

    【讨论】:

    【解决方案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 的人来说是无关紧要的。响应门面和具体的响应类比助手要好得多。
    猜你喜欢
    • 2016-01-06
    • 2012-08-12
    • 2021-11-03
    • 2022-08-04
    • 2015-06-24
    • 2018-05-20
    • 1970-01-01
    • 2015-12-01
    • 2014-04-19
    相关资源
    最近更新 更多