Ubuntu 16.04.4 LTS 安装php7.2

因项目要使用到Laravel,但Laravel要求php >= 7.1.3

我的本地系统为 Ubuntu 16.04.4 LTS ,php版本为7.0

当前php7.2已经有稳定版本发布,所以计划直接升级到php7.2

因php7.2版本比较新,并未收录在ubuntu 16.04.4 LTS 默认的软件包里面

所以就需要添加PPA(Personal Package Archives)

以下是添加和安装的步骤:

参考文档  https://tecadmin.net/install-php-7-on-ubuntu/

让Apache可以捕获HTTP头部Authorization字段

如果业务场景使用了JSON Web Token 进行身份认证,就需要WEB代理服务器如Nginx或者Apache能够解析HTTP header数据中的Authorization字段,在实际开发中遇到了Apache未能捕获此字段的情况,需要在.htaccess 文件中添加如下配置即可。

 

参考链接:

https://github.com/bitnami/bitnami-docker-wordpress/issues/104

 

vim调试PHP工具vdebug的使用

vdebug是一款vim下的代码调试工具,支持多种语言如PHP, Python, Perl, Ruby

如果你是使用Vundle管理vim插件,安装vdebug非常简单,只需要在vim添加一行配置

Plugin ‘vim-vdebug/vdebug’

然后在vim中输入命令:PluginInstall自动安装,成功后就可以调试了。

调试命令:

F10  添加/删除断点

F5开始调试

F2 逐行调试

F4 跳到断点

F6 结束调试

详细文档请访问

https://github.com/vim-vdebug/vdebug

如果是PHP,调试前需要安装PHP的调试扩展Xdebug

 

Docker容器自动退出问题解决方案

我在shell脚本里面执行了docker run 命令,

用来生成一个docker容器,但是随着shell脚本运行完毕,

生成的容器也自动退出了,经查询原因,在stackoverflow上找到一种解决办法,

在生成容器的时候,初始化执行的命令不能自动退出,例如:

上面的命令基于镜像tonvin/ubuntu:wp7生成一个名为$user的容器,

最后面的/bin/bash /root/init.sh表示初始化完毕后运行shell脚本/root/init.sh

我在/root/init.sh末尾添加了一行tail -f /dev/null

生成的容器就不自动退出了,也许此方法不好,但暂时可以解决问题。

还有一种办法是启动的时候添加参数 –restart=always

-d参数表示daemon方式运行

-P参数指示生成随机的端口映射

PHP字符串函数substr的用法

substr是PHP语言的一个字符串截取函数,它的作用是返回字符串的一部分。在日常开发中会经常使用到。
它有三个参数,

第一个参数是要处理的原始字符串;

第二个参数是截取的起始位置,字符串中第一个字符位置是0,向后依次累加,如果从字符串结尾开始指定位置,最后一个位置是-1,如果要截取末尾的几个字符,通常设定负数比较方便;

第三个参数是可选的,指定了要截取的长度,如果没有指定,默认截取到结尾。如果指定负数意思是从start位置开始截取,并舍弃字符串末端字符数。

如果要处理的字符串是多字节编码,就需要知道每个字符所占的字节数,比如中文 每个汉字占3字节,在设定参数时就需要计算好,否则容易出现乱码。也可以使用mb_substr等扩展库支持的函数来处理。

修改已经创建的docker容器的端口映射

本文翻译自Syed Rakib Al Hasanstackoverflow.com的回答

原始链接:https://stackoverflow.com/questions/19335444/how-do-i-assign-a-port-mapping-to-an-existing-docker-container

对于已经创建的docker容器,如何修改映射的端口号呢?可以参考如下的操作步骤

0)  docker container list –all

结果中的CONTAINER ID列为容器id

1)  docker inspect <容器id>   |  grep Id

查看容器hash,<容器id>由步骤0)获得

2)  docker stop <容器id>

停止运行中的容器

3) vim /var/lib/docker/containers/[容器hash]/hostconfig.json

编辑容器配置文件,<容器hash>由步骤1)获得

修改PortBindings参数配置,宿主机8001端口映射容器80端口示例:

“PortBindings”:{“80/tcp”:[{“HostIp”:””,”HostPort”:”8001″}]},”

4) systemctl restart docker

重新启动docker引擎

