| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 | 
							- <?php
 
- /**
 
-  * FecShop file.
 
-  *
 
-  * @link http://www.fecshop.com/
 
-  * @copyright Copyright (c) 2016 FecShop Software LLC
 
-  * @license http://www.fecshop.com/license/
 
-  */
 
- namespace fec\helpers;
 
- use Yii; 
 
- ##########################################################################################################################################
 
- # CProfile 是一个中央调度器,各个模块的访问,必须通过CProfile的 fetch方法
 
- # 1.模块如果想要被其他模块调用,必须把模块注册到CProfile,才可以使用CProfile调用
 
- #		1.1模块注册内容:模块路径,模块api url根路径,token(选填,如果不填写,使用默认的token)。
 
- #		1.2模块内容存放:模块的内容存放到数据库中,然后缓存到redis,要保证所有的节点都可以连接到数据库和redis,
 
- #		   如果没有配置mysql和redis,就无法调取模块注册的信息。
 
- # 2.在调取远程模块之前,进行数据的格式验证,和模块注册信息的验证,验证失败会抛出HTTP Exception
 
- # 3.如果是本地访问的模块,调度器会访问模块对应的o文件下的方法。
 
- # 4.如果访问的远程的模块,调度器会访问远程模块对应的o文件夹下面的方法。
 
- #		4.1数据传递:1.函数方法参数,2.$_GET,$_POST 里面的参数,3.cookie的值。
 
- #		4.2安全验证:模块的token和传递的token进行验证,验证通过,返回数据。
 
- #		4.3在远程模块访问前,先提交session,保证session提交到redis,进而,远程模块可以访问到最新的session
 
- #			同样,远程模块在返回数据之前,也会提交session到redis中。
 
- # 5.CProfile 是单例模式,只能通过  CProfile::getInstance() 实例化
 
- # 6.返回数据验证:远程返回的是json格式数据,验证数据的正确性,如果是错误信息,则会抛出HTTP Exception
 
- # 7.JSON格式转换成数组格式
 
- # 8. 注意:current_remote_function_param_array  不要在post 和get 中出现,这个参数被用来传递函数方法的参数。
 
- ##########################################################################################################################################
 
- /**
 
-  * @author Terry Zhao <2358269014@qq.com>
 
-  * @since 1.0
 
-  */
 
- class CProfile
 
