http到https的过渡

最近https有点火,搜索一下“运商商 流劫持持”,应该能看到好多运营商向网页中强制插入广告的新闻,运营商能这做一是因为流量都要从运营商过路,二是因为http传输的是明文。如果换成https传输数据,数据的安全性可以提高一个档次。

看下文之前请先看《https的使用注意事项》

http到https的切换,道理是很简单的,主要是修改对网址的解析(包括主域名和资源文件的CDN),项目里把“http://”改为“https://”或“//”(自适应协议)。下面是比较详细的改造过程:

1、改配置文件。
配置文件一般存放了项目域名、资源文件域名,所以第一步从这里下手改。
如果开启了https,$_SERVER['HTTPS']非空,一般为on(非https时,在IIS上使用ISAPI方式,该值为off)。
所以,判断是否是https访问的判断条件是 $_SERVER['HTTPS']=='on',我们用 $protocal 表示当前协议,然后把配置里的 http:// 改成 $protocal 。

2、修改项目中的绝对路径。
主要关注几个,jquery路径,二维码路径,微信js地址,轮播图地址,轮播图的点击地址,登录页面的地址。

3、外网资源文件。
如果资源文件很少,可以抓取过来放到自己网站。
如果资源文件很多,可以强制跳转到http页面。(百度图片就是强制跳转到http)

4、统计JS。
百度统计、腾讯统计均支持https,CNZZ现在也支持https(以前的cnzz统计代码不支持https)。
量子统计不支持https。

5、切换到https后可能出现的问题。
a.访问出现502错误;
b.网页打不开,加载时间非常长;
首先看是否是cdn解析问题,如果不能快速解决就切换回http。

总结:
刚始始切换后问题很多,主要特点就是“打不开”、“变慢”。多和运维做些沟通,持续优化https的体验。
https不是绝对安全,如果项目牵扯很多,改造起来难度也很大,量力而行。
记得要保证可以随时切回http。

PHP 自动加载总结

自动加载的测试代码

https://github.com/bayuexiong/simple-composer

1. 自动加载

php的加载文件,一般分为三种情况

  1. 直接include/require,不属于自动加载,一般用于PHP5以前的版本。
  2. 使用__autoload(),PHP5.0引入,在PHP5.1.12之后不再推荐使用。
  3. 使用spl_auoload_register(),现在使用比较多,于PHP5.1.12之后加入,提供了一种更加灵活的方式加载文件。

具体实例

第一种没什么说的。主要还是看第二种和第三种。

假设在一个项目里面有两个文件

Demo.php

class Demo
{
# coding
}

index.php

function __autoload($class_name)
{
$file = dirname(__FILE__) . '/' . $class_name;
if (file_exist($file)) {

include($file);

}

}

$obj = new Demo();

Demo.phpindex.php只要在一个同级目录内,php变会很智能的加载Demo.php,不需要显示的操作。

但是这里还是存在弊端的,比如一个项目中只能有一个__autoload(),这也意味着自动加载的价值变得很低,于是PHP便在PHP5.1.12版本之后添加了spl_autoload_register(),它接受一个回调函数,使得自动加载更加的灵活。

修改index.php

function my_autoload($class_name)

{

$file = dirname(__FILE__) . '/' . $class_name;

if (file_exist($file)) {

include($file);

}

}

spl_autoload_register('my_autoload');

$obj = new Demo();

之前的Demo.php不做修改,将index.php如此修改,便可以同样的功能。

关于spl_autoload_register()更多的内容可以查看官方文档。

http://php.net/manual/zh/function.spl-autoload-register.php

 TIPS
注意类名和文件名必须保持一致!!!

2. Composer

在5.3之后,Composer大行其道,号称PHP未来的希望。。。

使用Composer自动加载时只要引入一个自动加载文件就可以了。

include_once('vendor/autoload.php');

那么Composer的自动加载时怎么实现的呢,其实也是依靠spl_autoload_register()

首先Composer存储三对数组

class=>dir
namespace=>array(dir, dir, dir)
PSR4=>array(dir, dir1, dir2...)

然后在autoload.php, 存在一个loader,可以触发spl_autoload_register,
一旦触发,Composer会对触发的类型进行分析,选择合适的数组,将真实的地址提取出来,然后include,原理还是很简单,推荐大家自行查看一下Composer的自动加载的代码。

