XlsxWriter的使用

1.优点

一、功能比较强

相对而言,这是除Excel自身之外功能最强的工具了。比如我就用到了它提供的:字体设置、前景色背景色、border设置、视图缩放(zoom)、单元格合并、autofilter、freeze panes、公式、data validation、单元格注释、行高和列宽设置等等。

二、支持大文件写入

如果数据量非常大,可以启用constant memory模式,这是一种顺序写入模式,得到一行数据就立刻写入一行,而不会把所有的数据都保持在内存中。

2.缺点

一、不支持读取和修改

作者并没有打算做一个XlsxReader来提供读取操作。不能读取,也就无从修改了。它只能用来创建新的文件。我是利用xlrd把需要的信息读入后,用XlsxWriter创建全新的文件。

另外,即使是创建到一半Excel文件,也是无法读取已经创建出来的内容的(信息应该在,但是并没有相应的接口)。因为它的主要方法是write而不是set。当你在某个单元格写入数据后,除非你自己保存了相关的内容,否则还是没有办法读出已经写入的信息。从这个角度看,你无法做到读出->修改->写回,只能是写入->写入->写入。

二、不支持XLS文件

XLS是Office 2013或更早版本所使用的格式,是一种二进制格式的文件。XLSX则是用一系列XML文件组成的(最后的X代表了XML)一个压缩包。如果非要创建低版本的XLS文件,就请移步xlwt吧。

