如何扩展Laravel供应商包

时间:2016-12-20 12:23:44

标签: php laravel service-provider

我正在尝试延长Kryptonit3/Counter。特别是,我需要覆盖Counter.php类中的一个私有函数来检索过去24小时内的命中。

Counter.php私人功能:

private static function countHits($page)
{
    $page_record = self::createPageIfNotPresent($page);
    return number_format($page_record->visitors->count());
}

我需要的功能:

private static function countHits($page)
{
    $page_record = self::createPageIfNotPresent($page);
    return number_format($page_record->visitors()->where('created_at', '>=', Carbon::now()->subDay())->count());
}

因此,我正在寻找覆盖此软件包的正确方法。

方法1 :我应该创建自己的类来扩展Counter.php并在此类中包含我的自定义函数吗?如果是这样,原始类中包含的私有类会发生什么?我应该创建服务提供商吗?这个服务提供商的样子如何?

方法2 :我应该分叉供应商包并根据自己的需要更新此包吗?

我已经查看了与此主题相关的所有stackoverflow问题,但它们不够清晰。

更新 这就是我到目前为止所做的:

创建MyCounter类:

<?php

namespace App\Helpers\Counter;

use Kryptonit3\Counter\Counter;
class MyCounter extends Counter
{

}

创建MyCounterServiceProvider:

<?php

namespace App\Providers;

use App\Helpers\MyCounter;
use Illuminate\Support\ServiceProvider;

class MyCounterServiceProvider extends ServiceProvider
{
/**
 * Bootstrap the application services.
 *
 * @return void
 */
public function boot()
{
    //
}

/**
 * Register the application services.
 *
 * @return void
 */
public function register()
{
    $this->app['counter'] = $this->app->share(function($app)
    {
        $visitor = $app['visitor'];
        return new MyCounter($visitor);
    });
}
}

创建MyCounterFacade:

<?php

namespace App\Helpers\Counter;


use Illuminate\Support\Facades\Facade;

class MyCounterFacade extends Facade
{
    protected static function getFacadeAccessor() { return 'mycounter'; }
}

在config / app.php中包含提供程序和别名:

App\Providers\MyCounterServiceProvider::class,

'MyCounter'             => App\Helpers\Counter\MyCounterFacade::class,

2 个答案:

答案 0 :(得分:0)

静态方法不能静态覆盖,但您可以使用__callstatic以动态覆盖它们:

Route::get('/override', function() {
    $b = new ClassB();

    dd($b::originalMethod());
});

class ClassA {
    private static function originalMethod() {
        return 'Original value from ClassA';
    }

    public function callingOriginalMethodMethod()
    {
        return static::originalMethod();
    }
}

class ClassB {
    public static function __callStatic($name, $arguments) {
        if ($name == 'originalMethod') {
            return static::overloadedMethod();
        }

        return forward_static_call_array(array(ClassA::class, $name), $arguments);
    }

    protected static function overloadedMethod() {
        return 'Overloaded value from ClassB';
    }
}

点击/覆盖,你应该看到

Overloaded value from ClassB

话虽如此,你能做什么:

为该类创建覆盖:

<?php

namespace App\Helpers;

use Kryptonit3\Counter\Counter;

class MyCounter extends Counter
{
   public static function __callStatic($name, $arguments) {
        if ($name == 'countHits') {
            return static::myCountHits($page);
        }

        return forward_static_call_array(array(Counter::class, $name), $arguments);
    }

    protected static function myCountHits($page) {
        return 'whatever';
    }
}

然后您只需覆盖counter的原始实例。

app()->singleton('counter', function() {
    return app()->make(MyCounter::class);
});

答案 1 :(得分:0)

问题与MyCounterServiceProvider有关。下一段代码解决了这个问题。

 public function register()
{
    $this->app->singleton('mycounter', function() {
        return $this->app->make('App\Helpers\Counter\MyCounter');
    });
}