关于composer的一个Tips

在上线代码时可以使用composer dump-autoload -o 转换PSR-0/4 autoloadingclassmap 获得更快的载入速度。这特别适用于生产环境,但可能需要一些时间来运行,因此它目前不是默认设置。至于为什么,看完源代码就清晰了。

3. 简单实现一个Composer自动加载

简单实现ClassMap的自动加载功能

https://github.com/bayuexiong/simple-composer/tree/master/vendor

使用代码和Composer一样。

include 'vendor/autoload.php';

$obj = new Demo('gg');

$obj->sayName();

$obj2 = new Other('aa');

$obj2->sayName();

4. 如何选择自动加载机制

  1. 在程序一开始运行的时候,使用数组,将项目内所有的文件记录下来,实现自动加载(如果使用cache,应该还hold的住),symfony使用这种形式,代码如下。
    https://github.com/symfony/class-loader/blob/master/ClassMapGenerator.php
  2. class名和路径对应,便于查找,但是这样缺乏灵活性,框架的侵入性太强了,代码很受框架的限制,像ThinkPHP,CI就是使用这种形式。
  3. 组合使用,像Laravel就是使用PSR4和symfony的classLoader。

5. CI框架的自动加载

现在公司使用CI框架的情况比较多,所以对CI框架的自动加载做一些详细的介绍。

对于一个普通的CI加载类的方式:

 $this->load->library('myclass');

CI框架的内部是如何运行的呢?首先上个流程图

QQ截图20160314174227

具体的实现可以查看源代码,都在system/core/Loader.php文件下面。

其实CI框架的自动加载并没有借助spl系列的函数,而是直接查找文件的方式来自动加载,这可能与CI框架诞生的年岁有关,在那个时期不失为一种优秀的自动加载方法。

但是现在来说,算不上优秀,其对命名的规范太过苛刻了,效率也谈不上高效,当然CI框架的整体速度还是很快的,毕竟像symfony之流的框架为了实现完全解耦,付出了很多性能上的代价。

Tips

对于一个普通的加载类
$this->load->library($library, $param, $object_name);
1. $library 可以是一个数组key代表需要加载的类,value则是obejct_name。
2. $param 需要一个数组,作于传入构造器中的值
3. $object_name$this->load->model(calss, object_name)中第二个参数一样,加载完之后可以$this->object_name->sayHello()

具体的可以结合CI的文档再加上阅读CI的源代码,的确CI的文档相比其他的框架比较全面,但是一些技巧也没有详尽的介绍。

6. 小结

使用Composer吧!使用RSP4命名空间规范吧!这样各个组件与组件之间,自己的代码和别人的代码都可以无痛的结合,不需要花费额外的精力去处理文件加载的问题。

7. 补充

  1. 命名空间,命名空间提供了一种灵活的效率更高的辅助自动加载的方法。
  2. PSR4 规范命名空间的定义,是最近比较流行的命名空间规范。

材料参考:

  1. https://github.com/qinjx/adv_php_book/blob/master/class_autoload.md
  2. spl_autoload_register
  3. __atuoload

UEditor 独立图片上传功能

一、下载使用ueditor

1、从官网上下载UEditor富文本编辑器

2、学会部署使用ueditor。

二、实现方法

1、在html中放置UEditor编辑器,为了不使独立上传图片功能影响到正常的编辑器,这里要多设置一个UEditor编辑器并且需要隐藏。如下代码,myEditor是正常使用的编辑器,upload_ue为隐藏的编辑器。

<script id="myEditor" type="text/plain"></script>
<script id="upload_ue" type="text/plain" style="display:none"></script>

2、实例化编辑器,并侦听图片上传,实现图片预览

<script type="text/javascript">
    var _editor;
    $(function() {
        //实例化一个编辑器,防止在上面的editor编辑器中显示上传的图片或者文件
        _editor = UE.getEditor('upload_ue');
        _editor.ready(function () {
            //侦听图片上传
            _editor.addListener('beforeInsertImage', function (t, arg) {
                //单图预览
                $("#pic_lsit").attr("src", arg[0].src); 
                //多图预览
                for (var i = 0; i < arg.length; i++) {
                    $("#pic_list").append('<div id="photos'+i+'" style="float:left;"><input type="hidden" name="photos[]" value="'+arg[i].src+'" /><img src="'+arg[i].src+'" width="150" height="150" /><a onclick="removePhoto('+i+')">删除</a></div>');
                }
            });
        });
    });
</script>

ps:实例化编辑器之后,一定要确保编辑器上传图片功能能够实现。

3、添加一个按钮,并绑定onclick事件,用于触发编辑器中的上传图片功能。

<button onclick="upImage()">上传图片</button>
<script>
function upImage() {
    var myImage = _editor.getDialog("insertimage");
    myImage.open();
}
</script>

三、参数配置

1、在/ueditor/php/config.json中修改相关配置

/* 上传图片配置项 */
"imageActionName": "uploadimage", /* 执行上传图片的action名称 */
"imageFieldName": "upfile", /* 提交的图片表单名称 */
"imageMaxSize": 2048000, /* 上传大小限制,单位B */
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
"imageCompressEnable": true, /* 是否压缩图片,默认是true */
"imageCompressBorder": 1600, /* 图片压缩最长边限制 */
"imageInsertAlign": "none", /* 插入的图片浮动方式 */
"imageUrlPrefix": "", /* 图片访问路径前缀 */
"imagePathFormat": "/test2/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */

下载测试代码ueditor 独立图片上传

HHuploadify(基于Huploadify)的文件上传插件

整  理:雷  媛
时  间:2016-02-05
说  明: 上传图片的插件

一、简介

基于Huploadify(基于uploadify)的图片上传插件,自动上传,上传进度条,上传后预览

 二、安装

获取代码:下载HHuploadify的源代码。

网页中引入jquery和css

<script src="jquery-2.2.0.min.js"></script>
<script src="jquery.HHuploadify.js"></script>
<link rel="stylesheet" href="HHuploadify.css"> 
备注:可以在HHuploadify.css中对HHuploadify的样式进行修改。

三、使用方法:

 3.1  上传多张(一组)图片

demo:
<div id="upload"></div>
<script>
 $('#upload').HHuploadify({
        fileTypeExts:'*.jpg;*.png;*.gift',//允许上传的文件类型
        uploader:'sub/upload_sub.php' // 必须的,必须指定用来处理上传逻辑的后端处理URL
    });
</script>
点击按钮之后可以多选多张图片,每张图片会各自提交到upload_sub.php。这里提示一下,uploadify本身就是一张一张图片提交的,而不是所有图片一起提交。upload_sub .php可以是你自己的URL,在这个URL进行图片处理和保存,并且返回一个包含url字段的json字符串,通过这个url字段让上传区域展示图片。

3.2  单张图片上传

在上面的代码中,只需要加入一个isSingle参数即可:
demo:
<div id="upload"></div>
<script>
    $('#upload').HHuploadify({
        fileTypeExts:'*.jpg;*.png;*.gift',
        isSingle:true,
        uploader:'sub/upload_sub.php '// 必须的,必须指定用来处理上传逻辑的后端处理URL
    });
</script>
多张图片上传的时候,无论你上传了多少张图片,末尾都会存在选择图片的按钮,你还可以继续上传。而单张图片上传时,选择图片时只能选择一张,选择好之后就进入上传状态,按钮消失,不能继续选择图片进行上传。