三、暂时不支持透视表(Pivot Table

3.基本操作方法

  • 创建excel文件
import xlsxwriter

f = xlsxwriter.Workbook()    # 创建excel文件

  • 创建工作表
worksheet1 = f.add_worksheet('操作日志')  # 括号内为工作表表名

  • 添加工作表样式

样式有很多属性,更多具体样式请参考官方文档。

bold = f.add_format({
        'bold':  True,  # 字体加粗
        'border': 1,  # 单元格边框宽度
        'align': 'left',  # 水平对齐方式
        'valign': 'vcenter',  # 垂直对齐方式
        'fg_color': '#F4B084',  # 单元格背景颜色
        'text_wrap': True,  # 是否自动换行
    })

  • 写入单个单元格数据
//row:行, col:列, data:要写入的数据, bold:单元格的样式
worksheet1.write(row, col, data, bold)

  • 写入一整行,一整列
// A1:从A1单元格开始插入数据,按行插入, data:要写入的数据(格式为一个列表), bold:单元格的样式
worksheet1.write_row(“A1”,data,bold)

// A1:从A1单元格开始插入数据,按列插入, data:要写入的数据(格式为一个列表), bold:单元格的样式
worksheet1.write_column(“A1”,data,bold)

  • 插入图片
// 第一个参数是插入的起始单元格,第二个参数是图片你文件的绝对路径
worksheet1.insert_image('A1','f:\\1.jpg')

  • 写入超链接
worksheet1.write_url(row, col, "internal:%s!A1" % ("要关联的工作表表名"), string="超链接显示的名字")

  • 插入图表
workbook.add_chartsheet(type="")

参数中的type指的是图表类型,图表类型示例如下:
[area:面积图,bar:条形图,column:直方图,doughnut:环状图,line:折线图,pie:饼状图,scatter:散点图,radar:雷达图,stock:箱线图]

  • 获得当前excel文件的所有工作表
workbook.worksheets()

workbook.worksheets()用于获得当前工作簿中的所有工作表,这个函数的存在便利了对于工作表的循环操作,如果你想在当前工作簿的所有工作表的A1单元格中输入一个字符创‘Hello xlsxwriter’,那么这个命令就派上用场了。

  • 关闭excel文件
workbook.close()

这个命令是使用xlsxwriter操作Excel的最后一条命令,一定要记得关闭文件。

Mac下配置PHP+Nginx+Redis环境

Mac下是自己安装了Apache+PHP的,但是Mac OS版本每次变更后都需要重新配置下环境,参考:Mac升级系统macOS Sierra后PHP不编译

1.安装Homebrew

Mac没有预装 Homebrew,安装Homebrew 在终端执行:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

如果提示安装xcode命令行工具,在App Store中下载最新Xcode,然后根据提示安装xcode命令行工具,终端输入:

xcode-select --install

成功后继续安装Homebrew

2.安装Nginx

成功安装brew后,在终端执行:

brew install nginx

安装成功后,查看nginx信息,在终端执行:

brew info nginx

以下为提示信息:
nginx: stable 1.12.2 (bottled), devel 1.13.6, HEAD
...
...
Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx now and restart at login:
  brew services start nginx
Or, if you don't want/need a background service you can just run:
  nginx

Mac是自带Apache的,和Nginx会冲突吗?答案是不会,因为默认端口不同,Apache默认80端口,Nginx默认8080端口
ok,终端执行:

sudo nginx

浏览器访问:localhost:8080

Nginx相关命令

//启动 nginx服务
sudo nginx

//重新加载配置|重启|停止|退出 nginx
nginx -s reload|reopen|stop|quit

//测试配置是否有语法错误
nginx -t
3.安装PHP56

macOSX自带PHP,会跟随系统升级,目前macOS v10.13.x 跟随PHP已经是PHP7.0,所以我们还是需要安装PHP56,执行:

brew install php56 --build-from-source

安装成功,提示:

The php.ini file can be found in:
    /usr/local/etc/php/5.6/php.ini

✩✩✩✩ Extensions ✩✩✩✩

If you are having issues with custom extension compiling, ensure that you are using the brew version, by placing /usr/local/bin before /usr/sbin in your PATH:

      PATH="/usr/local/bin:$PATH"

PHP56 Extensions will always be compiled against this PHP. Please install them using --without-homebrew-php to enable compiling against system PHP.

✩✩✩✩ PHP CLI ✩✩✩✩

If you wish to swap the PHP you use on the command line, you should add the following to ~/.bashrc, ~/.zshrc, ~/.profile or your shell's equivalent configuration file:
  export PATH="$(brew --prefix homebrew/php/php56)/bin:$PATH"

✩✩✩✩ FPM ✩✩✩✩

To launch php-fpm on startup:
    mkdir -p ~/Library/LaunchAgents
    cp /usr/local/opt/php56/homebrew.mxcl.php56.plist ~/Library/LaunchAgents/
    launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php56.plist

The control script is located at /usr/local/opt/php56/sbin/php56-fpm

OS X 10.8 and newer come with php-fpm pre-installed, to ensure you are using the brew version you need to make sure /usr/local/sbin is before /usr/sbin in your PATH:

  PATH="/usr/local/sbin:$PATH"

You may also need to edit the plist to use the correct "UserName".

Please note that the plist was called 'homebrew-php.josegonzalez.php56.plist' in old versions of this formula.

With the release of macOS Sierra the Apache module is now not built by default. If you want to build it on your system you have to install php with the --with-httpd option. See  brew options php56 for more details.

To have launchd start homebrew/php/php56 now and restart at login:
  brew services start homebrew/php/php56

配置php.ini

sudo vim /usr/local/etc/php/5.6/php.ini

设置开机启动php-fpm:

mkdir -p ~/Library/LaunchAgents
cp /usr/local/opt/php56/homebrew.mxcl.php56.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php56.plist

php56-fpm 启动/停止… :

/usr/local/opt/php56/sbin/php56-fpm {start|stop|force-quit|restart|reload|status}

现在我们先执行php56 -v来查看版本要怎么办呢?执行:

sudo ln -s /usr/local/Cellar/php56/5.6.32_8/bin/php /usr/local/bin/php56

设置一下符号链接(相当于windows快捷方式) ,现在php56直接指向了/usr/local/Cellar/php56/5.6.32_8/bin/php 【参考链接】Linux环境变量和符号链接
设置完成,查看PHP版本:

php56 -v
4. 安装Redis

终端执行:

brew search redis

查询结果:
hiredis                       homebrew/php/php56-redis      redis                         redis@3.2
homebrew/php/php53-redis      homebrew/php/php70-redis      redis-leveldb
homebrew/php/php54-redis      homebrew/php/php71-redis      redis@2.6
homebrew/php/php55-redis      homebrew/php/php72-redis      redis@2.8

然后(注意区分下php的redis扩展)

brew install redis
To have launchd start redis now and restart at login:
  brew services start redis
Or, if you don't want/need a background service you can just run:
  redis-server /usr/local/etc/redis.conf

开启redis:

redis-server /usr/local/etc/redis.conf

微信开发服务器返回错误码大全

在微信官方的文档中, 提及的错误码及其说明并不完整, 这里是一个较为完整的错误码.

'-1' => '系统繁忙,此时请开发者稍候再试',
'0' => '请求成功',
'40073' => '不合法的 cardid',
'40009' => '图片文件超长。',
'40013' => '不合法的Appid,请开发者检查AppID的正确性,避免异常字符,注意大小写。',
'40053' => '不合法的actioninfo,请开发者确认参数正确。',
'40071' => '不合法的卡券类型。',
'40072' => '不合法的编码方式。',
'40078' => '不合法的卡券状态。',
'40079' => '不合法的时间。',
'40080' => '不合法的CardExt。',
'40099' => '卡券已被核销。',
'40100' => '不合法的时间区间。',
'40116' => '不合法的Code码。',
'40122' => '不合法的库存数量。',
'40124' => '会员卡设置查过限制的 custom_field字段。',
'40127' => '卡券被用户删除或转赠中。',
'41012' => '缺少cardid参数。',
'45030' => '该cardid无接口权限。',
'45031' => '库存为0。',
'45033' => '用户领取次数超过限制get_limit',
'41011' => '缺少必填字段。',
'45021' => '字段超过长度限制,请参考相应接口的字段说明。',
'40056' => '不合法的Code码。',
'43009' => '自定义SN权限,请前往公众平台申请。',
'43010' => '无储值权限,请前往公众平台申请。',
'40001' => '获取access_token时AppSecret错误',
'40002' => '不合法的凭证类型',
'40003' => '不合法的OpenID',
'40004' => '不合法的媒体文件类型',
'40005' => '不合法的文件类型',
'40006' => '不合法的文件大小',
'40007' => '不合法的媒体文件id',
'40008' => '不合法的消息类型',
'40009' => '不合法的图片文件大小',
'40010' => '不合法的语音文件大小',
'40011' => '不合法的视频文件大小',
'40012' => '不合法的缩略图文件大小',
'40013' => '不合法的AppID',
'40014' => '不合法的access_token',
'40015' => '不合法的菜单类型',
'40016' => '不合法的按钮个数',
'40017' => '不合法的按钮个数',
'40018' => '不合法的按钮名字长度',
'40019' => '不合法的按钮KEY长度',
'40020' => '不合法的按钮URL长度',
'40021' => '不合法的菜单版本号',
'40022' => '不合法的子菜单级数',
'40023' => '不合法的子菜单按钮个数',
'40024' => '不合法的子菜单按钮类型',
'40025' => '不合法的子菜单按钮名字长度',
'40026' => '不合法的子菜单按钮KEY长度',
'40027' => '不合法的子菜单按钮URL长度',
'40028' => '不合法的自定义菜单使用用户',
'40029' => '不合法的oauth_code',
'40030' => '不合法的refresh_token',
'40031' => '不合法的openid列表',
'40032' => '不合法的openid列表长度',
'40033' => '不合法的请求字符,不能包含\uxxxx格式的字符',
'40035' => '不合法的参数',
'40038' => '不合法的请求格式',
'40039' => '不合法的URL长度',
'40050' => '不合法的分组id',
'40051' => '分组名字不合法',
'40097' => '参数不正确,请参考字段要求检查json 字段',
'65104' => '门店的类型不合法,必须严格按照附表的分类填写',
'65105' => '图片url 不合法,必须使用接口1 的图片上传接口所获取的url',
'65106' => '门店状态必须未审核通过',
'65107' => '扩展字段为不允许修改的状态',
'65109' => '门店名为空',
'65110' => '门店所在详细街道地址为空',
'65111' => '门店的电话为空',
'65112' => '门店所在的城市为空',
'65113' => '门店所在的省份为空',
'65114' => '图片列表为空',
'65115' => 'poi_id 不正确',
'40117' => '分组名字不合法',
'40118' => 'media_id大小不合法',
'40119' => 'button类型错误',
'40120' => 'button类型错误',
'40121' => '不合法的media_id类型',
'40132' => '微信号不合法',
'40137' => '不支持的图片格式',
'40155' => '请勿添加其他公众号的主页链接',
'41001' => '缺少access_token参数',
'41002' => '缺少appid参数',
'41003' => '缺少refresh_token参数',
'41004' => '缺少secret参数',
'41005' => '缺少多媒体文件数据',
'41006' => '缺少media_id参数',
'41007' => '缺少子菜单数据',
'41008' => '缺少oauth code',
'41009' => '缺少openid',
'42001' => 'access_token超时',
'42002' => 'refresh_token超时',
'42003' => 'oauth_code超时',
'42007' => '用户需要重新授权',
'43001' => '需要GET请求',
'43002' => '需要POST请求',
'43003' => '需要HTTPS请求',
'43004' => '需要接收者关注',
'43005' => '需要好友关系',
'43019' => '需要将接收者从黑名单中移除',
'44001' => '多媒体文件为空',
'44002' => 'POST的数据包为空',
'44003' => '图文消息内容为空',
'44004' => '文本消息内容为空',
'45001' => '多媒体文件大小超过限制',
'45002' => '消息内容超过限制',
'45003' => '标题字段超过限制',
'45004' => '描述字段超过限制',
'45005' => '链接字段超过限制',
'45006' => '图片链接字段超过限制',
'45007' => '语音播放时间超过限制',
'45008' => '图文消息超过限制',
'45009' => '接口调用超过限制',
'45010' => '创建菜单个数超过限制',
'45011' => 'API调用太频繁,请稍候再试',
'45015' => '回复时间超过限制',
'45016' => '系统分组,不允许修改',
'45017' => '分组名字过长',
'45018' => '分组数量超过上限',
'45047' => '客服接口下行条数超过上限',
'46001' => '不存在媒体数据',
'46002' => '不存在的菜单版本',
'46003' => '不存在的菜单数据',
'46004' => '不存在的用户',
'47001' => '解析JSON/XML内容错误',
'48001' => 'api功能未授权',
'48002' => '粉丝拒收消息',
'48004' => 'api接口被封禁,请登录mp.weixin.qq.com查看详情',
'48005' => 'api禁止删除被自动回复和自定义菜单引用的素材',
'48006' => 'api禁止清零调用次数,因为清零次数达到上限',
'50001' => '用户未授权该api',
'50002' => '用户受限,可能是违规后接口被封禁',
'61451' => '参数错误(invalid parameter)',
'61452' => '无效客服账号(invalid kf_account)',
'61453' => '客服帐号已存在(kf_account exsited)',
'61454' => '客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)',
'61455' => '客服帐号名包含非法字符(仅允许英文+数字)',
'61456' => '客服帐号个数超过限制(10个客服账号)',
'61457' => '无效头像文件类型',
'61450' => '系统错误',
'61500' => '日期格式错误',
'65301' => '不存在此menuid对应的个性化菜单',
'65302' => '没有相应的用户',
'65303' => '没有默认菜单,不能创建个性化菜单',
'65304' => 'MatchRule信息为空',
'65305' => '个性化菜单数量受限',
'65306' => '不支持个性化菜单的帐号',
'65307' => '个性化菜单信息为空',
'65308' => '包含没有响应类型的button',
'65309' => '个性化菜单开关处于关闭状态',
'65310' => '填写了省份或城市信息,国家信息不能为空',
'65311' => '填写了城市信息,省份信息不能为空',
'65312' => '不合法的国家信息',
'65313' => '不合法的省份信息',
'65314' => '不合法的城市信息',
'65316' => '该公众号的菜单设置了过多的域名外跳(最多跳转到3个域名的链接)',
'65317' => '不合法的URL',
'9001001' => 'POST数据参数不合法',
'9001002' => '远端服务不可用',
'9001003' => 'Ticket不合法',
'9001004' => '获取摇周边用户信息失败',
'9001005' => '获取商户信息失败',
'9001006' => '获取OpenID失败',
'9001007' => '上传文件缺失',
'9001008' => '上传素材的文件类型不合法',
'9001009' => '上传素材的文件尺寸不合法',
'9001010' => '上传失败',
'9001020' => '帐号不合法',
'9001021' => '已有设备激活率低于50%,不能新增设备',
'9001022' => '设备申请数不合法,必须为大于0的数字',
'9001023' => '已存在审核中的设备ID申请',
'9001024' => '一次查询设备ID数量不能超过50',
'9001025' => '设备ID不合法',
'9001026' => '页面ID不合法',
'9001027' => '页面参数不合法',
'9001028' => '一次删除页面ID数量不能超过10',
'9001029' => '页面已应用在设备中,请先解除应用关系再删除',
'9001030' => '一次查询页面ID数量不能超过50',
'9001031' => '时间区间不合法',
'9001032' => '保存设备与页面的绑定关系参数错误',
'9001033' => '门店ID不合法',
'9001034' => '设备备注信息过长',
'9001035' => '设备申请参数不合法',
'9001036' => '查询起始值begin不合法',

Yii2 定时任务创建(Console 任务)

Yii2的定时任务可以有两种写法,原理都是通过服务器的定时任务去调用

1.通过调用指定的URL访问 就相当于在浏览器中访问

2.通过console调用

下面我们就来说说Console 是如何实现定时任务的

一、首先在创建Controller 并继承 yii\console\Controller;

 

二、测试是否成功

三、设置定时任务

linux下,运行crontab -e

上面的例子表示每晚的21:30执行上面的定时程序

 

下面是定时任务设置的一些基本介绍

基本格式 :
*  *  *  *  *  command
分 时 日 月 周 命令

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

crontab文件的一些例子:

使用 gitosis 管理 git 服务器

通过apt安装,gitosis使用SSH key来认证用户,但用户不需要在主机上添加账号,而是使用服务器上的一个受限账号。 安装的过程需要在客户端和服务器之间切换,留意操作步骤之前的说明。这里服务器和客户端都是使用ubuntu linux。

服务器端(ip:192.168.1.254)
1. 安装 git
sudo apt-get install git-core

2. 安装  python 和 python-setuptools
sudo apt-get install python python-setuptools

3. 安装gitosis

cd /tmp
sudo git clone https://github.com/tv42/gitosis.git
cd gitosis
sudo python setup.py install

PS:git://eagain.net/gitosis 已经失效了,找了好久才有一个新的。

4. 创建git用户

sudo adduser
–system
–shell /bin/sh
–gecos ‘git user’
–group
–disabled-password
–home /home/git
git

客户端(也需要先安装 git)
5. 在 gitosis 管理员的机器上生成 密钥,把公钥重命名为comet@3GCOMET.pub,这里用scp传到服务器上
ssh-keygen -t rsa
mv id_rsa.pub comet@3GCOMET.pub
scp comet@3GCOMET.pub comet@192.168.1.254:comet@3GCOMET.pub

6.在 ~/.ssh/config 添加以下内容,以便连接到服务器
Host 192.168.1.254
Compression yes
IdentityFile ~/.ssh/id_rsa

服务器端
7.使用上面的 comet@3GCOMET.pub 初始化 gitosis
sudo -H -u git gitosis-init < comet@3GCOMET.pub
sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

客户端
8.获取服务器上的 gitosis-admin 项目,会有keydir 文件夹和gitosis.conf
git clone git@192.168.1.254:gitosis-admin.git

9.添加新组jichuteam、用户comet@HP、项目jichu,并推送到远程服务器

注:如果客户端是windows,使用Puttygen生成公钥和私钥:参数为SSH-2 RSA,1024位,按需加上密码。

如果之前是使用ssh-keygen生成的,在这里直接Load private key,然后save private key,保存为ppk格式才能用。

复制puttygen显示的公钥保存为*.pub文件,注意不是”save public key”,保证公钥文件只有1行内容,否则不正确。把公钥给git的管理员,让他用gitosis-admin之类的方法把公钥加入git服务器,并设置好对应项目的权限。

在新的客户端生成密钥,并把公钥放到 gitosis-adminkeydir ,这里是comet@HP.pub
cd gitosis-admin
vi gitosis.conf

修改为下面内容,其中[gitosis]可以看gitosis/example.conf的说明,members 的 comet@HP 就是 comet@HP.pub 的文件名,多个用户用空格隔开
[gitosis]
gitweb = no
daemon = no
loglevel = DEBUG

 

[group gitosis-admin]
writable = gitosis-admin
members = comet@3GCOMET

[group jichuteam]
members = comet@HP
writable = jichu

git push

10.到其他地方建立项目根目录,并设置默认用户和邮箱,在.git/config添加远程服务器URL
mkdir jichu
cd jichu
git init
git config user.name Comet
git config user.email iamcomet@3gcomet.com
git remote add origin git@192.168.1.254:jichu.git

11.在 jichu 目录下进行开发,这里新建了 log.txt(一定要有新文件),提交到index,加上”initial import”信息并提交到本地仓库,最后是推送到远程服务器。
echo “begin develop” > log.txt
git add .
git commit -a -m “initial import”
git push origin master

服务器端
12.在服务器的 /home/git/repositories/ 可以看到有 jichu.git 的版本库。

linux常用svn命令

yum install subversion

安装完成之后, 你可以通过以下命令查看是svnversion版本信息:

svn –version

1、将文件checkout到本地目录
svn checkout path(path是服务器上的目录)
例如:svn checkout svn://192.168.1.1/pro/domain
简写:svn co
2、往版本库中添加新的文件
svn add file
例如:svn addtest.php(添加test.php)
svn add *.php(添加当前目录下所有的php文件)

你不能直接使用 svn add * 命令,必须使用 “svn add * –force” 命令。
请放心,–force参数没有看上去的那么可怕,svn会自动判断,看这个文件是否值得添加,–force参数只不过是驱使 svn 去检查一个子目录,而不管这个子目录是否已经纳入管理
3、将改动的文件提交到版本库
svn commit -m “LogMessage“ [-N] [–no-unlock] PATH(如果选择了保持锁,就使用–no-unlock开关)
例如:svn commit -m “add test file for my test“ test.php
简写:svn ci
4、加锁/解锁
svn lock -m “LockMessage“ [–force] PATH
例如:svn lock -m “lock test file“ test.php
svn unlock PATH
5、更新到某个版本
svn update -r m path
例如:
svn update如果后面没有目录,默认将当前目录以及子目录下的所有文件都更新到最新版本。
svn update -r 200 test.php(将版本库中的文件test.php还原到版本200)
svn update test.php(更新,于版本库同步。如果在提交的时候提示过期的话,是因为冲突,需要先update,修改文件,然后清除svn resolved,最后再提交commit)
简写:svn up
6、查看文件或者目录状态
1)svn status path(目录下的文件和子目录的状态,正常状态不显示)
【?:不在svn的控制中;M:内容被修改;C:发生冲突;A:预定加入到版本库;K:被锁定】
2)svn status -v path(显示文件和子目录状态)
第一列保持相同,第二列显示工作版本号,第三和第四列显示最后一次修改的版本号和修改人。
注:svn status、svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的,原因是svn在本地的.svn中保留了本地版本的原始拷贝。
简写:svn st
7、删除文件
svn delete path -m “delete test fle“
例如:svn delete svn://192.168.1.1/pro/domain/test.php -m “delete test file”
或者直接svn delete test.php 然后再svn ci -m ‘delete test file‘,推荐使用这种
简写:svn (del, remove, rm)
8、查看日志
svn log path
例如:svn log test.php 显示这个文件的所有修改记录,及其版本号的变化
9、查看文件详细信息
svn info path
例如:svn info test.php
10、比较差异
svn diff path(将修改的文件与基础版本比较)
例如:svn diff test.php
svn diff -r m:n path(对版本m和版本n比较差异)
例如:svn diff -r 200:201 test.php
简写:svn di
11、将两个版本之间的差异合并到当前文件
svn merge -r m:n path
例如:svn merge -r 200:205 test.php(将版本200与205之间的差异合并到当前文件,但是一般都会产生冲突,需要处理一下)
12、SVN 帮助
svn help
svn help ci
——————————————————————————
以上是常用命令,下面写几个不经常用的
——————————————————————————
13、版本库下的文件和目录列表
svn list path
显示path目录下的所有属于版本库的文件和目录
简写:svn ls
14、创建纳入版本控制下的新目录
svn mkdir: 创建纳入版本控制下的新目录。
用法:
1、mkdir PATH…
2、mkdir URL…
创建版本控制的目录。
1、每一个以工作副本 PATH 指定的目录,都会创建在本地端,并且加入新增调度,以待下一次的提交。
2、每个以URL指定的目录,都会透过立即提交于仓库中创建。在这两个情况下,所有的中间目录都必须事先存在。
15、恢复本地修改