5)docker start <容器id>

重新启动docker容器

 

Git升级

由于之前Ubuntu 14.04.1 LTS使用的是git 1.9版本,这个版本的git对于修改文件名的操作不能识别为renamed,

遂升级至2.14.2,升级步骤:

 

Vimsplain一款用来解释vim命令的工具

通过vimgolf可以练习vim操作,vimgolf网站给出了一系列文本操作的练习实例,同时列出了用户的操作步骤,

这个步骤是一长串vim命令,对于初学者来说往往看的眼花缭乱一头雾水,

比如:

pafcu的开源的这款Vimsplain正是为解决这个问题的,

通过它可以拆分并解释上面的命令:


安装和使用非常简单

代码仓库 git@github.com:pafcu/Vimsplain.git

使用

commands 为vim命令序列

vimgolf一个练习vim操作的高尔夫球场

www.vimgolf.com 提供了一个练习vim的场所,通过安装vimgolf,拉取练习实例,将原始文件编辑为目标文件,然后上传发布自己的操作步骤,同时,也可以借鉴其他人的操作。在这里,vim高手如云,各种奇葩技巧一定会让你大开眼界。

使用vimgolf需要先安装Ruby和Gem,然后得有twitter账号,用来登陆vimgolf,否则没有办法获取key。

然后执行下面的命令,[challenge ID]是网站首页列出得训练编号,随便选择一个训练项目,在页面右侧就可以看到challenge ID

以下是challenge ID为56fb2e75ccffcc0009026473的练习过程:

PHP使用SPL内置迭代器递归遍历目录

PHP开发中经常有遍历目录的需求,使用PHP内置标准库SPL提供的迭代器,可以很方便地实现,下面视频演示如何使用SPL迭代器实现目录和文件的遍历。

在目录dir下面有多个目录和文件,并且目录还有子目录,使用SPL库的迭代器可以很方便的递归遍历每个文件。

代码:

参考:
http://php.net/manual/en/spl.iterators.php

HTTP分析调试工具Fiddler的使用

Fiddler是什么?

Fiddler是一个Web调试代理程序,HTTP抓包分析工具,使用它可以分析您的电脑应用和互联网之间的基于HTTP协议的通信数据。通过Fiddler作为中间代理,就可以按需求查看、分析、修改所有的HTTP请求和响应内容。

为什么在网络编程中需要用到Fiddler?

日常网站开发中,经常会使用HTTP协议来传输数据,请求数据报文通常由头部参数和用户提交的正文部分按封装协议约定的格式,在TCP连接建立后,发送给远端的服务器,服务器处理完毕把头部信息和处理结果再封装为协议定义的响应格式返回给客户端,实际开发中可能由于两端业务逻辑的复杂性,组装完毕准备传输的最终内容,往往是未知的,此时如果借助Fiddler代理来捕获请求,就可以非常清晰地查看传输内容,同时,Fiddler可以修改发送和接收的数据,方便程序的调试开发。

Fiddler系统代理示意图

与Fiddler功能相似的工具还有哪些?

目前常见的有Charles, Burp Suite, Wireshark, HTTPWatch , Tcpdump。

Fiddler的安装

对于操作系统Windows,Linux,MacOS,官方都有支持的版本可供下载。

下载地址:

https://www.telerik.com/download/fiddler

Fiddler配置步骤

1)Fiddler配置

打开Fiddler,点击菜单栏Tools->Options…打开选项菜单,切换到Connections选项卡。

在Fiddler listens on port:的文本框里面输入监听的端口号。

然后访问 http://127.0.0.1:8883/, 如果想监听其它机器而非本机,选择Allow remote computers to connect为打开状态。

如果正常打开并显示 Fiddler Echo Service 表明Fiddler监听已经正常工作了(打不开注意防火墙的限制)。

2)安装Chrome扩展程序 Proxy SwitchyOmega

安装这个Chrome浏览器的扩展程序,新建一个Fiddler端口的情景模式,就可以设定访问的页面通过Fiddler代理了。

Chrome浏览器扩展SwitchyOmega添加Fiddler情景模式
Chrome浏览器扩展SwitchyOmega添加Fiddler情景模式

配置完成后,点击地址栏后面的SwitchOmeage的插件图标,选择Fiddler就可以了。

