您的位置:首页 > 编程语言 > PHP开发

三分钟学会扩展laravel服务

2016-04-03 15:10 465 查看
刚开始看了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=elasticsearch
ElasticSearch_PORT=9200

你想取出来,就使用:“env("ElasticSearch_HOST")”和“env(ElasticSearch_PORT)”

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

/vendor
/node_modules
/public/storage
Homestead.yaml
Homestead.json
.env
.idea
_ide_helper.php
storage
bootstrap
docker

这样一来,程序就会报错。怎么办呢?细心的你可能会发现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的扩展性真心不错!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: