如何在 Laravel 中创建自己的 PHP 辅助函数

file

Laravel 提供了很多优秀的 辅助函数 来处理数组、文件路径、字符串和路由,还有最受欢迎的 dd() 函数。

你还可以利用 Composer 的自动加载为你的 Laravel 应用和 PHP 程序包定义自己的辅助函数。

接下来让我们来看看如何创建可以自动由 Laravel 加载的辅助函数。

在 App 目录中创建一个 Helpers 文件

要在 Laravel 应用程序中引用辅助函数,你可以根据偏好决定辅助函数文件的位置,下面有几个建议的位置:

  • app/helpers.php
  • app/Http/helpers.php

这里更推荐保存在应用程序命名空间的根目录下 app/helpers.php

自动加载

要使用自定义的 PHP 辅助函数,首先要做的是,在运行时将它们加载到程序中。 事实上,在文件顶部看到下面这样的代码并不罕见:

require_once ROOT . '/helpers.php';

PHP 函数不能被自动加载,但是我们有比使用 requirerequire_once 更好的解决方案—— Composer。

你可以在 Laravel 的 composer.json 文件中看到 autoloadautoload-dev 这两个键:

"autoload": {
    "classmap": [
        "database/seeds",
        "database/factories"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},
"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
    }
},

如果你想添加一个辅助函数的文件, composer.json 中有一个 files 键(这是一个文件路径的数组),你可以在 autoload 中定义:

"autoload": {
    "files": [
        "app/helpers.php"
    ],
    "classmap": [
        "database/seeds",
        "database/factories"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},

添加了新的路径到 files 数组中之后,你需要执行以下命令:

composer dump-autoload

现在,在每个请求中,helpers.php 文件将被自动加载,因为 Laravel 需要在 public/index.php 中使用 Composer 的自动加载器:

require __DIR__.'/../vendor/autoload.php';

定义函数

在辅助函数类中定义函数是很简单的,但是有些事情要注意:所有的 Laravel 辅助函数文件都包含在一个检查中以避免函数定义冲突:

if (! function_exists('env')) {
    function env($key, $default = null) {
        // ...
    }
}

因为你可能会遇到你正在使用的函数定义,而你根本不知道哪一个是第一个定义的,这可能会变得棘手。

我更推荐在辅助函数文件中使用 function_exists 检查,但是如果在单个文件中定义辅助函数,那就不需要了。

如果跳过检查,你可能随时都会看到你的辅助函数与其他函数发生冲突,这可能对你重新考虑函数的命名来说很有用。

但在实践中,这种冲突不会像你想象的那样频繁发生,你只需要确保定义的函数不是过于通用即可。你也可以为你的函数名添加前缀,确保它们不会与其他依赖相冲突。

辅助函数示例

我喜欢定义一个多功能的路由函数来同时使用变形路径和 URL 辅助函数。例如,一张照片资源路由会暴露路由辅助函数,比如 new_photo_pathedit_photo_path 等。

当我在 Laravel 中使用资源路由时,我喜欢添加一些辅助函数能够在模板中定义路由更容易。在我的实现中,我喜欢有一个 URL 助手函数,我可以传递一个 Eloquent 模型并使用我定义的约定返回资源路由,例如:

create_route($model);
edit_route($model);
show_route($model);
destroy_route($model);

以下是在 app/helpers.php 文件中定义 show_route 的方法(其他类似):

if (! function_exists('show_route')) {
    function show_route($model, $resource = null)
    {
        $resource = $resource ?? plural_from_model($model);

        return route("{$resource}.show", $model);
    }
}

if (! function_exists('plural_from_model')) {
    function plural_from_model($model)
    {
        $plural = Str::plural(class_basename($model));

        return Str::kebab($plural);
    }
}

plural_from_model() 函数只是一些可重用的代码,辅助函数 route 是用来根据我喜欢的命名约定来预测路由资源名称——模型的 kebab-case 复数形式命名。

例如,以下是由模型派生出来的资源名称示例:

$model = new App\LineItem;
plural_from_model($model);
=> line-items

plural_from_model(new App\User);
=> users

使用这个约定,你可以在 routes/web.php 中这样定义资源路由:

Route::resource('line-items', 'LineItemsController');
Route::resource('users', 'UsersController');

然后在 Blade 模板中,执行以下操作:

<a href="{{ show_route($lineItem) }}">
    {{ $lineItem->name }}
</a>

这会产生如下的 HTML:

<a href="http://localhost/line-items/1">
    Line Item #1
</a>

你的 Composer 软件包也可以使用辅助文件添加任何辅助函数来让你的软件包可用于项目。

你只需要在包的 composer.json 文件中采用相同的方法,使用你的辅助函数文件的数组定义 files 键。

在这里你就必须得添加 function_exists() 来检查你的辅助函数,以便使用了你的代码的项目不会由于命名冲突而中断。

你应该选择适合你的包的函数名,如果你害怕你的函数名太泛化,可以考虑使用一个简短的前缀。

更多

查看 Composer 的 自动加载 文档,了解更多有关引用文件以及自动加载类的信息。

另一个建议是了解框架中所有的 Laravel 辅助函数,并通过阅读 Illuminate\Foundation helpersIlluminate\Support helpers 的源代码来了解它们的工作原理。

本文译自 Creating Your Own PHP Helpers in a Laravel Project

本文章首发在 Laravel China 社区

Stay Hungry, Stay Foolish.