svn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。revert:
用法: revert PATH…
注意: 本子命令不会存取网络,并且会解除冲突的状况。但是它不会恢复被删除的目录
16、代码库URL变更
svn switch (sw): 更新工作副本至不同的URL。
用法: 1、switch URL [PATH]
2、switch –relocate FROM TO [PATH…]
1、更新你的工作副本,映射到一个新的URL,其行为跟“svn update”很像,也会将服务器上文件与本地文件合并。这是将工作副本对应到同一仓库中某个分支或者标记的方法。
2、改写工作副本的URL元数据,以反映单纯的URL上的改变。当仓库的根URL变动(比如方案名或是主机名称变动),但是工作副本仍旧对映到同一仓库的同一目录时使用这个命令更新工作副本与仓库的对应关系。
17、解决冲突
svn resolved: 移除工作副本的目录或文件的“冲突”状态。
用法: resolved PATH…
注意: 本子命令不会依语法来解决冲突或是移除冲突标记;它只是移除冲突的
相关文件,然后让 PATH 可以再次提交。
18、输出指定文件或URL的内容。
svn cat 目标[@版本]…如果指定了版本,将从指定的版本开始查找。
svn cat -r PREV filename > filename (PREV 是上一版本,也可以写具体版本号,这样输出结果是可以提交的)

