├── .gitignore ├── .DS_Store ├── app ├── .DS_Store ├── config │ ├── .DS_Store │ ├── loader.php │ ├── config.php │ └── services.php ├── controllers │ ├── ControllerBase.php │ └── IndexController.php ├── views │ ├── index │ │ └── index.volt │ └── index.volt └── models │ ├── Institution.php │ ├── Departments.php │ └── User.php ├── server ├── .DS_Store ├── monitor.php ├── client.php └── server.php ├── tests ├── .DS_Store ├── docker-compose.yml ├── Dockerfile └── dora.sql ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddonng/DoraPhalcon/HEAD/.DS_Store -------------------------------------------------------------------------------- /app/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddonng/DoraPhalcon/HEAD/app/.DS_Store -------------------------------------------------------------------------------- /server/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddonng/DoraPhalcon/HEAD/server/.DS_Store -------------------------------------------------------------------------------- /tests/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddonng/DoraPhalcon/HEAD/tests/.DS_Store -------------------------------------------------------------------------------- /app/config/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddonng/DoraPhalcon/HEAD/app/config/.DS_Store -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "xcl3721/dora-rpc": ">=0.4.9" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /app/controllers/ControllerBase.php: -------------------------------------------------------------------------------- 1 | 2 |

Congratulations!

3 | 4 | 5 |

You're now flying with Phalcon. Great things are about to happen!

6 | 7 |

This page is located at views/index/index.volt

