三分钟学会扩展laravel服务

来源:互联网 发布:快手后期制作软件名字 编辑:程序博客网 时间:2024/06/07 07:05

        刚开始看了laravel "系统架构"这一章后,感觉很难懂,不知道service provider、service container、Facade等等名词讲的是什么鬼。直到自己摸索写出了一个elastic search的服务扩展才恍然大悟。

       其实,laravel service provider、service container、Facade 讲的都是一件事儿:你可以自由扩展laravel框架的服务。 貌似还是有点懵~

       首先你要了解一点:laravel的核心其实是一个IOC容器!laravel框架提供的服务,其实都是后来才注入到容器中的!例如你熟悉的方法“DB::select()”、“Cache::put()”等等中的DB、Cache等服务都是“核心”之外的东西,都是后来才注入到laravel框架中的!如下所有的laraval框架自带的服务,都是注入到laravel核心框架后,才可以使用的!

也就是说:你可以自己定义一个服务,然后放入框架中!

下面以elasticsearch为例,注册一个elasticsearch 服务到laravel框架中。

1、“service provider” 是提供服务的东东,你想提供什么服务,就在这里面定义。

我们先在composer.json中添加elasticsearch 需要的依赖。然后使用:php artisan make:provider ElasticSearchProvider创建一个“ElasticSearchProvider”;在register中添加上你想要实例化的类,即为laravel可提供的服务。推荐使用App的singleton方法,因为很明显“单例”,或者使用其他的例如“bind”等方法,IDE上自行查阅。

/** * Register the application services. * * @return void */public function register(){    $value = config('database.elasticsearch')['hosts'];    $this->app->singleton('Elasticsearch\Client',function($value) use ($value){       return ClientBuilder::create()->setHosts(           [$value])->build();    });}

然后,把所写的这个provider在config目录下的app.php配置文件中的provider 那一栏做一下注册,laravel框架中就有你的服务啦!


2、你想要达到从.env取路径或者配置的效果?就像是laravel框架原生的服务一样?

也很简单,从.env里取东西,只需调用方法"env('key')",例如你在.env文件中定义了如下内容:

#elasticsearch 配置ElasticSearch_HOST=elasticsearchElasticSearch_PORT=9200
你想取出来,就使用:“env("ElasticSearch_HOST")”和“env(ElasticSearch_PORT)”

但是这样会出现一个问题:由于".env"文件通常是不加入版本管理的。

/vendor/node_modules/public/storageHomestead.yamlHomestead.json.env.idea_ide_helper.phpstoragebootstrapdocker
这样一来,程序就会报错。怎么办呢?细心的你可能会发现laravel自带的DB等服务,都是在config目录下的配置文件中取出.env文件中的内容的:

/*|--------------------------------------------------------------------------| Redis Databases|--------------------------------------------------------------------------|| Redis is an open source, fast, and advanced key-value store that also| provides a richer set of commands than a typical key-value systems| such as APC or Memcached. Laravel makes it easy to dig right in.|*/'redis' => [    'cluster' => false,    'default' => [        'host' => env('REDIS_HOST', 'localhost'),        'password' => env('REDIS_PASSWORD', null),        'port' => env('REDIS_PORT', 6379),        'database' => 0,    ],],
我们当然可以效仿,定义一个elasticsearch配置文件。在config目录下或者写在已有的配置文件中(本例子就是),然后在配置文件中写"return 

'hosts' => env('ElasticSearch_HOST',"elasticsearch").":".env("ElasticSearch_PORT","9200")
这里的env方法如果取不到“ElasticSearch_HOST”或者“ElasticSearch_PORT”,就会默认将第二个参数返回即“elasticsearch”和“9200”,这样一来,就解决了.env文件加入版本忽略而下来代码后取不到值得问题。然后想要取配置文件中的内容的时候,使用“config”方法:例如你想取elasticsearch中的"hosts"中的内容 如上图所示。你就可以写:config("elasticsearch.hosts")。本例子是将elasticsearch的配置写在 database.php中的:

 /*|--------------------------------------------------------------------------| elasticsearch 相关的配置|--------------------------------------------------------------------------||*/ 'elasticsearch' => [    'hosts' => env('ElasticSearch_HOST',"elasticsearch").":".env("ElasticSearch_PORT","9200") ],
所以在取值的时候是这样的:

$value = config('database.elasticsearch')['hosts'];
3、好了,还有最后一步,你发现使用"DB::search()"等方式十分的简便:使用一个“代号”,来代表一个服务,然后直接使用这个服务,十分方便!下面就将ElasticSearch服务用“ES”来代替。

我原以为laraval框架既然支持大家自定义服务,会专门弄一个项目目录来存放Facade,就像controller目录来放置控制器一样,但是很遗憾,没找到!好吧,那只能自定义一个目录来放Facade了,我在App目录下自定义了一个Facade目录,然后写一个了Facade。

class ES extends Facade{    protected static function getFacadeAccessor() {        return 'Elasticsearch\Client';    }}
写Facade也类也很简单:首先继承laravel框架的Illumiate\Support\Facades\Facade接口,然后重写"getFacadeAccessor方法,返回你在service provider “register”方法中注册的那个类的名字即可。(就是$this->app->singleton(类的名字,function(){...}),请自行看本文的步骤一 service provider的那张图)

最后,你在config目录下的app.php中的最后一行“aliases”配置项中填上"ES" => 对应的Facade目录下的ES类

    'Route' => Illuminate\Support\Facades\Route::class,    'Schema' => Illuminate\Support\Facades\Schema::class,    'Session' => Illuminate\Support\Facades\Session::class,    'Storage' => Illuminate\Support\Facades\Storage::class,    'URL' => Illuminate\Support\Facades\URL::class,    'Validator' => Illuminate\Support\Facades\Validator::class,    'View' => Illuminate\Support\Facades\View::class,    'ES' => 刚才自定义的Facade的类的地址],

好了,大功完成!是不是很简单!laravel的扩展性真心不错!

2 0
原创粉丝点击