3) 设定Fiddler捕获数据和过滤器

Fiddler监听过滤设置
Fiddler监听过滤设置

 

如果打开的网页比较多,网络比较繁忙,抓取的HTTP会话会很多,设定过滤器可以只捕获特定的会话。

上图中设定了只捕获www.baidu.com和*.one234.xyz两个域名的HTTP会话。

如果Fiddler还是没有捕获,则需要注意左下角的设置,打开Capturing和All Processes。

如果是Windows,需要注意防火墙的设置。

4 ) 程序中设置Fiddler代理

如果欲监听的HTTP请求是由程序发起,可以在代码中设置代理,例如

PHP程序关键代码片段:

curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);

curl_setopt($ch, CURLOPT_PROXY, ‘127.0.0.1:8883’);

Java程序关键代码片段:

jre -DproxySet=true -DproxyHost=127.0.0.1 -DproxyPort=8888 MyApp

shell curl 命令使用Fiddler代理:

curl –proxy 192.168.199.117:8883 http://demo.one234.xyz/fiddler/fruit.html

5 ) HTTPS解析

依次打开Tools->options->HTTPS的选项卡,勾选相应的选项,如下图示例:

6 ) 手机配置代理

如果需要监听手机设备HTTP数据,在连接成功的Wi-Fi设置里面可以找到手动HTTP代理,设置代理主机名和端口:

Android HTTP设置代理图示:

iPhone HTTP代理设置图示:

想正常解析HTTPS,还需要安装一个Fiddler的插件CertMaker,来生成证书。

插件下载地址:https://telerik-fiddler.s3.amazonaws.com/fiddler/addons/fiddlercertmaker.exe

安装完毕重新启动Fiddler,然后用手机访问http://127.0.0.1:8883,注意127.0.0.1切换为安装了Fiddler的主机的IP

在页面点击FiddlerRoot Certificate下载证书后安装。

 查看HTTP会话

配置成功后,就可以在Fiddler的界面看到抓取到的HTTP会话了,如下图:

Fiddler抓取的HTTP会话列表
Fiddler抓取的HTTP会话列表

 

点击左侧每一条会话,就可以在右侧查看会话的所有信息,包括统计信息,会话请求和响应的数据报头和报体,使用的HTTP协议版本,Cookies等,以及使用表单,进制转化,JSON格式化等对数据报的解析查看。

HTTP会话数据报分析
HTTP会话数据报分析

在这里我们可以看到程序发给服务器的原始数据,和服务器处理后返回的原始结果。这样的分析有助于排查问题来源于客户端还是服务端。

自定义HTTP会话

1)自定义HTTP请求[Request]

自定义HTTP会话是指,可以通过Fiddler发起HTTP请求,下图是主动发起请求的例子:

Fiddler自定义HTTP请求
Fiddler自定义HTTP请求

在这里,可以脱离浏览器主动发起HTTP请求,也可以把左侧的会话拖到右侧,然后在原来会话的基础上修改,(在左侧会话上点击右键,选择Replay->Reissue and Edit也可以编辑会话)这样就不依赖应用程序了。可以修改上次发起的请求数据,也就说可以完全绕开代码程序的限制,比如网页上的Javascript校验,复杂的表单构造,数据准备依赖,在实际程序开发测试中,可以忽略繁琐的请求数据构造,大大提高效率。

2)自定义HTTP响应[Response]

Fiddler自定义HTTP响应
Fiddler自定义HTTP响应

如上图所示,使用AtuoResponder可以自定义每一次会话请求的响应内容,这样,有些请求就不需要发送到远端服务器去处理,直接在本地,按预定的格式返回。比如远程服务器响应太慢,边界条件无法满足,线上生产环境无法返回满足特定条件的数据,需要权限认证等。自定义响应的内容可以指定为一个本地文件,或者设定的HTTP状态码等等。同样对于开发和测试人员,只要掌握使用技巧,可以避免很多因素导致的响应问题。

想基于左侧的捕获的HTTP会话创建AutoResponder规则,先在左侧用Shift按键多选几条会话,拖动到右边即可。

重放HTTP请求

想重新请求某会话,只需要在会话上点击右键,选择Replay->Reissue Request即可。

Fidder重新发送HTTP请求
Fidder重新发送HTTP请求