随机数的生成函数,这里贡献给大家。

首先是要用mt_rand()函数生成指定个数的随机数字;

然后使用array_unique()函数去重;

因为去重了;所以得到的数字就不够指定个数了;

所以;核心是要用while循环;直到得到指定个数的数字;

到这里基本可以是结束了;

对于追求完美的人来说;还可以再用个sort();

目的不是要用来排序;主要是将得到的数组key格式化;

用代码来说话;就如下;

<?php
/**
* 生成不重复的随机数
* @param  int $start  需要生成的数字开始范围
* @param  int $end    结束范围
* @param  int $length 需要生成的随机数个数
* @return array       生成的随机数
*/
function get_rand_number($start=1,$end=10,$length=4){
$connt=0;
$temp=array();
while($connt<$length){
$temp[]=mt_rand($start,$end);
$data=array_unique($temp);
$connt=count($data);
}
sort($data);
return $data;
}

当然;重点不是这个函数;重点是这个函数的思路;可以解决很多类似的问题;

6f8cd40d-4516-4c6d-b602-fb8671ab5530

作为PHP开发者请务必了解Composer

Composer是一个非常流行的PHP包依赖管理工具,已经取代PEAR包管理器,对于PHP开发者来说掌握Composer是必须的.

对于使用者来说Composer非常的简单,通过简单的一条命令将需要的代码包下载到vendor目录下,然后开发者就可以引入包并使用了.

