php Laravel 5 中自定义助手的最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28290332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 23:47:23  来源:igfitidea点击:

Best Practices for Custom Helpers in Laravel 5

phplaravellaravel-5laravel-helper

提问by Calebe Oliveira

I would like to create helper functions to avoid repeating code between views in Laravel 5:

我想创建辅助函数以避免在 Laravel 5 中的视图之间重复代码:

view.blade.php

视图.blade.php

<p>Foo Formated text: {{ fooFormatText($text) }}</p>

They're basically text formatting functions. Where and how can I create a file with these functions?

它们基本上是文本格式功能。我在哪里以及如何创建具有这些功能的文件?

回答by Joseph Silber

Create a helpers.phpfile in your app folder and load it up with composer:

helpers.php在您的应用程序文件夹中创建一个文件并使用 Composer 加载它:

"autoload": {
    "classmap": [
        ...
    ],
    "psr-4": {
        "App\": "app/"
    },
    "files": [
        "app/helpers.php" // <---- ADD THIS
    ]
},

After adding that to your composer.jsonfile, run the following command:

将其添加到您的composer.json文件后,运行以下命令:

composer dump-autoload


If you don't like keeping your helpers.phpfile in your appdirectory (because it's not a PSR-4 namespaced class file), you can do what the laravel.comwebsite does: store the helpers.phpin the bootstrap directory. Remember to set it in your composer.jsonfile:

如果您不喜欢将helpers.php文件保存在您的app目录中(因为它不是 PSR-4 命名空间类文件),您可以执行laravel.com网站所做的操作:将文件存储helpers.php在 bootstrap 目录中。请记住在您的composer.json文件中设置它:

"files": [
    "bootstrap/helpers.php"
]

回答by heisian

Custom Classes in Laravel 5, the Easy Way

Laravel 5 中的自定义类,简单的方法

This answer is applicable to generalcustom classes within Laravel. For a more Blade-specific answer, see Custom Blade Directives in Laravel 5.

此答案适用于 Laravel 中的一般自定义类。有关更多特定于 Blade 的答案,请参阅Laravel 5 中的自定义 Blade 指令

Step 1:Create your Helpers (or other custom class) file and give it a matching namespace. Write your class and method:

第 1 步:创建您的 Helpers(或其他自定义类)文件并为其提供匹配的命名空间。编写您的类和方法:

<?php // Code within app\Helpers\Helper.php

namespace App\Helpers;

class Helper
{
    public static function shout(string $string)
    {
        return strtoupper($string);
    }
}

Step 2:Create an alias:

第 2 步:创建别名:

<?php // Code within config/app.php

    'aliases' => [
     ...
        'Helper' => App\Helpers\Helper::class,
     ...

Step 3:Run composer dump-autoloadin the project root

第三步:composer dump-autoload在项目根目录下运行

Step 4:Use it in your Blade template:

第 4 步:在您的 Blade 模板中使用它:

<!-- Code within resources/views/template.blade.php -->

{!! Helper::shout('this is how to use autoloading correctly!!') !!}

Extra Credit:Use this class anywhere in your Laravel app:

额外学分:在你的 Laravel 应用程序中的任何地方使用这个类:

<?php // Code within app/Http/Controllers/SomeController.php

namespace App\Http\Controllers;

use Helper;

class SomeController extends Controller
{

    public function __construct()
    {
        Helper::shout('now i\'m using my helper class in a controller!!');
    }
    ...


Source: http://www.php-fig.org/psr/psr-4/

来源:http: //www.php-fig.org/psr/psr-4/

Why it works: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/ClassLoader.php

为什么它有效:https: //github.com/laravel/framework/blob/master/src/Illuminate/Support/ClassLoader.php

Where autoloading originates from: http://php.net/manual/en/language.oop5.autoload.php

自动加载的来源:http: //php.net/manual/en/language.oop5.autoload.php

回答by Andrew Brown

my initial thought was the composer autoload as well, but it didn't feel very Laravel 5ish to me. L5 makes heavy use of Service Providers, they are what bootstraps your application.

我最初的想法是 Composer 自动加载也是如此,但我觉得它不是 Laravel 5ish。L5 大量使用服务提供者,它们是引导您的应用程序的工具。

To start off I created a folder in my appdirectory called Helpers. Then within the Helpersfolder I added files for functions I wanted to add. Having a folder with multiple files allows us to avoid one big file that gets too long and unmanageable.

首先,我在我的app目录中创建了一个名为Helpers. 然后在Helpers文件夹中,我为我想要添加的功能添加了文件。拥有一个包含多个文件的文件夹可以让我们避免一个太长且无法管理的大文件。

Next I created a HelperServiceProvider.phpby running the artisan command:

接下来我HelperServiceProvider.php通过运行 artisan 命令创建了一个:

artisan make:provider HelperServiceProvider

Within the registermethod I added this snippet

register方法中我添加了这个片段

public function register()
{
    foreach (glob(app_path().'/Helpers/*.php') as $filename){
        require_once($filename);
    }
}

lastly register the service provider in your config/app.phpin the providers array

最后在您config/app.php的 providers 数组中注册服务提供者

'providers' => [
    'App\Providers\HelperServiceProvider',
]

now any file in your Helpersdirectory is loaded, and ready for use.

现在您Helpers目录中的任何文件都已加载,可以使用了。

UPDATE 2016-02-22

更新 2016-02-22

There are a lot of good options here, but if my answer works for you, I went ahead and made a package for including helpers this way. You can either use the package for inspiration or feel free to download it with Composer as well. It has some built in helpers that I use often (but which are all inactive by default) and allows you to make your own custom helpers with a simple Artisan generator. It also addresses the suggestion one responder had of using a mapper and allows you to explicitly define the custom helpers to load, or by default, automatically load all PHP files in your helper directory. Feedback and PRs are much appreciated!

这里有很多不错的选择,但是如果我的回答对您有用,我会继续制作一个包,以这种方式包含助手。您可以使用该包获取灵感,也可以随意使用 Composer 下载它。它有一些我经常使用的内置助手(但默认情况下都是不活动的),并允许您使用简单的 Artisan 生成器创建自己的自定义助手。它还解决了响应者使用映射器的建议,并允许您明确定义要加载的自定义帮助程序,或者默认情况下自动加载您的帮助程序目录中的所有 PHP 文件。非常感谢反馈和 PR!

composer require browner12/helpers

Github: browner12/helpers

Github: browner12/helpers

回答by itsazzad

This is what is suggested by JeffreyWayin this Laracasts Discussion.

这就是被认为JeffreyWay在这个Laracasts讨论

  1. Within your app/Httpdirectory, create a helpers.phpfile and add your functions.
  2. Within composer.json, in the autoloadblock, add "files": ["app/Http/helpers.php"].
  3. Run composer dump-autoload.
  1. 在您的app/Http目录中,创建一个helpers.php文件并添加您的函数。
  2. 在 中composer.json,在autoload块中,添加"files": ["app/Http/helpers.php"]
  3. 运行composer dump-autoload

回答by dKen

Having sifted through a variety of answers on SO and Google, I still couldn't find an optimal approach. Most answers suggest we leave the application and rely on 3rd party tool Composer to do the job, but I'm not convinced coupling to a tool just to include a file is wise.

在 SO 和 Google 上筛选了各种答案后,我仍然找不到最佳方法。大多数答案建议我们离开应用程序并依靠 3rd 方工具 Composer 来完成这项工作,但我不相信仅仅为了包含文件而与工具耦合是明智的。

Andrew Brown's answercame the closest to how I think it should be approached, but (at least in 5.1), the service provider step is unnecessary. Heisian's answerhighlights the use of PSR-4which brings us one step closer. Here's my final implementation for helpers in views:

Andrew Brown 的回答最接近我认为应该采取的方式,但是(至少在 5.1 中),服务提供者步骤是不必要的。Heisian 的回答强调了使用PSR-4which 使我们更近了一步。这是我对视图中助手的最终实现:

First, create a helper file anywhere in your apps directory, with a namespace:

首先,在您的应用程序目录中的任何位置创建一个帮助文件,并使用命名空间:

namespace App\Helpers;

class BobFinder
{
    static function bob()
    {
        return '<strong>Bob?! Is that you?!</strong>';
    }
}

Next, alias your class in config\app.php, in the aliasesarray:

接下来,config\app.phpaliases数组中为您的类添加别名:

'aliases' => [
    // Other aliases
    'BobFinder' => App\Helpers\BobFinder::class
]

And that should be all you need to do. PSR-4and the alias should expose the helper to your views, so in your view, if you type:

这应该就是您需要做的全部。PSR-4并且别名应该向您的视图公开帮助程序,因此在您的视图中,如果您键入:

{!! BobFinder::bob() !!}

It should output:

它应该输出:

<strong>Bob?! Is that you?!</strong>

回答by heisian

Custom Blade Directives in Laravel 5

Laravel 5 中的自定义刀片指令

Yes, there is anotherway to do this!

是的,还有另一种方法可以做到这一点!

Step 1:Register a custom Blade directive:

第 1 步:注册自定义 Blade 指令:

<?php // code in app/Providers/AppServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

use Blade; // <-- This is important! Without it you'll get an exception.

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
     public function boot()
     {
         // Make a custom blade directive:
         Blade::directive('shout', function ($string) {
             return trim(strtoupper($string), '(\'\')');
         });

         // And another one for good measure:
         Blade::directive('customLink', function () {
             return '<a href="#">Custom Link</a>';
         });
     }
    ...

Step 2:Use your custom Blade directive:

第 2 步:使用您的自定义 Blade 指令:

<!-- // code in resources/views/view.blade.php -->

@shout('this is my custom blade directive!!')
<br />
@customLink

Outputs:

输出:

THIS IS MY CUSTOM BLADE DIRECTIVE!!
Custom Link

这是我的自定义刀片指令!!
自定义链接



Source: https://laravel.com/docs/5.1/blade#extending-blade

来源:https: //laravel.com/docs/5.1/blade#extending-blade

Additional Reading: https://mattstauffer.co/blog/custom-conditionals-with-laravels-blade-directives

补充阅读:https: //mattstauffer.co/blog/custom-conditionals-with-laravels-blade-directives



If you want to learn how to best make custom classes that you can use anywhere, see Custom Classes in Laravel 5, the Easy Way

如果你想学习如何最好地制作可以在任何地方使用的自定义类,请参阅Laravel 5 中的自定义类,简单的方法

回答by Pablo Ezequiel Leone

This is my HelpersProvider.php file:

这是我的 HelpersProvider.php 文件:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider
{
    protected $helpers = [
        // Add your helpers in here
    ];

    /**
     * Bootstrap the application services.
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     */
    public function register()
    {
        foreach ($this->helpers as $helper) {
            $helper_path = app_path().'/Helpers/'.$helper.'.php';

            if (\File::isFile($helper_path)) {
                require_once $helper_path;
            }
        }
    }
}

You should create a folder called Helpersunder the appfolder, then create file called whatever.phpinside and add the string whateverinside the $helpers array.

您应该Helpers在该app文件夹下创建一个名为的文件夹,然后创建名为whatever.phpinside 的文件并将字符串添加whatever到 $helpers 数组中。

Done!

完毕!

Edit

编辑

I'm no longer using this option, I'm currently using composer to load static files like helpers.

我不再使用这个选项,我目前正在使用 composer 来加载静态文件,比如 helpers。

You can add the helpers directly at:

您可以直接在以下位置添加助手:

...
"autoload": {
    "files": [
        "app/helpers/my_helper.php",
        ...
    ]
},
...

回答by Akshay Khale

For Custom Helper Libraries in my Laravel project, I have created a folder with name Librariesin my Laravel/AppDirectory and within Libraries directory, I have created various files for different helper libraries.

对于我的 Laravel 项目中的自定义助手库,我Libraries在我的Laravel/App目录和库目录中创建了一个带有名称的文件夹,我为不同的助手库创建了各种文件。

After creating my helper files I simply include all those files in my composer.jsonfile like this

创建我的帮助文件后,我只需像这样将所有这些文件包含在我的composer.json文件中

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

and execute

并执行

composer dump-autoload

回答by Paulo Freitas

Since OP asked for best practices, I think we're still missing some good advices here.

由于 OP 要求提供最佳实践,我认为我们在这里仍然缺少一些好的建议。

A single helpers.phpfile is far from a good practice. Firstly because you mix a lot of different kind of functions, so you're against the good coding principles. Moreover, this couldhurt not only the code documentation but also the code metrics like Cyclomatic Complexity, Maintainability Indexand Halstead Volume. The more functions you have the more it gets worse.

单个helpers.php文件远不是一个好的做法。首先,因为您混合了许多不同类型的功能,所以您违反了良好的编码原则。此外,这不仅损害代码文档,还会损害诸如Cyclomatic ComplexityMaintainability IndexHalstead Volume 之类的代码指标。您拥有的功能越多,情况就越糟。

Code documentation would be Ok using tools like phpDocumentor, but using Samiit won't render procedural files. Laravel API documentation is such a case - there's no helper functions documentation: https://laravel.com/api/5.4

使用phpDocumentor 之类的工具可以编写代码文档,但是使用Sami不会呈现程序文件。Laravel API 文档就是这种情况 - 没有辅助函数文档:https://laravel.com/api/5.4

Code metrics can be analyzed with tools like PhpMetrics. Using PhpMetrics version 1.x to analyze Laravel 5.4 framework code will give you very bad CC/MI/HV metrics for both src/Illuminate/Foundation/helpers.phpand src/Illuminate/Support/helpers.phpfiles.

可以使用PhpMetrics 等工具分析代码指标。使用 PhpMetrics 1.x 版来分析 Laravel 5.4 框架代码会给你的src/Illuminate/Foundation/helpers.phpsrc/Illuminate/Support/helpers.php文件提供非常糟糕的 CC/MI/HV 指标。

Multiple contextual helper files (eg. string_helpers.php, array_helpers.php, etc.) would certainly improve those bad metrics resulting in an easier code to mantain. Depending on the code documentation generator used this would be good enough.

多个上下文帮助文件(例如string_helpers.phparray_helpers.php等)肯定会改善那些糟糕的指标,从而使代码更易于维护。根据使用的代码文档生成器,这已经足够了。

It can be further improved by using helper classes with static methods so they can be contextualized using namespaces. Just like how Laravel already does with Illuminate\Support\Strand Illuminate\Support\Arrclasses. This improves both code metrics/organization and documentation. Class aliases could be used to make them easier to use.

通过使用带有静态方法的辅助类可以进一步改进它,以便它们可以使用命名空间进行上下文化。就像 Laravel 已经对Illuminate\Support\StrIlluminate\Support\Arr类所做的那样。这改进了代码度量/组织和文档。类别名可用于使它们更易于使用。

Structuring with classes makes the code organization and documentation better but on the other hand we end up loosing those great short and easy to remember global functions. We can further improve that approach by creating function aliases to those static classes methods. This can be done either manually or dynamically.

使用类进行结构化可以使代码组织和文档更好,但另一方面,我们最终会失去那些简短易记的全局函数。我们可以通过为这些静态类方法创建函数别名来进一步改进该方法。这可以手动或动态完成。

Laravel internally use the first approach by declaring functions in the procedural helper files that maps to the static classes methods. This might be not the ideal thing as you need to redeclare all the stuff (docblocks/arguments).
I personally use a dynamic approach with a HelperServiceProviderclass that create those functions in the execution time:

Laravel 在内部通过在映射到静态类方法的过程帮助文件中声明函数来使用第一种方法。这可能不是理想的事情,因为您需要重新声明所有内容(文档块/参数)。
我个人使用动态方法和一个HelperServiceProvider在执行时创建这些函数的类:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class HelperServiceProvider extends ServiceProvider
{
    /**
     * The helper mappings for the application.
     *
     * @var array
     */
    protected $helpers = [
        'uppercase' => 'App\Support\Helpers\StringHelper::uppercase',
        'lowercase' => 'App\Support\Helpers\StringHelper::lowercase',
    ];

    /**
     * Bootstrap the application helpers.
     *
     * @return void
     */
    public function boot()
    {
        foreach ($this->helpers as $alias => $method) {
            if (!function_exists($alias)) {
                eval("function {$alias}(...$args) { return {$method}(...$args); }");
            }
        }
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

One can say this is over engineering but I don't think so. It works pretty well and contrary to what might be expected it does not cost relevant execution time at least when using PHP 7.x.

有人可以说这是在工程上,但我不这么认为。它工作得很好,与预期的相反,至少在使用 PHP 7.x 时它不会花费相关的执行时间。

回答by Kenneth Sunday

instead of including your custom helper class, you can actually add to your config/app.phpfile under aliases.

您实际上可以config/app.php在别名下添加到您的文件中,而不是包含您的自定义帮助程序类。

should be look like this.

应该是这样的。

 'aliases' => [ 
    ...
    ...
    'Helper' => App\Http\Services\Helper::class,
 ]

and then to your Controller, include the Helper using the method 'use Helper' so you can simply call some of the method on your Helper class.

然后在您的控制器中,使用“use Helper”方法包含 Helper,这样您就可以简单地调用 Helper 类上的一些方法。

eg. Helper::some_function();

or in resources view you can directly call the Helper class already.

或者在资源视图中,您可以直接调用 Helper 类。

eg. {{Helper::foo()}}

But this is still the developer coding style approach to be followed. We may have different way of solving problems, and i just want to share what i have too for beginners.

但这仍然是要遵循的开发人员编码风格方法。我们可能有不同的解决问题的方法,我只想分享我对初学者的看法。