重放请求很方便,比如在联调时,客户端准备好数据后发起的请求,可以一直保持,不用再重建会话,因为实际开发中一次请求的数据构建可能依赖太多条件和步骤。

备份和载入HTTP会话

对于捕获的会话可以备份为文件,发送给其他开发测试人员,方便协助排查问题,也方便后续再次开发。

实际项目开发中,各个开发人员往往因为沟通和对齐参数花费大量时间,只要把实际请求的数据发送给对方便一目了然知道问题所在。

Fiddler打包会话
Fiddler打包会话

打包后是一个.saz文件,可以使用Fiddler直接打开。

命令行工具 QuickExec

?sometext 按字符查找会话
=status 按状态码选择过滤会话
@host 按主机域名搜寻
bpafter $path 设置中断
g 取消所有中断
select image/css/html 快速查找选择
!listen 8889 监听新端口

以上介绍了Fiddler对HTTP会话的各种操作,最主要的还是要看懂HTTP协议的数据报格式定义,数据报的body部分是业务互相传递的,对于熟悉业务的的编码人员比较了解,但是数据报的头部内容是独立于应用程序生成的,虽然编码人员本身不过多关注,但是出现问题了还是需要去分析的。Fiddler对HTTP会话的各种操作,让通信数据更加透明,通信过程更加可控,使软件开发调试以及测试更加便利,软件使用也很简单,是一款提高生产效率,简化开发过程不可多得的利器。

 

参考:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

http://www.telerik.com/fiddler

http://docs.telerik.com/fiddler/configure-fiddler/tasks/configurefiddler

PHP连接MySQL数据库

 PHP为什么要连接数据库呢?

如果首次接触PHP,会有这样的疑问。

当然,也可以不连接数据库,PHP程序也可以正常运行。

PHP程序代码,只负责业务逻辑的处理,对于输入的数据进行计算并输出结果。

比如,你给一段计算和值的代码输入1,2….10,程序计算完并返回结果55。

此时,如果想把这个计算过程中,输入数据和输出数据存储下来,就需要数据库了。

PHP可以连接哪些数据库?

只要数据库和程序之间有相应的统一接口,就可以连接,常见的MySQL, PostgreSQL,SQL Server,Oracle,MongoDB,Redis都可以连接,其中以MySQL使用最为广泛。

PHP程序如何与MySQL数据库交互?

PHP与MySQL是互相独立的软件,两者若要进行数据交互,

就必须相互暴露相关的API,这些API通常是基于各自源码开发的扩展程序。

PHP与数据库进行数据交互,主要有以下三种扩展:

1) mysql扩展

2) mysqli扩展

3) PDO_MYSQL扩展

上面3种扩展都是基于PHP核心代码编写的扩展库, 都有对应的库函数和类。

上面3种扩展连接数据库服务器,可以使用以下2种数据库驱动:

  1. MySQL Client Library [ libmysql ]
  2. MySQL Native Driver  [mysqlnd ]

注意,这两个库是底层的,直接和数据库服务器交互的,没有提供PHP代码编程接口,是安装PHP的时候就指定的。

php扩展-libmysql关系图[1]

注意:

自PHP5.4.x,默认的驱动由libmysql变为mysqlnd,自PHP 5.5.0 libmysql被废弃,自PHP 7.0.0 libmysql开始被移除,这是因为mysqlnd是由PHP官方发布的新一代驱动程序,之前的libmysql的由MySQL AB发布,从而规避了版权问题,这只是一方面的原因,mysqlnd是直接集成在PHP源码中的,使用PHP的内存管理系统,支持PHP的内存限制,比libmysql有更快执行速度和更少的内存使用率。

PHP mysqlnd数据库驱动结构图

php mysqlnd结构图[2]

mysqlnd和libmysql在内存占用上的对比:

limysql和mysqlnd在内存占用上的对比[3]

可以看到,libmysql查询的数据在内存中存储了2份,而mysqlnd只存储了一份。

使用mysqlnd,运行PHP的主机可以不用安装数据库,而之前使用libmysql这是必须的。

mysqlnd还有更多特性,例如,增强的持续连接,SSL支持等,所以是时候抛弃libmysql了。