其中的关键在于你项目定义的composer.json,可以定义项目需要依赖的包(可能有多个),而依赖的包可能又依赖其他的包(这就是组件的好处),这些都不用你烦心,Composer会自动下载你需要的一切,一切在于composer.json的定义.

Composer对于使用者来说是很透明,但是其背后的理念还是需要了解一下的,其的诞生也不是偶然的,得益于Github的快速发展,PHP语言也越来越现代化,显得更高大上了.

为了理解Composer,先大概了解下其结构:

Composer的结构

  • Composer命令行工具:

    这个理解就比较简单了,通过使用者定义的Composer.json去下载你需要的代码,假如只是简单的使用Composer,那么掌握一些具体命令就完全可以了

  • Autoloading代码加载器:

    通过Composer,开发者可以通过多种方式去使用,而其中的关键在于PHP的命名空间概念,以及PSR-4标准的发展,Composer只是根据这二者开发了一个代码自动加载器

  • Github:

    有了Github,PHP开发人员可以将开源的代码托管在这上面,而Composer的发展源于Github,Composer本质上就是将Github上的代码下载到本地.

  • Packagist:

    对于使用者来说使用的是Composer的命令行工具,那么命令行工具怎么知道有多少包可以被用户使用呢,这主要就是依赖于Packagist,Packagist是Composer主要的一个包信息存储库,包开发者将具体代码托管到Github上,将包信息提交到Packagist上,这样使用者就可以通过Composer去使用.

  • Composer根据本地定义的composer.json信息去查询Packagist,Packagist根据Composer.json/Package.json信息解析,最终对应到github仓库,Composer最终下载代码的时候还要依赖于Github仓库上的Composer.json,这里涉及到三种类型的composer.json,含义是不一样的.
  • Composer.json:

    这是Composer的核心,是Composer的规则,上面也提到了三种类型的Composer.json,在使用的时候一定要注意区分,我初学的时候就总是搞乱.

Composer命令行工具

composer init

使用者可以在自己的项目下创建composer.json以便定义你项目的依赖包,也可以通过composer init交互式的创建composer.json.

composer install

应该是最常用的命令,composer会根据本地的composer.json安装包,将下载的包放入项目下的vendor目录下,同时将安装时候的包版本信息放入到composer.lock,以便锁定版本.

其实在install的时候,假如发现composer.lock版本和目前vendor目录下的代码版本是一致的,则Composer会什么也不做,composer.lock的目的就是让你安心在目前这个版本下工作,而不获取最新版本的包.

composer update

那么如何更新composer.lock以便获取到最新版本的包呢?通过这个命令即可更新最新版本的包

composer config

这个命令还是建议了解下,全局的配置保存在COMPOSER_HOME/config.json,非全局的配置信息则存储在本项目目录下.

composer configlistg

composer configg notifyoninstall false

composer global config bindirabsolute

composer create-project

这个命令不常用,但是个人觉得还是很重要的,使用普通的install命令是将项目所有的依赖包下载到本项目vendor目录下.而通过这个命令则是将所有的代码及其依赖的包放到一个目录下,相当于执行了一个git clone命令,一般是包的开发者可能为了修复bug会使用该命令.

composer global

这是一个全局的安装命令,它允许你在COMPOSER_HOME目录下执行Composer的命令,比如install,update.当然你的COMPOSER_HOME要在$PATH环境下.

