Best Practices for Custom Helpers in Laravel 5

后端 未结 20 1984
暖寄归人
暖寄归人 2020-11-22 06:40

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

view.blade.php

Foo Formated text: {{ fo

相关标签:
20条回答
  • 2020-11-22 07:30

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

    A single helpers.php file 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 could hurt not only the code documentation but also the code metrics like Cyclomatic Complexity, Maintainability Index and Halstead Volume. The more functions you have the more it gets worse.

    Code documentation would be Ok using tools like phpDocumentor, but using Sami it won't render procedural files. Laravel API documentation is such a case - there's no helper functions documentation: 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.php and src/Illuminate/Support/helpers.php files.

    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.

    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\Str and Illuminate\Support\Arr classes. This improves both code metrics/organization and documentation. Class aliases could be used to make them easier to use.

    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 HelperServiceProvider class that create those functions in the execution time:

    <?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.

    0 讨论(0)
  • 2020-11-22 07:30

    First create helpers.php inside App\Http directory. Then add the following code inside the composer.json

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

    Next run the following command

    composer dump-autoload
    

    Now you can define your custom function inside the helpers.php file.

    0 讨论(0)
  • 2020-11-22 07:32

    This is what is suggested by JeffreyWay in this Laracasts Discussion.

    1. Within your app/Http directory, create a helpers.php file and add your functions.
    2. Within composer.json, in the autoload block, add "files": ["app/Http/helpers.php"].
    3. Run composer dump-autoload.
    0 讨论(0)
  • 2020-11-22 07:32

    Custom Blade Directives in Laravel 5

    Yes, there is another way to do this!

    Step 1: Register a custom Blade directive:

    <?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:

    <!-- // 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

    Additional Reading: 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

    0 讨论(0)
  • 2020-11-22 07:34

    Another Way that I used was: 1) created a file in app\FolderName\fileName.php and had this code inside it i.e

    <?php
    namespace App\library
    {
     class hrapplication{
      public static function libData(){
       return "Data";
      }
     }
    }
    ?>
    

    2) After that in our blade

     $FmyFunctions = new \App\FolderName\classsName;
      echo $is_ok = ($FmyFunctions->libData());
    

    that's it. and it works

    0 讨论(0)
  • 2020-11-22 07:38

    Custom Classes in Laravel 5, the Easy Way

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

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

    <?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:

    <?php // Code within config/app.php
    
        'aliases' => [
         ...
            'Helper' => App\Helpers\Helper::class,
         ...
    

    Step 3: Run composer dump-autoload in the project root

    Step 4: Use it in your Blade template:

    <!-- 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:

    <?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/

    Why it works: 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

    0 讨论(0)
提交回复
热议问题