我在一年前,帮助朋友构建游戏RPG后台的时候,思考如何兼顾开发效率和性能,最终想到了 php + swoole协程 + swoole_orm + zephir ,微信小游戏搜索:“剑的传说”  swoole协程有着极高的IO并发能力 swoole_orm 是我开发的php 扩展,有着非常高的性能、sql安全性和开发效率,开源地址为: https://github.com/swoole/ext-orm  游戏的战斗部分完全用 zephir 来实现,宣称像写php一样写php扩展,能做到同时兼顾性能和开发效率,(zephir 代码有机会我再开源出来,目前时机不成熟,游戏还比较火热) 后台框架开源地址:https://github.com/caohao-php/ycsocket 仅展示部分zephir代码: 输入参数为json, 根据 c 和 m 参数,路由到 controller/Game.php 下 verAction 函数。路由逻辑在 Application->run() 方法中, 所有控制器位于:application/controllers 目录下,继承自SuperController,父类SuperController 的构造函数中会调用$this->init()函数,所以你的控制器如果有初始化任务,请写在 init 函数里。 提供4个返回函数:  response_error 返回报错信息给自己  response_success_to_all 返回数据给当前所有玩家,例如世界聊天  response_success_to_me 返回数据给自己  response_success_to_uids 返回数据给指定uid,在 server.php ,数据接入的时候,我们会将 uid 绑定到 socket fd 上面去 application/Filter.php , 在 auth 中写入验签方法,所有接口都会在这里校验, 所有GET、POST等参数放在 $params 里。 通过 Loader 加载器可以加载业务层,dao层,公共库,日志、配置等对象, Logger 为日志类。 通过 $this->game_service = $this->loader->service(‘GameService’); 去加载业务层。  Service 继承自 SuperService,在 init() 函数里面实现对象初始化内容。 所有与Redis、MySQL等等存储介质打交道的逻辑,最好都放在Dao层,  dao对象通过 $this->game_dao = $this->loader->dao(“GameDao”); 加载。  Dao层继承自 SuperDao,在 init() 函数里面实现对象初始化内容。 $this->redis_name = “default”;  $this->db_name = “default”; 第三方类库都存在于 application/library 目录下 ,通过$this->utillib = $this->loader->library(“Utillib”); 实例化。 日志可以通过 loader 实例化,实例化的日志会打印有请求参数和客户端IP等信息,也可以用得静态函数,不过静态函数无法获取则请求参数或者客户端IP等信息。 日志路径在 server.php 中配置,记得把 /data/app/logs 的权限设置高些,define(‘LOG_PATH’, ‘/data/app/logs/super_server’); //日志目录  日志分如下5个级别:  const DEBUG = ‘DEBUG’;   /* 级别为 1 ,  调试日志,   当 DEBUG = 1 的时候才会打印调试 /  const INFO = ‘INFO’;    / 级别为 2 ,  应用信息记录,  与业务相关, 这里可以添加统计信息 /  const NOTICE = ‘NOTICE’;  / 级别为 3 ,  提示日志,  用户不当操作,或者恶意刷频等行为,比INFO级别高,但是不需要报告*/  const WARN = ‘WARN’;    /* 级别为 4 ,  警告,   应该在这个时候进行一些修复性的工作,系统可以继续运行下去 /  const ERROR = ‘ERROR’;   / 级别为 5 ,  错误,     可以进行一些修复性的工作,但无法确定系统会正常的工作下去,系统在以后的某个阶段, 很可能因为当前的这个问题,导致一个无法修复的错误(例如宕机),但也可能一直工作到停止有不出现严重问题 */
概述

 
代码结构
————————————————  |--- server.php               //启动入口  |--- system                   //框架系统代码 |--- application              //业务代码  |----- config        //配置目录 |----- controller    //控制器目录 |------ Game.php    //Game控制器 |----- dao           //数据层 |----- library       //公用类库 |----- service       //业务层 请求路由
webSocket.send('{"c":"game","m":"ver", "userid":123593}'); 
 路由之前,首先会调用 Filter::auth($params) 对参数验签,我们可以在该函数中加入自己的签名验证逻辑。//system/Application.php class Application { public function run(& $params, $clientInfo) { $ret = Filter::auth($params); if ($ret != 0) { return $ret; } foreach ($params as $k => $v) { $params[$k] = trim($v); } $controller = ucfirst($params['c']); $action = $params['m'] . "Action"; $class_name = $controller . "Controller"; try { $obj = new $class_name($params, $clientInfo); if (!method_exists($obj, $action)) { unset($obj); show_404("$controller/$action"); return $this->response_error(3, "route error"); } $ret = $obj->$action(); unset($obj); return $ret; } catch (Exception $e) { unset($obj); if ($e instanceof LogicException) { //业务异常 $errorcode = $e->getCode() == 0 ? 8 : $e->getCode(); return $this->response_error($errorcode, $e->getMessage()); } else if ($e->getMessage() != 'swoole exit.') {                 Logger::error("Catch An Exception File=[" . $e->getFile() . "|" . $e->getLine() . "] Code=[" . $e->getCode() . "], Message=[" . $e->getMessage() . "]", "exception_log"); echo "Catch An Exception n"; echo "File:" . $e->getFile() . "n"; echo "Line:" . $e->getLine() . "n"; echo "Code:" . $e->getCode() . "n"; echo "Message:" . $e->getMessage() . "n"; return $this->response_error(99, "system exception"); } else { echo "swoole exit.n"; return $this->response_error(99, "application exit"); } } } ... } 控制器Controller