- {
 
- 	
 
- 	//保存类实例的静态成员变量
 
- 	private static $_instance;
 
- 	 
 
- 	//private标记的构造方法
 
- 	private function __construct(){
 
- 		//echo 'This is a Constructed method;';
 
- 	}
 
- 	 
 
- 	//创建__clone方法防止对象被复制克隆
 
- 	public function __clone(){
 
- 		//trigger_error('Clone is not allow!',E_USER_ERROR);
 
- 	}
 
- 	 
 
- 	//单例方法,用于访问实例的公共的静态方法
 
- 	public static function getInstance(){
 
- 		if(!(self::$_instance instanceof self)){
 
- 			self::$_instance = new self;
 
- 		}
 
- 		return self::$_instance;
 
- 	}
 
- 	
 
- 	# 模块间访问数据的调度方法。
 
- 	# $obj_data   =   [ $modules,$file,$function,$is_remote='false'   ];
 
- 	# $req_data	  =   [];  传递的参数
 
- 	public function fetch($obj_data,$req_data=[]){
 
- 		if(!is_array($req_data)){
 
- 			$message = 'fetch($obj_data,$req_data),$req_data must be array';
 
- 			throw new \yii\web\HttpException(406,$message);
 
- 		} 
 
- 		$data = '';
 
- 		if(is_array($obj_data) && !empty($obj_data)){
 
- 			$modules 	= $obj_data[0];
 
- 			$file 		= $obj_data[1];
 
- 			
 
- 			$function 	= $obj_data[2];
 
- 			$is_remote 	= $obj_data[3];
 
- 			if($modules && $file && $function){
 
- 				$ModulesConfig = $this->getModulesConfig();
 
- 				if(isset($ModulesConfig[$modules])){
 
- 					$moduleConfig = $ModulesConfig[$modules];
 
- 					if($is_remote){
 
- 						# 远程 
 
- 						# 把模块更新的session更新到redis上面,以供其他模块使用
 
- 						session_commit();
 
- 						$data = $this->getRemotePostData($modules,$moduleConfig,$file,$function,$req_data,$timeout = 20);
 
- 					}else{
 
- 						# 本地
 
- 						$file   = str_replace("/","\\",$file);
 
- 						$function_exec = $moduleConfig['moduleDir']."\\o\\".$file;
 
- 						$function_exec .= "::".$function;
 
- 						$data = \call_user_func_array($function_exec,$req_data);
 
- 						$data = CFunc::object_to_array(json_decode($data));
 
- 					}
 
- 				}else{
 
- 					$message = "!! Get Data From Local Module <$modules> Error: Module is not config in Profile.";
 
- 					throw new \yii\web\HttpException(406,$message);
 
- 					
 
- 					
 
- 		
 
- 				}
 
- 			}else{
 
- 				$message = "!! Get Data From Local Module <$modules> Error: param:obj_data must is array and count >= 3.";
 
- 				throw new \yii\web\HttpException(406,$message);
 
- 				
 
- 			}
 
- 		}else{
 
- 			$message = "!! Get Data From Local Module <$modules> Error: param:obj_data is Empty OR is not Array .";
 
- 			throw new \yii\web\HttpException(406,$message);
 
- 			
 
- 			
 
- 		}
 
- 		return $data;
 
- 	}
 
- 	
 
- 	
 
- 	
 
- 	public function getDefaultToken(){
 
- 		return CConfig::getDefaultModuleToken();
 
- 	}
 
- 	
 
- 	# 得到模块的配置
 
- 	public function getModulesConfig(){
 
- 		return [
 
- 			
 
- 			'DMenu' => [
 
- 							'moduleDir' =>'\appdata\code\Blog\DMenu',
 
- 							'apiurl'  =>'http://120.24.37.249:100/dmenu',
 
- 							'token'  =>'xxxxxx',
 
- 						],	
 
- 		];
 
- 		
 
- 	}
 
- 	
 
- 	# 得到远程模块信息
 
- 	public function getRemotePostData($modules,$moduleConfig,$file,$function,$req_data=[],$timeout = 20){
 
- 		$file = str_replace("\\","/",$file);
 
- 		$url 	= strtolower(trim($moduleConfig['apiurl']."/".$file."/".$function));
 
- 		$module_token 	= $moduleConfig['token'] ? $moduleConfig['token'] : $this->getDefaultToken();
 
- 		$post 	= Yii::$app->request->post() ;
 
- 		$get 	= Yii::$app->request->get();
 
- 		$post 	= $post ? $post : [];
 
- 		$get 	= $get ? $get : [];
 
- 		$data   = array_merge($get , $post); 
 
- 		$data['module_token'] = $module_token;	
 
- 		$data['current_remote_function_param_array'] = serialize($req_data);
 
- 		$arr = '';
 
- 		//var_dump($_COOKIE);exit;
 
- 		if(is_array($_COOKIE)){
 
- 			foreach($_COOKIE as $k=>$v){
 
- 				$arr[]  = $k."=".urlencode($v);
 
- 			}
 
- 		}
 
- 		if(!empty($arr)){
 
- 			$strCookie = implode(";",$arr);
 
- 		}
 
- 		//对空格进行转义
 
- 		$url = str_replace(' ','+',$url);
 
- 		$ch = curl_init();
 
- 		//设置选项,包括URL
 
- 		curl_setopt($ch, CURLOPT_URL, "$url");
 
- 		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 
- 		curl_setopt($ch, CURLOPT_HEADER, 0);
 
- 		if($strCookie){
 
- 			curl_setopt( $ch, CURLOPT_COOKIE, $strCookie ); 
 
- 		}
 
- 		curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);  
 
- 		// POST数据
 
- 		curl_setopt($ch, CURLOPT_POST, 1);
 
- 		// 把post的变量加上
 
- 		curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
 
- 		//执行并获取url地址的内容
 
- 		$output = curl_exec($ch);
 
- 		//echo $output ;
 
- 		//释放curl句柄
 
- 		curl_close($ch);
 
- 		//var_dump($data['current_remote_function_param_array']);
 
- 		//var_dump($_COOKIE);
 
- 		//echo "<br/><br/>";
 
- 		//var_dump($output);
 
- 		//echo $url;
 
- 		//exit;
 
- 		//$return['ack'] = true;
 
- 		//$return['ack_description'] = "success";
 
- 		//$return['content'] = $data;
 
- 		$return = CFunc::object_to_array(json_decode($output));
 
- 		if($return['ack']){
 
- 			return $return['content'];
 
- 		}else{
 
- 			$message = "Get Data From Remote Module <$modules> Error:".$return['ack_description'].".";
 
- 			throw new \yii\web\HttpException(400,$message);
 
- 			
 
- 		}
 
- 		//return $output;
 
- 		
 
-         
 
-     
 
- 	}
 
- }
 
 
  |