How to extend laravel 4 core?

2019-03-27 18:55发布

I am a newb learning laravel 4. I want to override specific helper functions. Or add new functions to Url, Str etc. How to do this?

3条回答
\"骚年 ilove
2楼-- · 2019-03-27 19:36

Depending on what part of Laravel you want to extend or replace, there are different approaches.

Macros

Adding functions to Str is really easy, because of "macros":

Here's a short example for adding function:

Str::macro('test', function($str) {
    return 'Testing: ' . $str . '!';
});

You can then call this function as expected:

echo Str::test('text'); // Outputs "Testing: text!"

Adding functions using macros are supported by Str, Form, HTML and Response.

IOC Based Extension

To extend URL one must use the IOC of Laravel. This is explained in the docs (as mentioned by BenjaminRH). I agree it can be a bit hard to understand. Here's a step-by-step to extend URL:

  1. Create folder app/lib to hold your extension classes.

  2. Add this folder to autoloading:

    In app/start/global.php, append the lib path to the class loader:

    ClassLoader::addDirectories(array(
       app_path().'/commands',
       app_path().'/controllers',
       app_path().'/models',
       app_path().'/database/seeds',
       app_path().'/lib'
    ));
    

    Then add the path to composer.json classmap:

    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php",
            "app/lib"
        ]
    },
    
  3. Create the custom UrlGenerator app/lib/CustomUrlGenerator.php:

    <?php 
    
    use \Illuminate\Routing\UrlGenerator;
    
    class CustomUrlGenerator extends UrlGenerator
    {
        public function test()
        {
            return $this->to('/test');
        }
    }
    
  4. Create a service provider app/lib/CustomRoutingServiceProvider.php:

    <?php
    
    use \Illuminate\Routing\RoutingServiceProvider;
    
    class CustomRoutingServiceProvider extends RoutingServiceProvider
    {
        public function boot()
        {
            App::bind('url', function()
            {
                return new CustomUrlGenerator(
                    App::make('router')->getRoutes(),
                    App::make('request')
                );
            });
    
            parent::boot();
        }
    }
    
  5. Register the service provider in app/config/app.php:

    Add CustomRoutingServiceProvider to the providers array. For example, right after the Workbench provider:

    'Illuminate\Workbench\WorkbenchServiceProvider',
    'CustomRoutingServiceProvider',
    
  6. Run composer dump-autoload from project root folder.

  7. Done. Use like:

    URL::test();
    

NOTE The code is tested, but may contain some errors

查看更多
Anthone
3楼-- · 2019-03-27 19:43

Interesting that you should mention this, actually. A whole documentation section was just recently added, which covers this in detail. It's very clear, and easy to understand. If you've been using Laravel at all, it might not even surprise you that Laravel actually provides an extend method for a lot of core components.

查看更多
疯言疯语
4楼-- · 2019-03-27 19:47

Following Fnatte's answer, today's versions of Laravel do some extra processing in the url binding. Redefining the whole binding is no longer a practical option.

Here is how I ended up for extending the URL facade.

First, create your child class using this boilerplate:

use Illuminate\Routing\UrlGenerator;

class YourUrlGenerator extends UrlGenerator {

    public function __construct(UrlGenerator $url)
    {
        parent::__construct($url->routes, $url->request);
    }

    // redefine or add new methods here
}

Then, add this in a ServiceProvider:

$url = $this->app['url'];

$this->app->singleton('url', function() use ($url)
{
    return new YourUrlGenerator($url);
});

The point is simply that the original url binding should be executed at least once before we override it with our own.

查看更多
登录 后发表回答