四、初始化参数
js中默认的参数如下所示:
fileTypeExts:'*.*',//允许上传的文件类型,格式'*.jpg;*.doc'
uploader:'',//文件提交的地址
auto:true,//是否开启自动上传
method:'post',//发送请求的方式,get或post
multi:true,//是否允许选择多个文件
isSingle:false,// 是否是单个文件上传,如果是单个文件上传,选择文件后,上传按钮会消失,multi也会被强制设定为false
formData:null,//发送给服务端的参数,格式:{key1:value1,key2:value2}
fileObjName:'file',//在后端接受文件的参数名称,如PHP中的$_FILES['file']
fileSizeLimit:2048,//允许上传的文件大小,单位KB
showUploadedFilename:false,//是否显示上传文件名
showUploadedPercent:false,//是否实时显示上传的百分比,如20%
showUploadedSize:false,//是否实时显示已上传的文件大小,如1M/2M
buttonText:'选择文件',//上传按钮上的文字
itemTitle:false,// 该上传item区域的标题:该值将作为上传按钮的提示语,上传时,会显示在左上角,注意,每一个上传区都会有,所以尽可能再isSingle=true的情况下使用
removeTimeout: 1000,//上传完成后进度条的消失时间,单位毫秒
itemTemplate:itemTemp,//上传队列显示的模板
onUploadStart:null,//上传开始时的动作
onUploadSuccess:null,//上传成功的动作
onUploadComplete:null,//上传完成的动作
onUploadError:null, //上传失败的动作
onInit:null,//初始化时的动作
onCancel:null,//删除掉某个文件后的回调函数,可传入参数file
onClearQueue:null,//清空上传队列后的回调函数,在调用cancel并传入参数*时触发
onDestroy:null,//在调用destroy方法时触发
onSelect:null,//选择文件后的回调函数,可传入参数file
onQueueComplete:null//队列中的所有文件上传完成后触发
若是想要更改初始化参数,可在jquery.HHuploadify.js中修改,也可以在上述demo中的js中引用HHuploadify的时候修改,例如:
<script>
 $('#upload').HHuploadify({
     auto:true,
     fileTypeExts:'*.jpg;*.png;*.gift;*.doc',//允许上传的文件类型 
     isSingle : true,//上传一张图片图片
     fileSizeLimit:300,//图片最大300KB
     showUploadedSize:true,//实时显示已上传的文件大小,如1M/2M
     method:'post',//发送请求的方式,get或post
     formData: {item_id: <?php echo $item_id;?>},//传递到sub端的参数 
     uploader:'sub/upload_sub.php',
     onUploadComplete:function(file,data) {
         alert('图片上传成功'),
    }

});
</script>

继续阅读HHuploadify(基于Huploadify)的文件上传插件

关于ip的那些事


编	写:袁	亮
时	间:2014-05-20
说	明:关于ip的那些事

一、ip传递过程
	1、【真实客户端】 ==> [多级代理服务器] ==> [CDN加速] ==> [前端代理nginx|squid] ==> 【apache】==> 【PHP】
	2、中文括号的是必然会经过的,英文括号是可能经过的
	3、标准的ip传递是REMOTE_ADDR和HTTP_X_FORWARDED_FOR,前一个跟当前服务连接的真实ip,后一个是请求到前一个ip之前,经过了哪些代理
	4、REMOTE_ADDR是不可伪造的,HTTP_X_FORWARDED_FOR是可以任意修改的
	5、按标准,每传递到下一层,都会将上一层的实际ip地址加入到HTTP_X_FORWARDED_FOR中,继续传递
	6、对每一层来说,只有上一层的时间地址是可信的(REMOTE_ADDR),HTTP_X_FORWARDED_FOR均有风险
	7、真实情况中,到了cdn或者前端代理之后,ip传递都是可信的(我们自己可控制),之前的都有篡改的危险

二、各服务的真实ip传递情况
	1、CDN 快网的cdn会将用户的实际地址或者代理服务器地址传递到后面的服务中
		$_SERVER["HTTP_USER_IP"]	【不用快网的时候可伪造】
		$_SERVER["HTTP_FW_ADDR"]	【不用快网的时候可伪造】
		测试了一个新的cdn测试,没有传递真实ip过来

	2、nginx代理的情况下,可以使用x_real_ip来获取真实ip(有cdn的时候,该值获取的是cdn的ip地址)
		$_SERVER["HTTP_X_REAL_IP"]	【不用nginx的时候可伪造】

	3、$_SERVER["HTTP_CLIENT_IP"] :代理服务器发送的客户端真实ip【可伪造】

三、现在使用的获取ip函数
	a、如果有HTTP_CLIENT_IP,则该ip为用户ip(可被伪造)
	b、如果有HTTP_X_FORWARDED_FOR,则将HTTP_CLIENT_IP也加入到HTTP_X_FORWARDED_FOR,判断HTTP_X_FORWARDED_FOR中的ip是否是内网的,取第一个非内网的ip为客户端真实ip
	c、经过以上两步还没有取到ip的话,则根据REMOTE_ADDR取用户的ip
	ps:该函数的问题在于,前面两个的ip都是可以被任意伪造改写,从而导致获取不到用户的真实ip情况