比如执行composer global require fabpot/php-cs-fixer,现在php-cs-fixer命令行可以全局运行了,如果稍后想更新它,只需要运行composer global update

composer dump-autoload

当你修改项目下的composer.json的文件,并不一定要运行composer update命令进行更新,有的时候可以使用该命令来更新加载器,比如你要引用本地自定义的包(不是来自于packagist),后面会通过实践来说明该命令.

composer require

假如手动或者交互式创建composer.json文件,可以直接使用该命令来安装包

composer require  cerdic/csstidy:1.5.2

composer require “ywdblog/phpcomposer:dev-master”

–prefer-source和–prefer-dist参数

–prefer-dist:对于稳定的包来说,一般Composer安装默认使用该参数,这也能加快安装,比如有可能直接从packagist安装了相应的包,而不用实际去Github上下载包.

–prefer-source:假如使用该参数,则会直接从Github上安装,安装包后vendor目录下还含有.git信息

composer require “ywdblog/phpcomposer:dev-master”prefersource

#在vendor/ywdblog/phpcomposer目录下含有.git信息

如何给Composer添加代理

在国内使用Composer下载特别慢,可以通过二个方法进行加速

  • composer config repo.packagist composer “https://packagist.phpcomposer.com“
  • 编辑composer.json

“repositories”: {

  “packagist”: {

      “type”: “composer”,

      “url”: “https://packagist.phpcomposer.com”

  }

}

Autoloading代码加载器

composer本身集成一个autoloader,支持PSR-4,PSR-0,classmap,files autoloading.

这里通过一个例子来说明通过Composer如何引用classmap,files,本地符合PSR-4标准的代码

编辑composer.json

“autoload”: {

  “classmap”: [“othsrc/”,“classsrc.php”],

  “files”: [“othsrc/filesrc.php”],

  “psr-4”: {“Foo\Bar\”: “src}

}

composer dump-autoload

通过上述的操作,对于PSR-4来说等同注册了一个PSR-4 autoloader(从FooBar命名空间)

假如不想使用Composer的autoloader,可以直接包含vendor/composer/autoload_*.php 文件,配置自己的加载器.

具体的例子托管在github上,可参考.

Repositories

关于Repositories,了解其不是必须的,但是假如掌握则更能理解Composer,对于Repositories,其中文文档和英文文档解释的很好,这里也进行了一些摘抄.

基本概念