//server.php $uid = intval($input['userid']); if($uid > 0) {     Connector::set_fd($uid, $ws); } class GameController extends SuperController { var $game_service; var $userinfo_service; public function init() { $this->userinfo_service = $this->loader->service('UserinfoService'); $this->game_service = $this->loader->service('GameService'); $this->util_log = $this->loader->logger('game_log'); } //聊天接口 public function chatAction() { $userId = $this->params['userid']; $type = intval($this->params['type']); //0-世界 1-私聊 $token = $this->params['token']; $nickname = $this->params['nickname']; $avatar_url = $this->params['avatar_url']; $content = $this->params['content']; $to_userid = intval($this->params['to_userid']); $this->userinfo_service->getZoneUserAndAuth($userId, $token); if (empty($content)) { return $this->response_error(13342339, '内容不能为空'); } $result = array(); $result['userid'] = $userId; $result['type'] = $type; $result['nickname'] = $nickname; $result['avatar_url'] = $avatar_url; $result['gender'] = $this->params['gender']; $result['vip_level'] = $this->params['vip_level']; $result['lv'] = $this->params['lv']; $result['content'] = $content; if ($type == 0) { return $this->response_success_to_all($result); } else if ($type == 1) { return $this->response_success_to_uids([$userId, $to_userid], $result); } } } 过滤验签
class Filter { //验签过程 public static function auth(& $params) { /*         if($auth_error == false) { //验签失败             return self::response_error(123, "auth error");         } */ //验签成功 return 0; } public static function response_error($code, $message) { $data = array("code" => $code, "msg" => $message); $result['send_user'] = "me"; $result['msg'] = json_encode($data); return $result; } } 加载器
$this->game_service = $this->loader->service('GameService'); $this->game_dao = $this->loader->dao("GameDao"); $this->util_log = $this->loader->logger('game_log'); $this->util_lib = $this->loader->library('Utillib'); $this->conf = $this->loader->config('config'); 业务层
class GameService extends SuperService { public function init() { parent::init(); $this->game_dao = $this->loader->dao("GameDao"); $this->userinfo_service = $this->loader->dao("UserinfoService"); $this->util_log = $this->loader->logger('game_log'); } //用户充值 public function get_user_vip_contents($userid) { $data = $this->game_dao->get_user_vip_contents($userid); if (empty($data['content'])) { $content = array(); $content['leiji_xiaofei'] = 0; //累计消费 $content['leiji_chong'] = 0; //累计充值 $content['jijin']['status'] = 0; //是否购买成长基金 0-未购买 1-已购买 $this->game_dao->insert_user_vip_contents($userid, $content); } else { $content = json_decode($data['content'], true); } return $content; } //更新充值信息 public function update_user_vip_contents($userid, $content) { return $this->game_dao->update_user_vip_contents($userid, $content); } ... } Dao层
 SuperDao 提供了许多快速操作数据库的方法,如果你需要用到 SuperDao 的快速操作数据库的函数,
 你最好指定以下数据库、缓存配置,因为默认他们是 default, 这些配置位于application/config 目录下的 database.php 和 redis.php 中。class GameDao extends SuperDao { public function init() { $this->db_name = "game"; $this->util_log = $this->loader->logger('game_log'); } //user_vip_contents 表 public function get_user_vip_contents($userid) { $key = 'pre_vip_contents_' . $userid; $data = $this->get_one_table_data('user_vip_contents', ['user_id' => $userid], $key); return $data; } public function insert_user_vip_contents($userid, $content) { $key = 'pre_vip_contents_' . $userid; return $this->insert_table('user_vip_contents', ['user_id' => $userid, 'content' => json_encode($content)], $key); } ... } //数据库配置 database.php $util_db_config['default']['host'] = '127.0.0.1'; $util_db_config['default']['username'] = 'test'; $util_db_config['default']['password'] = 'test'; $util_db_config['default']['dbname'] = 'user'; $util_db_config['default']['char_set'] = 'utf8'; $util_db_config['default']['dbcollat'] = 'utf8_general_ci'; $util_db_config['default']['pool_size'] = 10; //redis配置 redis.php $util_redis_conf['userinfo']['host'] = '127.0.0.1'; $util_redis_conf['userinfo']['port'] = 6381; $util_redis_conf['userinfo']['auth'] = 'o01nc7vgd65xa'; //使用方法 MySQLPool::instance('default')->query($sql); MySQLPool::instance('default')->get($table, $where, $column); RedisPool::instance('userinfo')->set('test', 123); RedisPool::instance('userinfo')->expire('test', 86400); library库
日志
class GameService extends SuperService {     public function init()     {         parent::init();         $this->util_log = $this->loader->logger('game_log');     }          public funciton test()      {         $this->util_log->LogInfo("info test");     $this->util_log->LogNotice("notice test");     $this->util_log->LogWarn("warning test");     $this->util_log->LogError("error test");     }          public funciton static_test()      {         Logger::info("static info test");     Logger::notice("static notice test");     Logger::warn("static warning test");     Logger::error("static error test");          } } 附录 – CoreModel 中的辅助极速开发函数(不关心可以跳过)
/**  * 根据key获取表记录  * @param string redis_key redis 缓存键值  */ public function hget_redis($redis_key, $field); /**  * 设置 redis 值  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存  * @param array data 表数据  * @param int redis_expire redis 缓存到期时长(秒)  * @param boolean set_empty_flag 是否缓存空值,如果缓存空值,在表记录更新之后,一定记得清理空值标记缓存  */ public function hset_redis($redis_key, $field, $data, $redis_expire = 600, $set_empty_flag = true); /**  * 根据key获取表记录  * @param string redis_key redis 缓存键值  */ public function get_redis($redis_key) /**  * 设置 redis 值  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存    * @param array data 表数据  * @param int redis_expire redis 缓存到期时长(秒)  * @param boolean set_empty_flag 是否缓存空值,如果缓存空值,在表记录更新之后,一定记得清理空值标记缓存  */ public function set_redis($redis_key, $data, $redis_expire = 600, $set_empty_flag = true); /**  * 清理记录缓存  * @param string redis_key redis 缓存键值  */ public function clear_redis_cache($redis_key = ""); /**  * 插入表记录  * @param string table 表名  * @param array data 表数据  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存  */ public function insert_table($table, $data, $redis_key = ""); /**  * 更新表记录  * @param string table 表名  * @param array where 查询条件  * @param array data 更新数据  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存  */ public function update_table($table, $where, $data, $redis_key = ""); /**  * 替换表记录  * @param string table 表名  * @param array data 替换数据  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存  */ public function replace_table($table, $data, $redis_key = ""); /**  * 删除表记录  * @param string table 表名  * @param array where 查询条件  * @param string redis_key redis缓存键值, 可空, 非空时清理键值缓存  */ public function delete_table($table, $where, $redis_key = ""); /**  * 获取表数据  * @param string table 表名  * @param array where 查询条件  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存  * @param int redis_expire redis 缓存到期时长(秒)  * @param string $column 数据库表字段,可空  * @param boolean set_empty_flag 是否将空值写入缓存,防止数据库击穿,默认为是  */ public function get_table_data($table, $where = array(), $redis_key = "", $redis_expire = 600, $column = "*", $set_empty_flag = true); /**  * 获取一条表数据  * @param string table 表名  * @param array where 查询条件  * @param string redis_key redis 缓存键值, 可空, 非空时清理键值缓存  * @param int redis_expire redis 缓存到期时长(秒)  * @param string $column 数据库表字段,可空  * @param boolean set_empty_flag 是否将空值写入缓存,防止数据库击穿,默认为是  */ public function get_one_table_data($table, $where, $redis_key = "", $redis_expire = 600, $column = "*", $set_empty_flag = true); 
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
官方软件产品操作指南 (170)