四、附:(线上使用的获取ip函数)
function getIp(){//获取IP函数
        $ip = false;
        if(!empty($_SERVER["HTTP_CLIENT_IP"])){
                $ip = $_SERVER["HTTP_CLIENT_IP"];
        }
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $ips = explode (", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
                if ($ip) {
                        array_unshift($ips, $ip);
                        $ip = FALSE;
                }
                for ($i = 0; $i < count($ips); $i++) {
                        if (!preg_match("/^(10|172\.16|192\.168)\./", $ips[$i])) { // 判断是否内网的IP
                                $ip = $ips[$i];
                                break;
                        }
                }
        }
        return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}



http 1.1 和 http1.0 主要区别


编	写:袁	亮
时	间:2016-01-12
说	明:http 1.1 和 http1.0 主要区别

一、持久链接keep-alive
	1、标准的1.0版本中,每次请求都必须重新建立连接、传输数据、关闭连接
		但有些http服务和浏览器也实现了Connection: Keep-Alive的功能
	2、在1.1版本,默认就是Connection: Keep-Alive
		可以在同一次TCP连接中,多次传输数据
		减少了重新建立连接的开销,特别是当一个网页中有很多图片、js、css等的时候会非常有用
		但这也有可能会导致TCP一直不释放,从而影响性能,需要权衡设置
		
二、增加了HOST
	1、在1.0版本中,不支持HOST,同一ip同一端口,只能供一个服务使用
	2、1.1版本中,支持HOST来创建虚拟主机

三、带宽优化
	1、1.1版本中,增加了RANGE头来实现断点续传,从而防止下载中断之后又要全部重新上传
	2、增加压缩,通过Accept-Encoding头来实现,减少数据传输

四、其他
	1、缓存策略
	2、新增http状态码
	3、身份认证、状态管理
	4、我们服务器上有些apache还是返回http 1.0,感觉不大正常
	
		
附:参考文档
1、http://blog.csdn.net/elifefly/article/details/3964766
2、http://www.cnblogs.com/qqzy168/p/3141849.html
3、http://www.cnblogs.com/huangfox/archive/2012/03/31/2426341.html
4、http://www.360doc.com/content/14/0730/09/1073512_398058058.shtml

xhprof实际使用过程中的一些注意事项


编	写:袁	亮
时	间:2016-01-12
说	明:xhprof实际使用过程中的一些注意事项

一、扩展安装
	1、前置说明
		1.1 这个组件作为性能分析工具,测试环境有时候不能重现问题
		1.2 直接在生产环境安装,容易导致当前服务受影响或者不可用
		1.3 开启对性能也有一定影响,特别是大流量的情况下,直接全部开始,那就悲剧了
	2、分流开启(成本适中、危险性低)
		2.1 采用nginx分流,使一小部分流量请求发送到安装了xhprof的服务上
		2.2 安装的那台服务器,可用开启监控,并跟生产环境对比
		2.3 既可以达到采集到实际数据,也不影响大部分的用户和业务
	3、流量复制(成本较高,基本无危险)
		3.1 将正式环境的流量复制到测试机上,开启监控查看
		3.2 优点是对原业务几乎无影响,也方便进行流量放大,做压力测试等
		3.3 缺点是之前没做过,略有点麻烦

二、程序开启并记录
	ps:下载http://pecl.php.net/get/xhprof-0.9.2.tgz,参考其中的example/example.php的写法
	
	1、开启监控
		xhprof_enable();
		ps:只在需要的地方开,不要全部开,或者以一定概率开启	
	2、停止监控采集
		$xhprof_data = xhprof_disable();
	3、采集监控数据
		$XHPROF_ROOT = realpath(dirname(__FILE__) .'/..');
		include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
		include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
		$xhprof_runs = new XHProfRuns_Default('可以保存到自己定义的文件夹中,未设置则采用php中的默认设置');
	4、保存监控数据
		$run_id = $xhprof_runs->save_run($xhprof_data, "保存数据的后缀,作为同一项目的区分用");
		ps:可以将数据保存在一个挂载盘中,这样可以在一台统一的服务器上统一查看调用

	ps:后期也可以考虑自动化,针对慢的请求,直接在php配置中auto_prepend_file增加一段监控程序,按一定比例采样,并汇总分析
	
