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;
-
-
-
- }
- }
|