包:

Composer是一个依赖管理工具,它在本地安装一些资源包和包的描述(比如包名称和对应的版本),比较重要的元数据描述是dist和source,dist指向一个存档,该存档是对一个资源包的某个版本的数据进行的打包.source指向一个开发中的源,这通常是一个源代码仓库(比如git)

资源库:

一个资源库是一个包的来源.它是一个packages/versions的列表.

Composer将查看所有你定义的repositories以找到项目需要的资源包(这句话很重要).

默认情况下已经将Packagist.org注册到Composer(或者理解为Packagist.org是Composer资源库默认的仓库类型)

Composer资源库类型

Composer资源库包括四种类型,默认的是composer类型,也就是packagist.org所使用的资源类型.

它使用一个单一的packages.json文件,包含了所有的资源包元数据.当你将包发布到pckagist.org上,则默认系统会创建一个packages.json,不过我没有找到我的包对应的文件.

VCS资源库类型

假如你想构建一个私有的Composer私有资源库类型,可以使用该类型,这里举一个例子,比如你在自己项目的composer.json定义如下,则就可以使用对应的Github上的代码了.

{

    “repositories”: [

    {

        “type”: “vcs”,

        “url”: “https://github.com/ywdblog/phpcomposer”

    }

    ],

    “require”: {

        “ywdblog/phpcomposer”: “dev-master”

    }

}

当运行composer update的时候,Comoser实际上是从Github上下载包而不是从pckagist.org上下载.

另外假如需要使用Package资源库类型或者PEAR资源库类型,参考官方文档即可,一般在composer.json中定义name、version属性即可.

Composer.json

在本文上面也多次提到了composer.json,比如你希望使用第三方包则需要在本地定义composer.json,Composer安装第三方包后,也会在第三方包目录下发现composer.json,那么这二者都叫composer.json,有什么区别呢?理解这非常的重要.

假如你在自己的项目下面定义一个composer.json,则这个包称之为ROOT包,这个composer.json定义你项目需要的条件(比如你的项目可能依赖一个第三方包).

composer.json中有些属性只能被ROOT包使用,比如config属性只在ROOT包中生效.

一个资源包是不是ROOT包,取决于它的上下文,比如你git clone ywdblog/phpcomposer,则这时候本地phpcomposer目录就是ROOT包,假如你在本地phpcomposer目录下composer require ywdblog/phpcomposer,则这时候你的项目phpcomposer就是ROOT包.

了解composer-schema.json可参考该网址,Laravel作为一个成熟的框架,其定义的composer.json非常经典

关于包的版本

当使用者在本地配置composer.json的时候,可以指定需要包的特定版本,Composer支持从Github仓库中下载Tag或者分支下的包.

对于Github上的Tag来说,Packagist会创建对应包的版本,它符合X.Y.Z,vX.Y.Z,X.Y.Z-包类型,就是说Github上虽然只有一个特定版本的包,但Composer支持多种形式的引用方式,比如:

composer require monolog/monolog  1.0.0RC1

composer require monolog/monolog  v1.0.0RC1

composer require monolog/monolog  1.0.*

composer require monolog/monolog  ~1.10

对于Github上的分支来说,Packagist会创建对应包的版本,假如分支名看起来像一个版本,将创建{分支名}-dev的包版本号,如果分支名看起来不像一个版本号,它将会创建dev-{分支名}形式的版本号

composer require monolog/monolog  masterdev

composer require monolog/monolog  master.xdev

总结:

理解Composer,最重要的是实践,最后也能明白PSR-4和命名空间,也可以尝试将你的项目发布到pckagist.org上.

搭建Git服务器

在远程仓库一节中,我们讲了远程仓库实际上和本地仓库没啥不同,纯粹为了7×24小时开机并交换大家的修改。

GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。

搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。

假设你已经有sudo权限的用户账号,下面,正式开始安装。

第一步,安装git

$ sudo apt-get install git

第二步,创建一个git用户,用来运行git服务:

$ sudo adduser git

第三步,创建证书登录:

收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

第四步,初始化Git仓库:

先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:

$ sudo git init --bare sample.git

Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git

$ sudo chown -R git:git sample.git

第五步,禁用shell登录:

出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

git:x:1001:1001:,,,:/home/git:/bin/bash

改为:

git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

第六步,克隆远程仓库:

现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:

$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.

剩下的推送就简单了。

管理公钥

如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。

这里我们不介绍怎么玩Gitosis了,几百号人的团队基本都在500强了,相信找个高水平的Linux管理员问题不大。

管理权限

有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite就是这个工具。

这里我们也不介绍Gitolite了,不要把有限的生命浪费到权限斗争中。

小结

  • 搭建Git服务器非常简单,通常10分钟即可完成;
  • 要方便管理公钥,用Gitosis;
  • 要像SVN那样变态地控制权限,用Gitolite。