vip 模块串讲
来源:互联网 发布:小超市供销存管理优化 编辑:程序博客网 时间:2024/05/11 18:21
模块串讲
一. 新人专题快速入手
1.部署配置
在http://gitlab.tools.vipshop.com/mst/mst-admin-front 拉代码,优先选择git原生支持的ssh协议,即git clone git@gitlab.tools.vipshop.com:mst/mst-admin-front.git 优点就是每次push 和pull 不用输入账号密码,而已速度更快,条件是要将开发电脑的ssh key 添加到gitlab
拉下来的代码目录要修改所有者和用户组,根据nginx的worker进程的所有者
和php-fpm 的子进程(与nginx保持一致)
所以这里是 chown -R www-data www-data mst-admin-front
这样才有足够权限读写,例如写日志,而不需要给文件777这种不安全的设置
nginx 的配置,看部分配置文件
server { listen 80; server_name mst-admin.vip.vip.com; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; #charset koi8-r; #access_log logs/host.access.log main; root /Users/liuxing/www/mtms/branches/mtms_0525; location / { root /Users/liuxing/www/mtms/branches/mtms_0525; index admin.php; } rewrite ^/css/(.+)$ /client/src/css/$1; rewrite ^/common/(.+)$ /client/src/common/$1; rewrite ^/bower_component/(.+)$ /client/src/bower_component/$1; rewrite ^/api/(.+)$ /client/src/api/$1; rewrite ^/demo/(.+)$ /client/src/demo/$1; rewrite ^/module/(.+)$ /client/src/module/$1; rewrite ^/prototype/(.+)$ /client/src/prototype/$1; set $flag 0; if ($request !~ "admin.php"){ set $flag "${flag}1"; } if (!-e $request_filename) { set $flag "${flag}2"; } if ($request ~ ([0-9]+)\.php(.*)$) { set $flag "${flag}3"; rewrite ([0-9]+)\.php(.*)$ /index.php/Special/page?page_type_id=1&id=$1&$2; } if ($flag = "012") { rewrite ^/(.*)$ /index.php/$1; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location ~ \.php { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; set $real_script_name $fastcgi_script_name; set $path_info ""; if ( $fastcgi_script_name ~ "^(.+\.php)(/.+)$"){ set $real_script_name $1; set $path_info $2; } fastcgi_param SCRIPT_FILENAME $document_root$real_script_name; fastcgi_param PATH_INFO $path_info; include fastcgi_params; } }
2.框架结构与开发流程
MobileFramework,较轻量的web框架,阅读源码比较容易,下面看admin的入口文件
调用了 MobileFramework::init(‘admin’);
核心代码是
require SYS_PATH.’/core/Load.class.php’;
require SYS_PATH.’/core/Hooks.class.php’;
Load::init();
Hooks::init();
Hooks::call(‘pre_system’);
# 网站根目录地址 define('ROOT', isset($_SERVER['SCRIPT_NAME']) ? rtrim(dirname($_SERVER['SCRIPT_NAME']), '\\') : NULL); require SYS_PATH.'/core/Common.php'; require SYS_PATH.'/core/Model.class.php'; Application::init(); Route::init(); Dispatcher::init(); Hooks::call('last_system');12345678910111213141516
Load 这个class 的核心功能就是提供了类的自动加载,自动导入share 和new share 目录下的所有类和框架核心类,不用每次调用都require,可以在config/autoload.php 这个文件配置自动加载的类库
Hooks 钩子功能,可以指定调用控制器方法之前或之后执行的脚本,目前项目没怎么使用该功能
Application:init 利用 register_shutdown_function 函数注册 脚本运行结束的回调函数 功能: 将错误日志写到指定文件
Route 路由器,,整理url参数信息, 支持4种路由规则 专题项目使用的是pathinfo 的url解析方法,若开启路由,先解析路由规则
Dispatcher 框架调度类,调用请求action 入口
主要目录作用
service:调用外部接口
bussiness:编写业务逻辑
helper:辅助类
model: 与数据库交互
前后端交互 :目前一种方式是后端返回json,前端调接口。另外一种是用smarty模板引擎,后面会去掉,没用的东西。
还有一种是没用smarty 使用一个PhpView的简单模板
项目大量使用了Factory::create(),一个简单的工厂,实现了最基本的单例模式
开发流程一般是controller 调bussiness bussiness 里调了service或model,就是这么简单。
二.框架和业务代码编写的不足
底层类DB类的链式操作封装不完善,例如当要实现(where ..and ..and (name = .. or name is null))这种形式的操作只能写原生sql,建议完善DB类的方法封装
SimpleUploadHelper 这个类封装了httpPost 这个方法,重用性不高
public static function httpPost($url,$data, $timeout = 30) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_HEADER, 0);//返回数据不包含头信息 curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);//刷新链接 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//POST提交的数据 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'TEST PHP5 Client 1.1 (curl) ' . phpversion()); $result = curl_exec($ch); $err = curl_error ( $ch ); if (false === $result || !empty ( $err )) { $errno = curl_errno ( $ch ); $info = curl_getinfo ( $ch ); curl_close ( $ch ); return array ( 'result' => $result, 'errno' => $errno, 'msg' => $err, 'info' => $info ); } curl_close($ch); return $result; }
建议这个方法放在RequestHelper请求类中,发送请求应该是请求类的职责
再看以下函数
public static function saveFile($originalName = false) { //uploadType上传类型,0为上传至服务本地,1为上传到图片域服务器 $uploadType = 0; $data = array(); if (!self::$init || !is_uploaded_file(self::$file['tmp_name'])) { return false; } $filename = md5(uniqid(rand(100000, 999999))); $levelpath = self::makeLevelPath($filename); $extension = self::getFileExt(); if (!$levelpath) { return false; } /** * 上传类型名判断 */ if(!preg_match("#jpg|jpeg|png|gif|xls|zip|rar|bmp|xlsx#i", $extension)){ return false; } if(preg_match("#jpg|jpeg|png|bmp|gif#i", $extension)){ $uploadType = 1; } // 如果上传原名 if($originalName) { $filename = $filename . '-' . self::getOrgName(); } else { $filename = $filename . ($extension ? '.' . $extension : ''); } $relative = $levelpath . '/' . $filename; $absolute = self::$path . '/' . $relative; if($uploadType == 0){ if (move_uploaded_file(self::$file['tmp_name'], $absolute)) { file_put_contents(BASE_PATH . "/upload_log/".date("Ymd").".log", date("Y-m-d H:i:s", time()).", add, $absolute", FILE_APPEND); return array( 'absolute' => $absolute, 'relative' => $relative, ); } }else if($uploadType == 1){ if(self::$_isSplit){ $source = 0; $imgArr = getimagesize(self::$file['tmp_name']); $ext = end($imgArr); if(preg_match("#png#i", $ext)){ $source = imagecreatefrompng(self::$file['tmp_name']); }else if(preg_match("#jpg|jpeg#i", $ext)){ $source = imagecreatefromjpeg(self::$file['tmp_name']); } $width = imagesx($source); $height = imagesy($source); $tmp = 0; $pics = array(); $data['width'] = $width; $data['height'] = $height; // 剪裁 $num = floor($height/200); $data['average_height'] = (double)number_format($height/$num, 2); $start_x = $start_y = 0; for ($i=0; $i < $num; $i++) { $croped=imagecreatetruecolor($width, $data['average_height']); imagecopy($croped,$source,0,0,$start_x,$start_y,$width,$data['average_height']); exec("mkdir -p " . BASE_PATH . Load::config('base', 'split_pic')); imagejpeg($croped, BASE_PATH . Load::config('base', 'split_pic') . "split_".$i.$filename); imagedestroy($croped); $tmp += $data['average_height']; $start_y = $tmp; $pics[] = BASE_PATH . Load::config('base', 'split_pic') . "split_".$i.$filename; } $post_url = IMG_SERVER_URL; foreach ($pics as $key => $value) { $post_data = array( 'domain'=>IMG_SERVER_DOMAIN, 'apikey'=>IMG_SERVER_AIPKEY, 'desc' => '', 'filename' => $filename, 'tag' => '', 'usage' => 'touch', 'replaceable' => '1', 'md5' => '', //php5.3版本使用 'imgfile' => '@' . $value //php5.5版本使用 //"imgfile" =>new \CURLFile(realpath($value)) ); $res = self::httpPost($post_url,$post_data); $res = json_decode($res, true); $data['imgs'][] = $res['url']; } $post_data = array( 'domain'=>IMG_SERVER_DOMAIN, 'apikey'=>IMG_SERVER_AIPKEY, 'desc' => '', 'filename' => $filename, 'tag' => '', 'usage' => 'touch', 'replaceable' => '1', 'md5' => '', //php5.3版本使用 'imgfile' => '@' . self::$file['tmp_name'] //php5.5版本使用 //"imgfile" =>new \CURLFile(realpath(self::$file['tmp_name'])) ); $res = self::httpPost($post_url,$post_data); $res = json_decode($res, true); $data['source'] = $res['url']; return $data; }else{ $post_url = IMG_SERVER_URL; $post_data = array( 'domain'=>IMG_SERVER_DOMAIN, 'apikey'=>IMG_SERVER_AIPKEY, 'desc' => '', 'filename' => $filename, 'tag' => '', 'usage' => 'touch', 'replaceable' => '1', 'md5' => '', //php5.3版本使用 'imgfile' => '@' . self::$file['tmp_name'] //php5.5版本使用 //"imgfile" =>new \CURLFile(realpath(self::$file['tmp_name'])) ); $res = self::httpPost($post_url,$post_data); $res = json_decode($res, true); return array( 'absolute' => $res['url'], 'relative' => $res['url'], ); } } return false; }
函数太长,阅读性差,在重构:改善既有代码的设计书中 是建议函数中的代码行数原则上不要多于100行,至少其中的图片切割应该提取出单独函数,而且代码编写未达到性能最大化,有些变量在if中需要,在else中并不需要,造成了多余的计算,类似的代码在整个项目中很多地方存在。
5.附录
1. nginx的配置、虚拟主机、负载均衡和反向代理 https://www.zybuluo.com/phper/note/89391
2. git 操作 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
3. 重构:改善既有代码的设计书 http://www.linuxidc.com/Linux/2014-08/105065.htm
- vip 模块串讲
- DM8168 HDVPSS的VIP Parser模块(1)
- DM8168 HDVPSS的VIP Parser模块(2)
- DM8168 HDVPSS的VIP Parser模块(3)
- DM8168 HDVPSS的VIP Parser模块(4)
- DM8168 HDVPSS的VIP Parser模块(5)
- 江中游VIP模块独立实战教学
- vip
- VIP
- Oracle串讲
- CMMI串讲
- 业务串讲
- 串讲2
- 框架串讲
- 串讲笔记:Hook
- 线程_IO串讲
- 学位考试串讲材料
- 网络管理员考试串讲视频教程
- 模块,AMD,require笔记
- Android动画中的一些知识点的总结
- iOS10 权限崩溃
- HTML5-嵌入内容
- 每天一个linux命令(9):touch 命令
- vip 模块串讲
- vim格式化代码
- [LeetCode] Ransom Note (java)
- 最长公共子串基本介绍
- Toast使用小技巧
- C++ 常量类型 const 详解
- JavaScript强化教程 —— Cocos2d-JS的屏幕适配方案
- Mysql: 利用Xtrabackup搭建从库
- Android 上Camera分析