8 | -------------------------------------------------------------------------------- /app/config/loader.php: -------------------------------------------------------------------------------- 1 | registerDirs( 9 | array( 10 | $config->application->controllersDir, 11 | $config->application->modelsDir 12 | ) 13 | )->register(); 14 | -------------------------------------------------------------------------------- /server/monitor.php: -------------------------------------------------------------------------------- 1 | array( 8 | array(//first reporter 9 | "ip" => getenv("HOST_MACHINE_IP"), 10 | "port" => "6379", 11 | ), 12 | ), 13 | "Config" =>"./client.conf.php" 14 | ); 15 | $res = new \DoraRPC\Monitor("0.0.0.0", 9569, $Config); 16 | -------------------------------------------------------------------------------- /app/config/config.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'adapter' => 'Mysql', 8 | 'host' => getenv('HOST_MACHINE_IP'), 9 | 'username' => 'root', 10 | 'password' => '123456', 11 | 'dbname' => 'core', 12 | 'charset' => 'utf8', 13 | ), 14 | 'application' => array( 15 | 'controllersDir' => APP_PATH . '/app/controllers/', 16 | 'modelsDir' => APP_PATH . '/app/models/', 17 | 'migrationsDir' => APP_PATH . '/app/migrations/', 18 | 'viewsDir' => APP_PATH . '/app/views/', 19 | 'pluginsDir' => APP_PATH . '/app/plugins/', 20 | 'libraryDir' => APP_PATH . '/app/library/', 21 | 'cacheDir' => APP_PATH . '/app/cache/', 22 | 'baseUri' => '/www/', 23 | ) 24 | )); 25 | -------------------------------------------------------------------------------- /app/views/index.volt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Phalcon PHP Framework 9 | 10 | 11 | 12 |
13 | {{ content() }} 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DoraPhalcon 2 | 3 | 标签(空格分隔):swoole doraRPC phalcon 4 | 5 | --- 6 | 7 | 这是一个菜鸟的好时代,因为大神们不断的贡献……好人一生平安!(●ˇ∀ˇ●) 8 | 9 | DoraPhalcon只是将DoraRPC与Phalcon组装在一起……DoraRPC写得非常好,作者[@蓝天](http://weibo.com/thinkpc)还在继续按照他最初的完美设计在不断完成,所以[DoraRPC](https://github.com/xcl3721/Dora-RPC)还可以更好o(^▽^)o,顺便带上DoraPhalcon。用Phalcon是因为太喜欢它的DI了,而且用习惯了后也不想再换框架……要我自己写,水平不够,轮子造不出来( ▼-▼ )…… 10 | 11 | 12 | DoraPhalcon上PHP7,目前: 13 | > * PHP7已发布 14 | > * Swoole支持PHP7 15 | > * Phalcon3.0发布 16 | > * [Waiting] ODM上php7需要等待官方 17 | 18 | ## Install 19 | 1、安装phalcon3(最新) 20 | 21 | 2、安装Dora-RPC 22 | 23 | composer require "xcl3721/dora-rpc" 24 | 25 | ## 如何体验 26 | 准备了docker环境,按以下步骤可进行体验: 27 | 28 | 1、安装docker 29 | 这里访问[docker官网][1],安装好对应系统的 30 | 31 | 2、下载代码库 32 | 33 | git clone https://github.com/ddonng/DoraPhalcon.git 34 | 3、编译镜像 35 | 36 | cd DoraPhalcon/tests 37 | docker build -t ddonng/rpc:7.0 . 38 | 4、启动容器 39 | 修改docker-compose.yml中的HOST_MACHINE_IP为当前电脑的ip,然后命令: 40 | 41 | docker-compose up -d 42 | 43 | 由于数据库还未建立,运行会报错。 44 | 45 | 5、导入sql文件 46 | 使用mysql管理软件,如mysql-workbench,连接到localhost:3306,创建数据库core,并导入tests目录下的dora.sql创建数据表及测试数据。 47 | 48 | 6、重新启动服务 49 | 50 | docker-compose down 51 | #全部删除后 52 | docker-compose up -d 53 | 54 | 7、尽情体验 55 | 56 | [1]: https://www.docker.com 57 | -------------------------------------------------------------------------------- /tests/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | dora_server: 5 | image: ddonng/rpc:7.0 6 | environment: 7 | HOST_MACHINE_IP: 192.168.1.102 # 设置为宿主机ip 8 | volumes: 9 | - '../:/home/www/' 10 | command: php /home/www/server/server.php 11 | restart: always 12 | networks: 13 | - backend 14 | dora_monitor: 15 | image: ddonng/rpc:7.0 16 | volumes: 17 | - ../:/home/www/:rw 18 | environment: 19 | HOST_MACHINE_IP: 192.168.1.102 # 设置为宿主机ip 20 | restart: always 21 | command: php /home/www/server/monitor.php 22 | networks: 23 | - backend 24 | dora_client: 25 | image: ddonng/rpc:7.0 26 | volumes: 27 | - ../:/home/www/:rw 28 | environment: 29 | HOST_MACHINE_IP: 192.168.1.102 # 设置为宿主机ip 30 | restart: always 31 | command: php /home/www/server/client.php 32 | networks: 33 | - backend 34 | mysql: 35 | image: mysql:5.6 36 | restart: always 37 | environment: 38 | MYSQL_ROOT_PASSWORD: 123456 39 | volumes: 40 | - "./data/mysqldb:/var/lib/mysql:rw" 41 | ports: 42 | - "3306:3306" 43 | redis: 44 | image: redis:3.2.1 45 | restart: always 46 | ports: 47 | - "6379:6379" 48 | networks: 49 | backend: {} 50 | -------------------------------------------------------------------------------- /app/models/Institution.php: -------------------------------------------------------------------------------- 1 | hasMany('institution_id', 'Departments', 'institution_id', array('alias' => 'Departments')); 30 | $this->hasMany('institution_id', 'User', 'institution_id', array('alias' => 'User')); 31 | } 32 | 33 | /** 34 | * Returns table name mapped in the model. 35 | * 36 | * @return string 37 | */ 38 | public function getSource() 39 | { 40 | return 'institution'; 41 | } 42 | 43 | /** 44 | * Allows to query a set of records that match the specified conditions 45 | * 46 | * @param mixed $parameters 47 | * @return Institution[] 48 | */ 49 | public static function find($parameters = null) 50 | { 51 | return parent::find($parameters); 52 | } 53 | 54 | /** 55 | * Allows to query the first record that match the specified conditions 56 | * 57 | * @param mixed $parameters 58 | * @return Institution 59 | */ 60 | public static function findFirst($parameters = null) 61 | { 62 | return parent::findFirst($parameters); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/models/Departments.php: -------------------------------------------------------------------------------- 1 | hasMany('department_id', 'User', 'deartment_id', array('alias' => 'User')); 36 | $this->belongsTo('institution_id', 'Institution', 'institution_id', array('alias' => 'Institution')); 37 | } 38 | 39 | /** 40 | * Returns table name mapped in the model. 41 | * 42 | * @return string 43 | */ 44 | public function getSource() 45 | { 46 | return 'departments'; 47 | } 48 | 49 | /** 50 | * Allows to query a set of records that match the specified conditions 51 | * 52 | * @param mixed $parameters 53 | * @return Departments[] 54 | */ 55 | public static function find($parameters = null) 56 | { 57 | return parent::find($parameters); 58 | } 59 | 60 | /** 61 | * Allows to query the first record that match the specified conditions 62 | * 63 | * @param mixed $parameters 64 | * @return Departments 65 | */ 66 | public static function findFirst($parameters = null) 67 | { 68 | return parent::findFirst($parameters); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /tests/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7-cli 2 | MAINTAINER XiaodongHuang 3 | 4 | RUN apt-get update && apt-get install -y git zlib1g-dev 5 | # install pdo_mysql extension 6 | RUN docker-php-ext-install pdo_mysql 7 | 8 | # memcached extensions 9 | RUN apt-get install -y libmemcached11 libmemcachedutil2 build-essential libmemcached-dev libz-dev 10 | RUN git clone -b php7 https://github.com/php-memcached-dev/php-memcached.git 11 | RUN cd php-memcached && phpize && ./configure && make && make install \ 12 | && echo "extension=memcached.so" > /usr/local/etc/php/conf.d/memcached.ini 13 | 14 | # install phpredis extension 15 | ENV PHPREDIS_VERSION 3.0.0 16 | RUN curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/$PHPREDIS_VERSION.tar.gz \ 17 | && tar xfz /tmp/redis.tar.gz \ 18 | && rm -r /tmp/redis.tar.gz \ 19 | && mv phpredis-$PHPREDIS_VERSION /usr/src/php/ext/redis \ 20 | && docker-php-ext-install redis 21 | 22 | # install mongo extension, phalcon3.0 is still not support mongoDB driver T.T 23 | #RUN apt-get -y install libssl-dev pkg-config && pecl install mongo \ 24 | # && echo "extension=mongo.so" > /usr/local/etc/php/conf.d/mongo.ini 25 | 26 | # swoole extension,use 1.8.7 27 | RUN pecl install swoole-1.8.7 && echo extension=swoole.so >> /usr/local/etc/php/conf.d/swoole.ini 28 | 29 | # phalcon extension 30 | RUN apt-get install -y libpcre3-dev openssl libssl-dev 31 | RUN git clone --depth=1 http://github.com/phalcon/cphalcon 32 | RUN cd cphalcon/build && ./install \ 33 | && echo extension=phalcon.so >> /usr/local/etc/php/conf.d/phalcon.ini 34 | RUN rm -rf cphalcon 35 | 36 | RUN apt-get install -y \ 37 | libfreetype6-dev \ 38 | libjpeg62-turbo-dev \ 39 | libmcrypt-dev \ 40 | libpng12-dev \ 41 | && docker-php-ext-install -j$(nproc) iconv mcrypt \ 42 | && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ 43 | && docker-php-ext-install -j$(nproc) gd 44 | # clean 45 | RUN apt-get remove -y build-essential libmemcached-dev libz-dev git \ 46 | && apt-get autoremove -y 47 | 48 | RUN apt-get clean 49 | RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 50 | 51 | WORKDIR /home/www/ 52 | VOLUME ["/home/www/"] 53 | -------------------------------------------------------------------------------- /server/client.php: -------------------------------------------------------------------------------- 1 | array( 8 | // array("ip" => "172.23.0.4", "port" => 9567), 9 | // //array("ip"=>"127.0.0.1","port"=>9567), you can set more ,the client will random select one,to increase High availability 10 | // ), 11 | // ); 12 | //or 13 | $config = include("client.conf.php"); 14 | // var_dump($config); 15 | //define the mode 16 | $mode = array("type" => 1, "group" => "test_group"); 17 | $maxrequest = 0; 18 | //new obj 19 | $obj = new \DoraRPC\Client($config); 20 | //change connect mode 21 | $obj->changeMode($mode); 22 | // for ($i = 0; $i < 10000; $i++) { 23 | // $ret2 = $obj->singleAPI("getUserById", array("user_id" => 1, "foo" => $i), \DoraRPC\DoraConst::SW_MODE_WAITRESULT, 1); 24 | // $ret2 = $obj->singleAPI("checkUserLoginInfo", array("login_type" => "stuff_id", "login_name" => "00167","password"=>"5f9a9917d364bdb3fa7f61a5a719b694"), \DoraRPC\DoraConst::SW_MODE_WAITRESULT, 1); 25 | // $ret2 = $obj->singleAPI("addUser", 26 | // array("user" => array( 27 | // "stuff_id"=>"00189", 28 | // "name" => "李四", 29 | // "institution_id"=>3, 30 | // "register_time"=>time(), 31 | // "email"=>"ssd@11.com", 32 | // "passwd"=>"5f9a9917d364bdb3fa7f61a5a719b694")), 33 | // \DoraRPC\DoraConst::SW_MODE_WAITRESULT, 1); 34 | // $ret2 = $obj->singleAPI("updateUser", 35 | // array("user" => array( 36 | // "user_id"=>1, 37 | // "stuff_id"=>"00180", 38 | // "name" => "问道", 39 | // "institution_id"=>3, 40 | // "register_time"=>time(), 41 | // "email"=>"adfsdf@qq.com", 42 | // "passwd"=>"5f9a9917d364bdb3fa7f61a5a719b694")), 43 | // \DoraRPC\DoraConst::SW_MODE_WAITRESULT, 1); 44 | // $ret2 = $obj->singleAPI("deleteUser", 45 | // array("user_id" => 9),\DoraRPC\DoraConst::SW_MODE_WAITRESULT, 1); 46 | // var_dump("single sync", $ret); 47 | $ret2 = $obj->singleAPI("getUsers", 48 | array("fields"=>array("institution_id" => 3,"degree"=>"硕士")),\DoraRPC\DoraConst::SW_MODE_WAITRESULT, 1); 49 | // var_dump("single sync", $ret); 50 | var_dump("single sync", $ret2); 51 | // } 52 | -------------------------------------------------------------------------------- /app/config/services.php: -------------------------------------------------------------------------------- 1 | setShared('url', function () use ($config) { 25 | $url = new UrlResolver(); 26 | $url->setBaseUri($config->application->baseUri); 27 | 28 | return $url; 29 | }); 30 | 31 | /** 32 | * Setting up the view component 33 | */ 34 | $di->setShared('view', function () use ($config) { 35 | 36 | $view = new View(); 37 | 38 | $view->setViewsDir($config->application->viewsDir); 39 | 40 | $view->registerEngines(array( 41 | '.volt' => function ($view, $di) use ($config) { 42 | 43 | $volt = new VoltEngine($view, $di); 44 | 45 | $volt->setOptions(array( 46 | 'compiledPath' => $config->application->cacheDir, 47 | 'compiledSeparator' => '_' 48 | )); 49 | 50 | return $volt; 51 | }, 52 | '.phtml' => 'Phalcon\Mvc\View\Engine\Php' 53 | )); 54 | 55 | return $view; 56 | }); 57 | 58 | /** 59 | * Database connection is created based in the parameters defined in the configuration file 60 | */ 61 | $di->setShared('db', function () use ($config) { 62 | $dbConfig = $config->database->toArray(); 63 | $adapter = $dbConfig['adapter']; 64 | unset($dbConfig['adapter']); 65 | 66 | $class = 'Phalcon\Db\Adapter\Pdo\\' . $adapter; 67 | 68 | return new $class($dbConfig); 69 | }); 70 | 71 | /** 72 | * If the configuration specify the use of metadata adapter use it or use memory otherwise 73 | */ 74 | $di->setShared('modelsMetadata', function () { 75 | return new MetaDataAdapter(); 76 | }); 77 | 78 | /** 79 | * Register the session flash service with the Twitter Bootstrap classes 80 | */ 81 | $di->set('flash', function () { 82 | return new Flash(array( 83 | 'error' => 'alert alert-danger', 84 | 'success' => 'alert alert-success', 85 | 'notice' => 'alert alert-info', 86 | 'warning' => 'alert alert-warning' 87 | )); 88 | }); 89 | 90 | /** 91 | * Start the session the first time some component request the session service 92 | */ 93 | $di->setShared('session', function () { 94 | $session = new SessionAdapter(); 95 | $session->start(); 96 | 97 | return $session; 98 | }); 99 | 100 | $di->setShared('table',function(){ 101 | var_export("table shared \n"); 102 | $table = new swoole_table(1024); 103 | $table->column('param',swoole_table::TYPE_STRING,1024); 104 | $table->create(); 105 | return $table; 106 | }); 107 | -------------------------------------------------------------------------------- /app/models/User.php: -------------------------------------------------------------------------------- 1 | email) && isset($this->email) ){ 131 | $this->validate( 132 | new Email( 133 | array( 134 | 'field' => 'email', 135 | 'required' => true, 136 | ) 137 | ) 138 | ); 139 | } 140 | 141 | 142 | if ($this->validationHasFailed() == true) { 143 | return false; 144 | } 145 | 146 | return true; 147 | } 148 | 149 | /** 150 | * Initialize method for model. 151 | */ 152 | public function initialize() 153 | { 154 | $this->belongsTo('deartment_id', 'Departments', 'department_id', array('alias' => 'Departments')); 155 | $this->belongsTo('institution_id', 'Institution', 'institution_id', array('alias' => 'Institution')); 156 | } 157 | 158 | /** 159 | * Returns table name mapped in the model. 160 | * 161 | * @return string 162 | */ 163 | public function getSource() 164 | { 165 | return 'user'; 166 | } 167 | 168 | /** 169 | * Allows to query a set of records that match the specified conditions 170 | * 171 | * @param mixed $parameters 172 | * @return User[] 173 | */ 174 | public static function find($parameters = null) 175 | { 176 | return parent::find($parameters); 177 | } 178 | 179 | /** 180 | * Allows to query the first record that match the specified conditions 181 | * 182 | * @param mixed $parameters 183 | * @return User 184 | */ 185 | public static function findFirst($parameters = null) 186 | { 187 | return parent::findFirst($parameters); 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /server/server.php: -------------------------------------------------------------------------------- 1 | 3, 17 | //to improve the accept performance ,suggest the number of cpu X 2 18 | //如果想提高请求接收能力,更改这个,推荐cpu个数x2 19 | 'reactor_num' => 2, 20 | //packet decode process,change by condition 21 | //包处理进程,根据情况调整数量 22 | 'worker_num' => 10, 23 | //the number of task logical process progcessor run you business code 24 | //实际业务处理进程,根据需要进行调整 25 | /******************************************/ 26 | 'task_worker_num' => 20, //太大引起崩溃会提示onFinish那里的$data是数组而不是string, < mysql max_connections 27 | 28 | ); 29 | protected $externalHttpConfig = array( 30 | 'reactor_num' => 2, 31 | 'worker_num' => 10, 32 | 'task_worker_num' => 20, 33 | 'daemonize' => 0, 34 | ); 35 | 36 | public static function getDiInstance() { 37 | if (!self::$diInstance) { 38 | self::$diInstance = new Phalcon\Di\FactoryDefault(); 39 | } 40 | return self::$diInstance; 41 | } 42 | public static function getAppInstance() { 43 | if (!self::$appInstance) { 44 | try { 45 | /** 46 | * Read the configuration 47 | */ 48 | $config = include APP_PATH . "/app/config/config.php"; 49 | /** 50 | * Read auto-loader 51 | */ 52 | include APP_PATH . "/app/config/loader.php"; 53 | 54 | /** 55 | * Read services 56 | */ 57 | $di = self::getDiInstance(); 58 | include APP_PATH . "/app/config/services.php"; 59 | 60 | self::$appInstance = new \Phalcon\Mvc\Micro($di); 61 | 62 | /** 63 | * Handle the Route, Sync RPC handler 64 | */ 65 | $syncRoute = new Phalcon\Mvc\Micro\Collection(); 66 | $syncRoute->setHandler('IndexController',true); 67 | $syncRoute->setPrefix('sync/'); 68 | $syncRoute->map('getUserById/{key}','getUserByIdAction'); 69 | $syncRoute->map('checkUserLoginInfo/{key}','checkUserLoginInfoAction'); 70 | $syncRoute->map('checkLoginName/{key}','checkLoginNameAction'); 71 | $syncRoute->map('addUser/{key}','addUserAction'); 72 | $syncRoute->map('updateUser/{key}','updateUserAction'); 73 | $syncRoute->map('deleteUser/{key}','deleteUserAction'); 74 | $syncRoute->map('getUsers/{key}','getUsersAction'); 75 | 76 | self::$appInstance->mount($syncRoute); 77 | 78 | /** 79 | * More, just like Async RPC handler 80 | */ 81 | 82 | } catch (\Exception $e) { 83 | echo $e->getMessage() . '
'; 84 | echo '
' . $e->getTraceAsString() . '
'; 85 | } 86 | } 87 | return self::$appInstance; 88 | } 89 | function initServer($server){ 90 | //the callback of the server init 附加服务初始化 91 | //such as swoole atomic table or buffer 可以放置swoole的计数器,table等 92 | 93 | } 94 | function doWork($param){ 95 | //process you logical 业务实际处理代码仍这里 96 | //return the result 使用return返回处理结果 97 | 98 | $app = self::getAppInstance(); 99 | $di = self::getDiInstance(); 100 | 101 | // Two route Controller : sync and async 102 | 103 | $routePrefix = ''; 104 | $type = $param['type']; 105 | $apiName = $param['api']['name']; 106 | if($type == \DoraRPC\DoraConst::SW_MODE_WAITRESULT_SINGLE || $type == \DoraRPC\DoraConst::SW_MODE_WAITRESULT_MULTI) 107 | { 108 | $routePrefix = 'sync/'.$apiName; 109 | } elseif($type == DoraRPC\DoraConst::SW_MODE_ASYNCRESULT_SINGLE || $type == DoraRPC\DoraConst::SW_MODE_ASYNCRESULT_MULTI){ 110 | $routePrefix = 'async/'.$apiName; 111 | } 112 | 113 | $key = $type."_".$apiName."_".$param['guid']; 114 | $table = $di->get('table'); 115 | $table->set($key,array("param"=>serialize($param['api']['param']))); 116 | 117 | $route = $routePrefix.'/'.$key; 118 | return $app->handle($route); 119 | } 120 | function initTask($server, $worker_id){ 121 | //require_once() 你要加载的处理方法函数等 what's you want load (such as framework init) 122 | // self::getAppInstance(); 123 | $app = self::getAppInstance(); 124 | $di = self::getDiInstance(); 125 | } 126 | } 127 | //this server belong which logical group 128 | //different group different api(for Isolation) 129 | $groupConfig = array( 130 | "list" => array( 131 | "test_group", 132 | ), 133 | ); 134 | //redis for service discovery register 135 | //when you on product env please prepare more redis to registe service for high available 136 | $redisconfig = array( 137 | array(//first reporter,可改为ip 138 | "ip" => getenv("HOST_MACHINE_IP"), 139 | "port" => "6379", 140 | ), 141 | ); 142 | 143 | $res = new Server("0.0.0.0", 9567, 9566, $groupConfig, $redisconfig); 144 | -------------------------------------------------------------------------------- /tests/dora.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.7.12, for osx10.9 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: core 4 | -- ------------------------------------------------------ 5 | -- Server version 5.6.31 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `departments` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `departments`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `departments` ( 26 | `department_id` int(11) NOT NULL AUTO_INCREMENT, 27 | `department_name` varchar(100) NOT NULL, 28 | `department_desc` varchar(200) DEFAULT NULL, 29 | `institution_id` int(11) NOT NULL, 30 | PRIMARY KEY (`department_id`), 31 | UNIQUE KEY `department_id_UNIQUE` (`department_id`), 32 | KEY `institution_fk_idx` (`institution_id`), 33 | CONSTRAINT `dep_institution_fk` FOREIGN KEY (`institution_id`) REFERENCES `institution` (`institution_id`) ON DELETE NO ACTION ON UPDATE CASCADE 34 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 35 | /*!40101 SET character_set_client = @saved_cs_client */; 36 | 37 | -- 38 | -- Dumping data for table `departments` 39 | -- 40 | 41 | LOCK TABLES `departments` WRITE; 42 | /*!40000 ALTER TABLE `departments` DISABLE KEYS */; 43 | INSERT INTO `departments` VALUES (1,'教务处','教学运行管理部门',3); 44 | /*!40000 ALTER TABLE `departments` ENABLE KEYS */; 45 | UNLOCK TABLES; 46 | 47 | -- 48 | -- Table structure for table `institution` 49 | -- 50 | 51 | DROP TABLE IF EXISTS `institution`; 52 | /*!40101 SET @saved_cs_client = @@character_set_client */; 53 | /*!40101 SET character_set_client = utf8 */; 54 | CREATE TABLE `institution` ( 55 | `institution_id` int(11) NOT NULL AUTO_INCREMENT, 56 | `institution_name` varchar(200) NOT NULL, 57 | `institution_desc` varchar(200) DEFAULT NULL, 58 | PRIMARY KEY (`institution_id`), 59 | UNIQUE KEY `institution_id_UNIQUE` (`institution_id`), 60 | UNIQUE KEY `institution_name_UNIQUE` (`institution_name`) 61 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; 62 | /*!40101 SET character_set_client = @saved_cs_client */; 63 | 64 | -- 65 | -- Dumping data for table `institution` 66 | -- 67 | 68 | LOCK TABLES `institution` WRITE; 69 | /*!40000 ALTER TABLE `institution` DISABLE KEYS */; 70 | INSERT INTO `institution` VALUES (3,'机构名称','111'); 71 | /*!40000 ALTER TABLE `institution` ENABLE KEYS */; 72 | UNLOCK TABLES; 73 | 74 | -- 75 | -- Table structure for table `user` 76 | -- 77 | 78 | DROP TABLE IF EXISTS `user`; 79 | /*!40101 SET @saved_cs_client = @@character_set_client */; 80 | /*!40101 SET character_set_client = utf8 */; 81 | CREATE TABLE `user` ( 82 | `user_id` int(11) NOT NULL AUTO_INCREMENT, 83 | `name` varchar(12) NOT NULL, 84 | `passwd` varchar(32) DEFAULT NULL, 85 | `sex` varchar(4) DEFAULT NULL, 86 | `institution_id` int(11) NOT NULL, 87 | `deartment_id` int(11) DEFAULT NULL, 88 | `professional_title` varchar(64) DEFAULT NULL, 89 | `diploma` varchar(45) DEFAULT NULL, 90 | `degree` varchar(45) DEFAULT NULL, 91 | `nation` varchar(10) DEFAULT NULL, 92 | `native_place` varchar(45) DEFAULT NULL, 93 | `stuff_id` varchar(45) DEFAULT NULL, 94 | `qq` varchar(45) DEFAULT NULL COMMENT 'qq还有邮箱的形式', 95 | `email` varchar(45) DEFAULT NULL, 96 | `mobile_phone` varchar(88) DEFAULT NULL COMMENT '加密 base64', 97 | `office_phone` varchar(88) DEFAULT NULL COMMENT 'base64加密', 98 | `register_time` int(10) NOT NULL, 99 | `login_q` varchar(32) DEFAULT NULL, 100 | `login_phone` varchar(32) DEFAULT NULL, 101 | PRIMARY KEY (`user_id`), 102 | UNIQUE KEY `user_id_UNIQUE` (`user_id`), 103 | UNIQUE KEY `email_UNIQUE` (`email`), 104 | KEY `institution_id_normal` (`institution_id`), 105 | KEY `department_fk_idx` (`deartment_id`), 106 | CONSTRAINT `department_fk` FOREIGN KEY (`deartment_id`) REFERENCES `departments` (`department_id`) ON DELETE NO ACTION ON UPDATE CASCADE, 107 | CONSTRAINT `institution_fk` FOREIGN KEY (`institution_id`) REFERENCES `institution` (`institution_id`) ON DELETE NO ACTION ON UPDATE CASCADE 108 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 109 | /*!40101 SET character_set_client = @saved_cs_client */; 110 | 111 | -- 112 | -- Dumping data for table `user` 113 | -- 114 | 115 | LOCK TABLES `user` WRITE; 116 | /*!40000 ALTER TABLE `user` DISABLE KEYS */; 117 | INSERT INTO `user` VALUES (1,'张三','5f9a9917d364bdb3fa7f61a5a719b694','男',3,1,'助教','研究生','硕士','汉族','江西省赣州','00167','324324235','asfsg@qq.com','13688888888','013-12345678',1469023544,'cce65970cf4b7b772caef8976142e944','ae766006fae78a5cd2f350ecfc717723'); 118 | /*!40000 ALTER TABLE `user` ENABLE KEYS */; 119 | UNLOCK TABLES; 120 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 121 | 122 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 123 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 124 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 125 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 126 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 127 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 128 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 129 | 130 | -- Dump completed on 2016-08-01 16:15:05 131 | -------------------------------------------------------------------------------- /app/controllers/IndexController.php: -------------------------------------------------------------------------------- 1 | table->get($key); 20 | return unserialize($data['param']); 21 | } 22 | 23 | /** 24 | * 用user_id获取用户信息,不返回密码; 25 | * 26 | * @return array 返回不包含password的用户数据 27 | */ 28 | 29 | public function getUserByIdAction($key) 30 | { 31 | $param = $this->__getParam($key); 32 | $user_id = $param['user_id']; 33 | 34 | $user = User::findFirst(array( 35 | "user_id = :user_id:", 36 | "bind" => array("user_id"=>intval($user_id)) 37 | )); 38 | 39 | $ret = array_merge( 40 | $user->toArray(), 41 | array( 42 | "institution_name" => $user->Institution->institution_name, 43 | "institution_desc" => $user->Institution->institution_desc, 44 | "department_name" => $user->Departments->department_name, 45 | "department_desc" => $user->Departments->department_desc 46 | ) 47 | ); 48 | unset($ret['passwd']);//密码不返回 49 | 50 | $this->table->del($key); 51 | return $ret; 52 | } 53 | 54 | /** 55 | * 检查登陆用户名与密码是否匹配,使用手机号码、工号、qq号、邮箱与密码匹配. 56 | * 客户端需要提供的参数dorarpc client param: 57 | * 58 | * [1] login_type [login_q, login_phone, email, stuff_id]中一个 59 | * 60 | * [2] login_name 登录用户名值 61 | * 62 | * [3] password 用户密码. 63 | * @return array 64 | */ 65 | 66 | public function checkUserLoginInfoAction($key) 67 | { 68 | $param = $this->__getParam($key); 69 | $login_type = $param['login_type']; 70 | $login_name = $param['login_name']; 71 | $password = $param['password']; 72 | 73 | $user = User::findFirst(array( 74 | "$login_type = :login_name: AND passwd = :password:", 75 | "bind"=>array( 76 | "login_name"=>$login_name, 77 | "password"=>$password 78 | ) 79 | )); 80 | 81 | if($user) 82 | { 83 | // 用户名与密码匹配,返回用户id 84 | $ret = array("result"=>"SUCCESS","user_id"=>$user->user_id); 85 | }else{ 86 | // 不匹配 87 | $ret = array("result"=>"FAIL"); 88 | } 89 | 90 | $this->table->del($key); 91 | return $ret; 92 | } 93 | 94 | /** 95 | * 用户名是否存在 96 | * 97 | * 客户端需要提供的参数dorarpc client param: 98 | * 99 | * [1] login_type [login_q, login_phone, email, stuff_id]中一个 100 | * 101 | * [2] login_name 登录用户名值 102 | * @return array 103 | */ 104 | 105 | public function checkLoginNameAction($key) 106 | { 107 | $param = $this->__getParam($key); 108 | $login_type = $param['login_type']; 109 | $login_name = $param['login_name']; 110 | 111 | $user = User::findFirst(array( 112 | "$login_type = :login_name:", 113 | "bind"=>array( 114 | "login_name"=>$login_name 115 | ) 116 | )); 117 | 118 | if($user) 119 | { 120 | // 用户名与密码匹配,返回用户id 121 | $ret = array("result"=>"SUCCESS","user_id"=>$user->user_id); 122 | }else{ 123 | // 不匹配 124 | $ret = array("result"=>"FAIL"); 125 | } 126 | 127 | unset($user); 128 | $this->table->del($key); 129 | return $ret; 130 | } 131 | 132 | /** 133 | * 新增用户,客户端提供用户数据;不验证直接insert,返回user_id 134 | */ 135 | public function addUserAction($key) 136 | { 137 | $param = $this->__getParam($key); 138 | $new_user = $param['user']; 139 | 140 | $user = new User(); 141 | $user->assign($new_user); 142 | if($user->save()) 143 | { 144 | $ret = array("result"=>"SUCCESS","user_id"=>$user->user_id); 145 | }else{ 146 | $ret = array("result"=>"FAIL","msg"=>$user->getMessages()); 147 | } 148 | 149 | unset($user); 150 | $this->table->del($key); 151 | return $ret; 152 | } 153 | 154 | /** 155 | * 更新用户,客户端需提供user_id与其他键值对 156 | */ 157 | 158 | public function updateUserAction($key) 159 | { 160 | $param = $this->__getParam($key); 161 | $update_user = $param['user']; 162 | if(!isset($update_user['user_id'])){ 163 | return array("result"=>"FAIL","msg"=>"Must need user ID."); 164 | } 165 | 166 | $user = User::findFirst(array( 167 | "user_id = :user_id:", 168 | "bind"=>array("user_id"=>$update_user['user_id']) 169 | )); 170 | 171 | if($user) 172 | { 173 | $user->assign($update_user); 174 | if($user->update()) 175 | { 176 | $ret = array("result"=>"SUCCESS","user_id"=>$user->user_id); 177 | }else{ 178 | $ret = array("result"=>"FAIL","msg"=>$user->getMessages()); 179 | } 180 | } 181 | unset($user); 182 | $this->table->del($key); 183 | return $ret; 184 | 185 | } 186 | 187 | /** 188 | * 删除用户,需提供user_id 189 | */ 190 | public function deleteUserAction($key) 191 | { 192 | $param = $this->__getParam($key); 193 | if(isset($param['user_id'])) 194 | $user_id = $param['user_id']; 195 | 196 | $user = User::findFirst(array( 197 | "user_id = :user_id:", 198 | "bind"=>array("user_id"=>$user_id) 199 | )); 200 | 201 | if($user->delete()) 202 | { 203 | $ret = array("result"=>"SUCCESS"); 204 | }else{ 205 | $ret = array("result"=>"FAIL"); 206 | } 207 | 208 | unset($user); 209 | $this->table->del($key); 210 | return $ret; 211 | } 212 | 213 | /** 214 | * 获取多用户数据,传入用户字段键值对,返回用户数组 215 | * fields必须为字段键值对数组 216 | */ 217 | public function getUsersAction($key) 218 | { 219 | $param = $this->__getParam($key); 220 | $fields = $param['fields']; 221 | 222 | #拼接查询 223 | $condition = " "; 224 | $and = False; 225 | foreach ($fields as $key => $value) { 226 | if($and) $condition .= " AND "; 227 | $condition .= "$key = :$key:"; 228 | $and = True; 229 | } 230 | 231 | $users = User::find(array( 232 | $condition, 233 | "bind"=>$fields, 234 | )); 235 | if($users) 236 | { 237 | $users_detail = array(); 238 | foreach ($users as $user) { 239 | #密码不返回 240 | $arr = $user->toArray(); 241 | unset($arr["passwd"]); 242 | $users_detail[] = array_merge($arr, 243 | array( 244 | "institution_name" => $user->Institution->institution_name, 245 | "institution_desc" => $user->Institution->institution_desc, 246 | "department_name" => $user->Departments->department_name, 247 | "department_desc" => $user->Departments->department_desc 248 | ) 249 | ); 250 | unset($arr); 251 | } 252 | $ret = array("result"=>"SUCCESS","users"=>$users_detail); 253 | }else{ 254 | $ret = array("result"=>"FAIL","msg"=>$users->getMessages()); 255 | } 256 | 257 | unset($users); 258 | unset($users_detail); 259 | $this->table->del($key); 260 | return $ret; 261 | 262 | } 263 | 264 | } 265 | --------------------------------------------------------------------------------