三、显示性能分析
	1、可以在任意一台能访问存储的监控数据的地方
	2、复制下载文件中的xhprof_html文件夹,并放在可web访问的地方
	3、通过保存时候生成的run_id和自己设置的后缀,即可访问
	4、重点关注callgraph.php,生成的调用链接,主要耗时的调用链有非常明显的颜色标注出来,一眼就能看到性能瓶颈在哪
		ps:这个需要graphviz和graphviz-gd


svn管理流程实践

整 理:吴万利
时 间:2015-01-08
说 明:svn管理流程实践

svn目录结构

trunk 主干:存储最新稳定的版本
tags 标记:主要保存比较完整的版本标记,类似里程碑
branches 分支:用于分工操作,以开发分支、用户名、日期为目录存储

svn工作模式

常用的两种工作模式

基础结构准备

选定trunk为主要开发文件夹
tag为发布版本的地方(可能也有紧急的bug修复,之后要将代码合并回主干)
branch为分支目录(bug修复、模块独立开发等)

现有的文件结构

trunk/ 主要开发的目录

*.php

tag/ 版本发布目录(发布tag一定要标记信息!)

release_1.0 已经发布的一个版本(1版本号,0修订号)

branch/ bug修复,独立模块开发等

问题应对流程

  1. 日常的开发怎么办?
    答:日常可以在trunk里面进行开发,周期不长开发测试完成可以打包出来进行测试。

    • 开发完成之后由管理人员操作打包得到
      http://svnxxx.xxx.com/svn/vshop2_trade_module/tag/release_2.0
    • 在测试机上测试稳定之后就可以准备上线
      上线:可以在对应项目目录下面执行svn switch命令(我的方案)
  2. 线上的项目出现问题怎么办?
    • 紧急而且简单
      1. 直接在release里面修改(其实不推荐,而且测试机的配置,同样用switch命令?),然后测试提交,在线上更新。
      2. 通知trunk、branch里面的dev进行merge(merge前提交所有改动!)
    • 不紧急而且较复杂
      1. 在branch里面copy一个release_1.0版本为dev_1.0_bugfix进行修改
      2. 测试通过之后发布为tags/patch_1.1 通知trunk等进行合并操作
  3. 开发新的独立模块怎么办?
    答:可以考虑在branch下复制一个当前稳定版本的dev_2.0_yilucaifu出来进行修改,测试完成之后可以独立上线,但是不要忘记合并。

情景模拟

0. 情景准备

svn仓库结构:

branches
tags

release_1.0

trunk

服务器上代码结构:

正式版

tvshop2_online(svn:tags/release_1.0)

测试机

tvshop2_online_dev(svn:trunk)

1. 上线的东西出问题,需要调试

  1. 对于tag版本出一个bugfix分支

    svn cp
    http://svnxxx.xxxx.com/svn/tvshop2/tags/release_1.0http://svnxxx.xxxx.com/svn/tvshop2/branches/dev_1.0_bugfix
    -m '1.0bug修复'

  2. 测试版切换到分支

    tvshop2_online_dev:
    svn switch http://svnxxx.xxxx.com/svn/tvshop2/branches/dev_1.0_bugfix

  3. 测试版debug,测试提交

    tvshop2_online_dev:
    svn ci -m 'debug message'

  4. 发布一个新的版本

    svn cp
    http://svnxxx.xxxx.com/svn/tvshop2/branches/dev_1.0_bugfixhttp://svnxxx.xxxx.com/svn/tvshop2/tags/patch_1.1
    -m 'bug修复'

  5. 改动上线

    tvshop2_online:
    svn switch http://svnxxx.xxxx.com/svn/tvshop2/tags/patch_1.1

  6. 清理无用分支dev_1.0_bugfix

    svn del http://svnxxx.xxxx.com/svn/tvshop2/branches/dev_1.0_bugfix -m '已经上线'

  7. 合并改动到主分支
    tip:一般线上的紧急调试都不会太大,所以合并一般问题都不会很多

    1. 切换测试机为主分支
      tvshop2_online_dev:
      svn switch http://svnxxx.xxxx.com/svn/tvshop2/trunk
    2. 合并改动到主分支(推荐在windows下用工具辅助做)
      svn merge http://svnxxx.xxxx.com/svn/tvshop2/tags/patch_1.1/ ./
    3. 下次提交将改动一起提交即可

2. 新的模块的开发

  1. 开发之前先大致确定一下可能的改动,是否跟原来的开发改动了同一块地方。
  2. 对于需要共同修改的地方在合并的时候必须小心处理,可以跟原来的开发一起查看改动是否合理。

3. 优点:

  1. 线上代码稳定,可靠性高(除非有人故意删除release)
  2. 回退方便,能够很清楚的知道上个版本是哪个

4. 缺点:

  1. 操作复杂,繁琐,比较容易搞混当前的版本是哪个
  2. merge回当前开发分支的时候可能会引起冲突(无法避免)
  3. 线上如果有人修改可能会引起树冲突,所以切换之前需要提交所有改动

5. 原则总结:

  1. 在执行switch的之前一定要提交所有的改动。
  2. 每次发布新版本之后其他分支需要从trunk上merge来获取最新的版本(冲突的话需要协商解决)。

仓库迁移记录

  1. 准备好即将使用的svn仓库
  2. 在线上先co出两个文件夹备用(svnshop2+svnshop2_dev)
  3. 将线上的代码export一份作为一个基础版本,并发布一个tag(release_1.0)
  4. 将本地开发的所有改动提交到之前的仓库
  5. 将之前的仓库文件导入到现在的svn里面的trunk中
  6. 在线上测试机co trunk,测试各项功能是否ok(测试一起购、一路财富改动都没有问题)
  7. 以后上线:trunk发布新的tag,线上执行switch操作(确保线上svn里面的文件没有M状态!)

可能的问题

  1. crontab怎么办?(直接在服务器上做的alias,没有影响原结构)
  2. 静态文件上线?(只能针对静态文件单独做合并、上线)
  3. 以后数据库的改动怎么同步?

 

VIM PHP IDE的安装步骤

前言

操作文档的链接

文件包所在

\\192.168.0.18\运维网络硬盘\y袁亮\vim-php-ide
  • php-vim-fool.tgz是fool式安装
  • php-vim-full.tgz是full式安装

其实就是相差一个YCM插件,YCM插件需要clang编译,所以比较烦。

FOOL安装

最好要求php5.3.9以上版本,也最好安装php-xml

yum install php-xml

关于自动补全

  • 最好,也至少安装一下ctags不然很多东西用不起了。
  • yum install ctags
  • 如果没有权限安装,那也只能作罢。

fool版的代价是不太友好的自动补全,当然也没有路径补全了=_=

安装步骤:

  • 使用winscpphp-vim-fool.tgz上传到工作用户目录下。
  • 执行指令tar xzvf php-vim-fool.tgz -C ~/
  • 然后就ok了

关于配置文件

  • 位置在~/.vimrc
  • 打开vim ~/.vimrc,先使用zM折叠所有方便查找,za单独打开和关闭折叠。

full安装(其实就是自动补全的差距)

需要安装的外部依赖:

  • git是必须的yum install git
  • gcc gcc-c++ yum install gcc gcc-c++
  • clang 
    • 先添加epel源, yum install epel-release
    • yum install clang
  • python-devel yum install python-devel
  • cmake yum install cmake
  • ctags yum install ctags
  • 可能需要php5.3.9以上的版本,不然需要关闭phpmd检查

安装vim-php

  • 使用winscpphp-vim-full.tgz上传到工作用户的目录下,即~/下面,github太慢,还是直接压缩包来得好。
  • tar xzvf php-vim-full.tgz -C ~/
  • vim ~/.vimrc 查看有没有报错(一般没有),然后:PluginUpdate,时间可能有点久,这不是必要的,可以直接下一步。
  • 进入~/.vim/bundle/YouCompleteMe/, 执行./install.py编译一下,可能比较久。 
    • 提示缺少argparse 安装pip install argparse
    • 如果没有pip,安装yum install python-pip
  • 如果编译失败,请查看依赖有没有安装成功
  • 安装成功后可以在vim下键入:PluginUpdate vim-shippets更新模块。

VIM PHP IDE的基本操作

