yii2 添加变量,Yii::$service,并像组件component那样可以添加单例配置 [ 2.0 版本 ]
原文链接: yii2 给Yii 添加一个变量,Yii::$service,并像组件component那样可以添加单例配置
在yii2中,组件是可以通过配置的方式添加到Yii::$app中的。
现在我们想添加一个Yii静态变量,$service,下面都称呼这个变量为服务,
可以通过Yii::$service访问,然后添加服务,以及服务的子服务,
譬如我添加了一个cms服务,以及cms服务的子服务article。
那么我想访问cms服务,可以通过Yii::$service->cms访问,
如果我想访问cms服务的子服务,那么,我可以通过Yii::$service->cms->article访问。
上面的使用访问和yii2的组件很类似,是单例模式。下面说具体实现方式:
1.创建一个Yii.php添加$service参数: @vendor/fancyecommerce/fecshop/yii/Yii.php
<?php
$dir = __DIR__ . '/../../../yiisoft/yii2';
require($dir.'/BaseYii.php');
/**
* Yii is a helper class serving common framework functionalities.
*
* It extends from [[\yii\BaseYii]] which provides the actual implementation.
* By writing your own Yii class, you can customize some functionalities of [[\yii\BaseYii]].
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Yii extends \yii\BaseYii
{
public static $service;
}
spl_autoload_register(['Yii', 'autoload'], true, true);
Yii::$classMap = require($dir.'/classes.php');
Yii::$container = new yii\di\Container();
2.在入口文件index.php中,将对yii的Yii.php去掉,换成:
require(__DIR__ . '/../../vendor/fancyecommerce/fecshop/yii/Yii.php');
也就是加载上面,我创建的文件。
然后修改index.php底部代码:
new fecshop\services\Application($config['services']);
unset($config['services']);
//var_dump($config);
$application = new yii\web\Application($config);
$application->run();
也就是添加了代码:
new fecshop\services\Application($config['services']);
unset($config['services']);
这个代码的作用是,给$service变量赋值,Yii::$service = fecshop\services\Application($config[‘services’]);
3.下面我们实现这个Application。
<?php
/**
* FecShop file.
*
* @link http://www.fecshop.com/
* @copyright Copyright (c) 2016 FecShop Software LLC
* @license http://www.fecshop.com/license/
*/
namespace fecshop\services;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
/**
* @author Terry Zhao <2358269014@qq.com>
* @since 1.0
*/
class Application
{
public $childService;
public $_childService;
public function __construct($config = [])
{
Yii::$service = $this;
$this->childService = $config;
}
/**
* 得到services 里面配置的子服务childService的实例
*/
public function getChildService($childServiceName){
if(!$this->_childService[$childServiceName]){
$childService = $this->childService;
if(isset($childService[$childServiceName])){
$service = $childService[$childServiceName];
$this->_childService[$childServiceName] = Yii::createObject($service);
}else{
throw new InvalidConfigException('Child Service ['.$childServiceName.'] is not find in '.get_called_class().', you must config it! ');
}
}
return $this->_childService[$childServiceName];
}
/**
*
*/
public function __get($attr){
return $this->getChildService($attr);
}
}
- 在配置中添加配置:
[
'services' => [
'cms' => [
'class' => 'fecshop\services\Cms',
# 子服务
'childService' => [
'article' => [
'class' => 'fecshop\services\cms\Article',
'storage' => 'mysqldb', # mysqldb or mongodb.
],
],
],
]
5.上面的配置,给cms添加了一个子服务article。
cms 对应的class的代码如下:
<?php
/**
* FecShop file.
*
* @link http://www.fecshop.com/
* @copyright Copyright (c) 2016 FecShop Software LLC
* @license http://www.fecshop.com/license/
*/
namespace fecshop\services;
use Yii;
use yii\base\InvalidValueException;
use yii\base\InvalidConfigException;
use fec\helpers\CSession;
use fec\helpers\CUrl;
/**
* Breadcrumbs services
* @author Terry Zhao <2358269014@qq.com>
* @since 1.0
*/
class Cms extends Service
{
/**
* cms storage db, you can set value: mysqldb,mongodb.
*/
public $storage = 'mysqldb';
}
artile的代码如下:
<?php
/**
* FecShop file.
*
* @link http://www.fecshop.com/
* @copyright Copyright (c) 2016 FecShop Software LLC
* @license http://www.fecshop.com/license/
*/
namespace fecshop\services\cms;
use Yii;
use yii\base\InvalidValueException;
use yii\base\InvalidConfigException;
use fec\helpers\CSession;
use fec\helpers\CUrl;
use fecshop\services\Service;
use fecshop\services\cms\article\ArticleMysqldb;
use fecshop\services\cms\article\ArticleMongodb;
/**
* Breadcrumbs services
* @author Terry Zhao <2358269014@qq.com>
* @since 1.0
*/
class Article extends Service
{
public $storage = 'mongodb';
protected $_article;
public function init(){
if($this->storage == 'mongodb'){
$this->_article = new ArticleMongodb;
}else if($this->storage == 'mysqldb'){
$this->_article = new ArticleMysqldb;
}
}
/**
* Get Url by article's url key.
*/
public function getUrlByPath($urlPath){
//return Yii::$service->url->getHttpBaseUrl().'/'.$urlKey;
return Yii::$service->url->getUrlByPath($urlPath);
}
/**
* get artile's primary key.
*/
public function getPrimaryKey(){
return $this->_article->getPrimaryKey();
}
/**
* get artile model by primary key.
*/
public function getByPrimaryKey($primaryKey){
return $this->_article->getByPrimaryKey($primaryKey);
}
/**
* @property $filter|Array
* get artile collection by $filter
* example filter:
* [
* 'numPerPage' => 20,
* 'pageNum' => 1,
* 'orderBy' => ['_id' => SORT_DESC, 'sku' => SORT_ASC ],
* 'where' => [
* 'price' => [
* '?gt' => 1,
* '?lt' => 10,
* ],
* 'sku' => 'uk10001',
* ],
* 'asArray' => true,
* ]
*/
public function coll($filter=''){
return $this->_article->coll($filter);
}
/**
* @property $one|Array , save one data .
* @property $originUrlKey|String , article origin url key.
* save $data to cms model,then,add url rewrite info to system service urlrewrite.
*/
public function save($one,$originUrlKey){
return $this->_article->save($one,$originUrlKey);
}
public function remove($ids){
return $this->_article->remove($ids);
}
}
他们继承的service类代码如下:
<?php
/**
* FecShop file.
*
* @link http://www.fecshop.com/
* @copyright Copyright (c) 2016 FecShop Software LLC
* @license http://www.fecshop.com/license/
*/
namespace fecshop\services;
use Yii;
use yii\base\Object;
use yii\base\InvalidConfigException;
/**
* @author Terry Zhao <2358269014@qq.com>
* @since 1.0
*/
class Service extends Object
{
public $childService;
public $_childService;
/**
* 得到services 里面配置的子服务childService的实例
*/
public function getChildService($childServiceName){
if(!$this->_childService[$childServiceName]){
$childService = $this->childService;
if(isset($childService[$childServiceName])){
$service = $childService[$childServiceName];
$this->_childService[$childServiceName] = Yii::createObject($service);
}else{
throw new InvalidConfigException('Child Service ['.$childServiceName.'] is not find in '.get_called_class().', you must config it! ');
}
}
return $this->_childService[$childServiceName];
}
/**
*
*/
public function __get($attr){
return $this->getChildService($attr);
}
}
然后,我就可以使用了,按照上面的方法
Yii::$service->cms->$storage # 获取存储方式,这个变量可以在service配置中注入。
Yii::$service->cms->article->remove($ids) # cms服务对应子服务artile的删除功能。
由于这种方式是单例模式,因此,可以用这种方式,在controller和model之间,做一个中间服务层,方便日后的扩展和使用,譬如我如果把mysql换成了mongodb,只需要把这个服务的public方法 重新实现以下就可以了,目前fecshop采用了这种实现方式。
Fecshop 深圳
最后登录:2024-08-13
在线时长:73小时36分
- 粉丝157
- 金钱2381
- 威望490
- 积分8011
热门源码
- 基于 Yii 2 + Bootstrap 3 搭建一套后台管理系统 CMF
- 整合完 yii2-rbac+yii2-admin+adminlte 等库的基础开发后台源码
- 适合初学者学习的一款通用的管理后台
- yii-goaop - 将 goaop 集成到 Yii,在 Yii 中优雅的面向切面编程
- yii-log-target - 监控系统异常且多渠道发送异常信息通知
- 店滴云1.3.0
- 面向对象的一小步:添加 ActiveRecord 的 Scope 功能
- Yii2 开源商城 FecShop
- 基于 Yii2 开发的多店铺商城系统,免费开源 + 适合二开
- leadshop - 基于 Yii2 开发的一款免费开源且支持商业使用的商城管理系统
共 2 条评论
66666
最后,推荐一下我的Fecshop ,开源商城,github地址:https://github.com/fancyecommerce/yii2_fecshop
演示地址:http://fecshop.appfront.fancyecommerce.com/
截止到2016-11-12号,产品,分类,首页,评论,用户中心,搜索,多语言,多货币 等功能已经做完,除了购物车和支付部分,其他的基本都已经完成,关注fecshop的 在等2-3个月,也就是明年2,3月份,版本已经就可以出来,2017年4,5月份在把手机web 做一下,预计到明年5月份,后台,pc前台,手机web前台 ,命令控制台 这几个入口 基本可以完善,多谢大家关注和你们的Star,谢谢,我会坚持把他写好。
作者QQ:2358269014