PHP连接MySQL数据库代码示例:

  • mysqli扩展提供了丰富的面向对象编程模式来操作数据库的方式,比只支持函数式编程的mysql扩展好很多。
  • PDO方式虽然在编程上稍复杂一点,程序效率稍慢点,但是当业务的数据库类型变化时,基本上不用修改代码,因为它为各个不同的数据库定义了一个统一的接口。
  • mysql_connect方式的连接已经淘汰了。

参考资料
[1] http://jpauli.github.io/2014/07/21/php-and-mysql-communication-mysqlnd.html
[2] http://jpauli.github.io/2014/07/21/php-and-mysql-communication-mysqlnd.html
[3] Andrey Hristov <andrey@mysql.com>

PHP中constant用法举例

如果define定义的常量的名字在程序中是个变量,可以使用constant()函数来获取常量的值。

例如:

 

PHP函数set_exception_handler在各个版本中的差异

PHP函数set_exception_handler用来设置用户自定义的异常处理函数,

此函数的参数在PHP5和PHP7之间存在一些差异,

PHP7对传入 exception_handler 的参数从 Exception 改为 Throwable

这个错误存在于Codeigniter 3.06以前的版本。

参考资料:

http://stackoverflow.com/questions/36982769/codeigniter-ci-exceptionsshow-exception-error-after-updating-to-php-7

https://secure.php.net/manual/zh/language.exceptions.php

https://github.com/bcit-ci/CodeIgniter/issues/4137

vim编辑器宏的使用

如果把vim编辑器的各种操作比喻为武侠小说中的功夫,那么可以称得上是葵花宝典,两者最大的特点都是,通过宏可以将一组操作指令以自动化的方式重复执行指定的次数,从而提高编辑效率。如果能够合理利用,这种批处理的方式在实际的编码过程中非常有用。

下面介绍宏的基本使用方法:

0)  定义宏

命令格式    q<letter><commands>q

q    标明开始录制宏;

<letter>输入一个a到z的字母,设置将宏存储在哪个暂存器;

<commands>输入要执行的操作;

q   标明 结束录制宏;

举例:qa0gUwjjq    定义个一个名称为a的宏,它的指令集是0gUwjj,这个操作会使隔行的字母全部转换为大写字母。

vim宏定义

1) 查看宏

命令格式    :reg <letter>

举例:要查看刚才定义的宏a,输入:reg a就可以查看宏a的命令序列。

查看定义的宏
查看定义的宏

2)执行宏

命令格式    <number>@<letter>

<number> 调用宏的次数;

@ 开始执行宏;

<letter> 要执行的宏名称;

举例:在命令模式下直接输入 5@a 将刚才录制的宏a重复执行5次。

调用已经定义的宏
调用已经定义的宏

3)保存宏

宏默认会临时保存到.viminfo文件,此文件一般位于目录~【家目录】如果指定的暂存器内容未被覆盖,即便退出vim, 下次打开也依然可以调用。

如果想永久保存录制的宏,可以将宏的定义添加到~/.vimrc配置文件中。

例如将刚才录制的宏永久保存,编辑.vimrc文件,添加下面的行

let @a=’0gUwjj’

这样任何时候使用@a就可以调用宏了。( 编辑模式下依次按键Ctrl-R Ctrl-R a可以快速输入暂存器里面的内容)

vim宏保存

4)编辑宏

如果录制的宏需要做一些临时修改, 在当前文件中,输入

:let @a=’

再依次按键 Ctrl-R Ctrl-R a自动补全宏指令集

:let @a=’0gUwjj

做出对应的修改,然后补全最后面的单引号即可

:let @a=’03xgUwjj’

这样之前的宏就修改为,先删除行首3个字符,在转化大小写

调用宏依然使用@a命令

此时可以输入:reg a 发现宏的内容已经被修改了

5)宏应用简单示例

宏实现了编辑操作的模式接口,只要自己能抽象出操作的共同指令集,就可以实现快捷强大的编辑操作,从而提高工作效率。

a) 给多个行末尾添加分号

let @a=’0A;^[j0′

b) 多行注释代码

let @a=’0i#^[j’

c) 删除不规则长度的字符串

let @a=’0t)hdi’j0′

css选择器first-child的使用

设有如下HTML

欲给第一个LI设定属性,可以写为:

需要注意的是,下面的写法是容易出现的错误。