前言

 安装步骤的链接

关于安装步骤:

  • 分full和fool两个版本,版本差距在自动补全的插件。
  • 最好安装ctags,如果不安装ctags自动补全将不完善,tagbar也无法工作。
  • 可以考虑一下vim的练级攻略

语法检查

文件在保存时会检查语法错误和规范

一共有三种警告:

  • p> php的语法错误, 可以使用:Php主动检查
  • s> 不符合prs2规范, 可以使用:Phpcs主动检查
  • m> 质量检验, 可以使用:Phpmd主动检查

格式修复

vim-php-cs-fixer

nnoremap <silent><F7> :call PhpCsFixerFixDirectory()<CR>
nnoremap <silent><F8> :call PhpCsFixerFixFile()<CR>

F8可以修复一些不符合psr2的规范,但是存在一些问题,如果只是定义了函数名或是类名的一些没有实际作用的代码可能会被删除,安全性有待评估。

自动补全

YCM

full基本操作:

  • 两个字符后开始自动补全
  • tab键选择,shift-tab逆向选择
  • 可以使用ctrl-n向下,或是ctrl-p向上选择

如果是fool版:

  • 不能自动开启补全,不能像图中那样方便。
  • 必须使用<ctrl-x><ctrl-o>开启补全
  • ctrl-nctrl-p无法选择, tab可以使用
  • 其他相同

一般只支持系统函数补全,如果要支持自己编写的函数补全,需要如此:

  1. 在项目顶层目录下执行指令 ctags -R
  2. 必需在项目顶层目录,即ctags文件所在的目录打开vim
  3. 打开文件,不要退出vim,使用NERDTreectrl-p查找和打开文件,如果需要创建文件,可以使用ctrl-p打开文件。
  4. 如果创建了新的类,将必须在项目顶层目录执行ctags -R的指令,当然可以在vim执行:!ctags -R,在不退出vim的情况下更新ctags文件

可以通过tags来实现require的补全

对于composer的补全,默认composer是全局安装的,好像失败了。

代码块

u

已经将php的模板文件软连接到用户主目录下,可以自行查看修改 
vim ~/php.shippets

?-tab 可以生成这样的代码 <?php ?>

f-tab可以生成这样的代码

function ()
{

}

pub-tab可以生成

/*
 * undocumented function
 * @return void
 * /
public function name($param)
{
    return null;
}

c-tab

class filename
{

}

class-tab可以生成一个带注释的class

文件目录和代码浏览

NERDTree 
NERDTree

F2 打开文件目录 
在NERDTree中按?呼出帮助文档

tagbar

需要安装ctags 
tagbar
F3 打开代码浏览

模糊搜索

ctrl-p 
ctrl-p
基本不需要设置

ctrl-p 打开模糊搜索

ctrl-k  ctrl-j 可以在搜索结果中上下选择 
ctrl-t 在新标签页打开 
ctrl-v 分割打开 
ctrl-y 新建文件, 需要先敲入路径和文件名

html tag跳转

在一个html tag上使用%可以跳转与之匹配的tag

官方文档

将光标移动到需要查看的函数上,使用shift-k,就可以查看官方文档a。

符号补全

在使用', ", (, [, {时,会自动补全另一半,同时如果再按各个匹配的另一半,则会跳出。

 

全局搜索

可以使用命令

:CtrlSF param

也可以设置

nmap <leader><leader>f <Plug>CtrlSFPrompt

<leader>默认是\,所以快捷就是 \\f

因为是全局搜索,所以不要在太顶层目录使用,具体请查看CtrlSF

多光标

ctrl-n 开启选择/选择下一个 
下面操作需要在ctrl-n执行后 
ctrl-p 取消一个选择 
ctrl-x 跳过一个选择 
详细vim-multiple-cursor

PS: 可以通过结合全局搜索实现重构

注释

\cc 注释当前行 
\cu 反注释当前行 
可以通过shift-v实现多行操作

撤销树

此处输入图片的描述 
gundo

F4呼出撤销树,查看之前的撤销修改

其它一些插件

php.vim

更好的代码高亮

PHP-Indenting-for-vim

在php 和 html代码混杂在一起时提供更好的缩进

vim-airline

状态栏美化

vim-trailing-whitespace

显示多余的空格