justudy

just study


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 公益404

PHP多进程引发的msyql连接数问题

发表于 2016-09-07

PHP多进程引发的msyql连接数问题

业务中有一块采用了PHP的pcntl_fork多进程,希望能提高效率,但是在执行的时候数据库报错

1
2
PDO::prepare(): Premature end of data (mysqlnd_wireprotocol.c:1244)
Packets out of order. Expected 1 received 108. Packet size=7102829

发现应该是短时间大量的链接写入数据库.导致数据库无法响应

show variables like ‘%max_connections%’;
show variables like ‘%back_log%’;

修改my.ini 配置 back_log
back_log = 104
MySQL能有的连接数量。当主要MySQL线程在一个很短时间内得到非常多的连接请求,这就起作用,
然后主线程花些时间(尽管很短)检查连接并且启动一个新线程。back_log值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。
如果期望在一个短时间内有很多连接,你需要增加它。也就是说,如果MySQL的连接数据达到max_connections时,新来的请求将会被存在堆栈中,
以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。
另外,这值(back_log)限于您的操作系统对到来的TCP/IP连接的侦听队列的大小。
你的操作系统在这个队列大小上有它自己的限制(可以检查你的OS文档找出这个变量的最大值),试图设定back_log高于你的操作系统的限制将是无效的。

在linux中,/proc/sys/net/core/somaxconn这个参数,linux中内核的一个不错的参数somaxconn
  看下其解析:
  对于一个TCP连接,Server与Client需要通过三次握手来建立网络连接.当三次握手成功后,
  我们可以看到端口的状态由LISTEN转变为ESTABLISHED,接着这条链路上就可以开始传送数据了.
  每一个处于监听(Listen)状态的端口,都有自己的监听队列.监听队列的长度,与如下两方面有关:
  - somaxconn参数.
  - 使用该端口的程序中listen()函数.
  1. 关于somaxconn参数:
  定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128,具体信息为:
  Purpose:
  Specifies the maximum listen backlog.
  Values:
  Default: 128 connections
  Range: 0 to MAXSHORT
  Type: Connect
  Diagnosis:
  N/A
  Tuning
  Increase this parameter on busy Web servers to handle peak connection rates.
  看下FREEBSD的解析:
  限制了接收新 TCP 连接侦听队列的大小。对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多。 服务进程会自己限制侦听队列的大小(例如 sendmail(8) 或者 Apache),常常在它们的配置文件中有设置队列大小的选项。大的侦听队列对防止拒绝服务 DoS 攻击也会有所帮助。
我们可以通过,
echo 1000 >/proc/sys/net/core/somaxconn
修改连接数

Mac 环境修改如下:
增加max open files。先查看一下:
$ sysctl -a | grep files
kern.maxfiles = 12288 kern.maxfilesperproc = 10240

修改为
$ sudo sysctl -w kern.maxfiles=65535 $ sudo sysctl -w kern.maxfilesperproc=65535

增加 max sockets
$ sysctl -a | grep somax

kern.ipc.somaxconn: 128 $ sudo sysctl -w kern.ipc.somaxconn=2048

增加PHP程序配置文件实践

发表于 2016-09-06   |   分类于 PHP

#增加PHP程序配置文件实践

###最原始的方式

写php程序时会直接把数据库、缓存的连接信息放在config.php文件里。这样做有两个弊端,1.在开发调试时必须先把连接信息改成本地的,要提交代码时再改回远程的,麻烦,也容易遗漏。2.开发人员可以直接看到线上数据库的连接地址、账号、密码,不安全。

线上运行PHP程序时通常需要一个Http服务器,例如apache、nginx。以nginx为例,在配置文件中可以通过fastcgi_param指令来给PHP传递变量

fastcgi_param DB_HOST “192.168.1.1”;

这样就可以在PHP代码里通过$_SERVER[‘DB_HOST’]来获取到对应的值。

所以开发环境和线上环境只要配好nginx的配置,就可以实现不改代码执行程序了。

更进一步,可以传递一个标示当前环境的变量,例如

fastcgi_param CODE_ENV “production”;

然后在程序里可以根据$_SERVER[‘CODE_ENV’]的不同来执行一些不同的逻辑(比如开发环境会打印所有错误信息而线上环境不显示)

###这样完美了吗?

并没有,在实际应用中发现有两个问题:1.如果这个PHP程序不仅仅提供web服务,还提供了cli工具(例如数据库升级脚本),这个时候nginx传递的变量就过不来了。2.貌似不支持传递数组变量。

解决思路

要同时支持web和cli,通过nginx配置传变量已经行不通了,那能不能走php自己的配置呢?

于是在php.ini的末尾加上如下配置:

1
2
3
[userconf]
userconf.db_host=127.0.0.1
userconf.db_name=test

重启php-fpm之后,发现通过ini_get(‘userconf.db_host’)取到的数据是空,于是详细查看了php的文档,发现对于自定义的配置项,需要通过get_cfg_var()函数来获得。经过测试,在web和cli模式下,通过get_cfg_var(‘userconf.db_host’)可以拿到正确的值。

再优化

但这个方案还是有弊端:1.修改配置需要重启php-fpm。2.虽然php.ini里面支持数组的数据,但是还是不够灵活,最好是能直接用php配置。

所以我们可以在php.ini里面只配置一个配置目录的路径,这个目录下放置各个程序的配置文件,php程序先从php.ini获取到这个目录的路径,再从这个目录下读取php格式的配置文件。示例代码:

1
2
$path = get_cfg_var('userconf.dir');
$conf = include($path . '/test.php');

这样配置文件是每次访问都会重新读取,变更时不需要重启php-fpm;而且不同的站点只要选择不同的配置文件名,就可以在一台服务器上共存。

但这样还是有一个问题没有解决,那就是无法在同一台服务器上部署两个相同的站点,不过这个场景也不多,不解决也没关系。

expect脚本使用

发表于 2016-09-06   |   分类于 linux

#expect自动化远程登录脚本

首先要安装 expect 脚本程序,不过在 Macbook 中自带了。比如 CentOS 的机器,可以使用 yum install expect 的方式安装。

###简单模式

1
2
3
4
5
6
7
8
#!/usr/bin/expect -f
set timeout 5
spawn ssh root@192.168.0.1
expect "*assword*"
send "root\r"
expect "#"
send "ifconfig \r"
expect eof

spawn: 启动新的进程
expect:从进程接受字符串
send:用于向进程发送字符串
interact:容许用户交互

spawn 后面就是要执行的 shell 命令,expect 是捕获要等待输入的字符,send 是自动输入的内容,注意要 “\r” 表示换行以确认输入。

###使用变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/expect -f
set port 22
set user root
set host 192.168.0.12
set password root
set timeout -1
spawn ssh -D $port $user@$host "ifconfig"
expect {
"*yes/no" { send "yes\r"; exp_continue}
"*assword:" { send "$password\r" }
}
expect "*#*"
send "ifconfig > /home/cfg \r"
send "exit\r"
}

###通过读取配置文件获取变量:

配置文件
192.168.0.1 root
192.168.0.2 root

登陆脚本

#!/usr/bin/expect -f
set f [open ./ip r]  
while { [gets $f line ]>=0 } {       
set ip [lindex $line 0]     
set pwd [lindex $line 1]
spawn ssh $ip
expect  "*password:" { send "$pwd\r" }
expect "#"
send "ifconfig \r"
send "exit\r"
interact
}

mysql-index

发表于 2016-09-05   |   分类于 mysql

mysql索引

聚簇索引的叶节点就是数据节点,而非聚簇索引的页节点仍然是索引检点,并保留一个链接指向对应数据块。

  • myisan引擎

MyISAM 为非聚簇索引(NonCluster Index)
MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录

  • innodb引擎

InnoDB的主索引是聚簇索引(Cluster Index),数据和Key本身都会存储在B+Tree的叶子节点
InnoDB的辅助索引本身主要是记录主索引的Key,最终查找数据还是从辅助索引再去主索引查找

纯读模式下,性能对比MyISAM引擎会稍有影响(辅助索引需要3次io,主索引需要3次io,MyISAM可能只需要4次IO)

如果非特殊原因,强烈建议使用 InnoDB(XtraDB)存储引擎!
原因:(对比MyISAM or Aria)
更稳定可靠的数据存储和索引结构;整个存储引擎设计思想更可靠先进,接近于Oracle、SQL Server级别的数据库(有兴趣可以去阅读源码了解细节)
更多可靠特性支持,比如事务、外键等支持(支付等关键领域事务非常重要)
运行更稳定,不论读写数据的量级,都能够保证比较稳定的性能响应
更好地崩溃恢复机制,特别利用一些Percona的一些工具,更有效运维InnoDB
MySQL 5.5+ 对比 MySQL 5.1.x 总体功能和性能提升太多,改进太多

###mysql优化

  • 硬件

    1. CPU:使用多核CPU,能够充分发挥新版MySQL多核下的效果,建议4核以上
    2. 内存:如果数据量比较大,建议使用不要低于20G内存的服务器;
    3. 硬盘:如果条件允许使用SSD硬盘,TPS能够达到2000或者更高;SAS硬盘的TPS极限也可能在1000左右,对性能的提升是非常显著;为保证数据可靠性,建议适合的RAID方案

    4. 网卡:保证网卡不是瓶颈,保证足够的吞吐量,建议千兆网卡

  • linux服务器关键配置
    1. 文件打开描述符:/etc/security/limits.conf 中 nofile、/proc/sys/fs/nr_open
    2. 可分配文件句柄数:/etc/sysctl.conf 中 fs.file-max、/proc/sys/fs/file-max
    3. 进程数:/etc/security/limits.conf 中的 nproc
    4. 线程数:/proc/sys/kernel/thread-max
    5. 其他TCP和网络相关选项:/etc/sysctl.conf
    6. 这些都可以通过ulimit 或 直接调整 /proc 中变量进行临时修改
    7. 建议关闭SWAP分区(内存要足够大才行);如果数据太大,为了防止夯死主机,可以设置2G左右的SWAP分区
  • msyql 配置等

mysql优化

发表于 2016-09-05   |   分类于 mysql

MYSQL优化

[http://d.pr/i/HJUk][1]

  1. 为查询缓存优化你的查询
  2. EXPLAIN你的SELECT查询。根据结果给出分析相应的查询优化
  3. 当只要一行数据时使用LIMIT1,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。
  4. 为搜索字段建索引
  5. 在Join表的时候使用相当类型的数据,并将其索引
  6. 千万不要ORDER BY RAND()
  7. 避免 SELECT * 8. 永远为每张表设置一个ID,为数据库里的每张表都设置一个ID做为其主键,而且最好的是一个INT型的(推荐使用UNSIGNED),并设置上自动增加的AUTO-INCREMENT标志
  8. 使用ENUM而不是VARCHAR
  9. 从PROCEDURE ANALYSE()取得建议
  10. 尽可能的使用NOT NULL
  11. Prepared Statements,Prepared Statements可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击。当然,你也可以手动地检查你的这些变量,然而,手动的检查容易出问题,而且很经常会被程序员忘了。当我们使用一些framework或是ORM的时候,这样的问题会好一些。
  12. 无缓冲的查询,mysql-unbuffered-query()发送一个SQL语句到MySQL而并不像mysql-query()一样去自动fethch和缓存结果。这会相当节约很多可观的内存,尤其是那些会产生大量结果的查询语句,并且,你不需要等到所有的结果都返回,只需要第一行数据返回的时候,你就可以开始马上开始工作于查询结果了。
  13. 把IP地址存成UNSIGNED INT
  14. 固定长度的表会更快,固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。可能会浪费空间
  15. 垂直分割,“垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。
  16. 拆分大的DELETE或INSERT语句,这两个操作是会锁表的,表一锁住了,别的操作都进不来了。
  17. 越小的列会越快
  18. 选择正确的存储引擎
  19. 用一个对象关系映射器(Object Relational Mapper)
  20. 小心“永久链接” mysql-pconnect()

redis

发表于 2016-08-26   |   分类于 redis

redis命令

KEY

  1. DEL key [key …]

    删除给定的一个或多个 key 。

PHP程序优化技巧大全

发表于 2016-08-23   |   分类于 PHP

1
1、如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍。
2、$row[’id’] 的速度是$row[id]的7倍。
3、echo 比 print 快,并且使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接,比如echo $str1,$str2。
4、在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替。
5、注销那些不用的变量尤其是大数组,以便释放内存。
6、尽量避免使用get,set,__autoload。
7、require_once()代价昂贵。
8、include文件时尽量使用绝对路径,因为它避免了PHP去include_path里查找文件的速度,解析操作系统路径所需的时间会更少。
9、如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于 time()。
10、函数代替正则表达式完成相同功能。
11、str_replace函数比preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。
12、如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换代码,使得每次传递参数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。
13、使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。
14、用@屏蔽错误消息的做法非常低效,极其低效。
15、打开apache的mod_deflate模块,可以提高网页的浏览速度。
16、数据库连接当使用完毕时应关掉,不要用长连接。
17、错误消息代价昂贵。
18、在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。
19、递增一个全局变量要比递增一个局部变量慢2倍。
20、递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。
21、递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。
22、仅定义一个局部变量而没在函数中调用它,同样会减慢速度(其程度相当于递增一个局部变量)。PHP大概会检查看是否存在全局变量。
23、方法调用看来与类中定义的方法的数量无关,因为我(在测试方法之前和之后都)添加了10个方法,但性能上没有变化。
24、派生类中的方法运行起来要快于在基类中定义的同样的方法。
25、调用带有一个参数的空函数,其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。
26、Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面,少用脚本。
27、除非脚本可以缓存,否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能,以免除编译开销。
28、尽量做缓存,可使用memcached。memcached是一款高性能的内存对象缓存系统,可用来加速动态Web应用程序,减轻数据库负载。对运算码 (OP code)的缓存很有用,使得脚本不必为每个请求做重新编译。
29、当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数。此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储的已知字符串长度。但是,由于strlen()是函数,多多少少会有些慢,因为函数调用会经过诸多步骤,如字母小写化(译注:指函数名小写化,PHP不区分函数名大小写)、哈希查找,会跟随被调用的函数一起执行。在某些情况下,你可以使用isset() 技巧加速执行你的代码。
(举例如下)
if (strlen($foo) \< 5) { echo “Foo is too short”$$ }
(与下面的技巧做比较)
if (!isset($foo{5})) { echo “Foo is too short”$$ }
调用isset()恰巧比strlen()快,因为与后者不同的是,isset()作为一种语言结构,意味着它的执行不需要函数查找和字母小写化。也就是说,实际上在检验字符串长度的顶层代码中你没有花太多开销。
34、当执行变量$i的递增或递减时,$i++会比++$i慢一些。这种差异是PHP特有的,并不适用于其他语言,所以请不要修改你的C或Java 代码并指望它们能立即变快,没用的。++$i更快是因为它只需要3条指令(opcodes),$i++则需要4条指令。后置递增实际上会产生一个临时变量,这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种,正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意,因为并不是所有的指令优化器都会做同样的优化处理,并且存在大量没有装配指令优化器的互联网服务提供商(ISPs)和服务器。
35、并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。
36、并非要用类实现所有的数据结构,数组也很有用。
37、不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?
38、当你需要时,你总能把代码分解成方法。
39、尽量采用大量的PHP内置函数。
40、如果在代码中存在大量耗时的函数,你可以考虑用C扩展的方式实现它们。
41、评估检验(profile)你的代码。检验器会告诉你,代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序,评估检验总体上可以显示出代码的瓶颈。
42、mod_zip可作为Apache模块,用来即时压缩你的数据,并可让数据传输量降低80%。
43、在可以用file_get_contents替代file、fopen、feof、fgets等系列方法的情况下,尽量用 file_get_contents,因为他的效率高得多!但是要注意file_get_contents在打开一个URL文件时候的PHP版本问题;
44、尽量的少进行文件操作,虽然PHP的文件操作效率也不低的;
45、优化 Select SQL 语句,在可能的情况下尽量少的进行 Insert、Update 操作(在 update 上,我被恶批过);
46、尽可能的使用PHP内部函数(但是我却为了找个 PHP 里面不存在的函数,浪费了本可以写出一个自定义函数的时间,经验问题啊!);
47、循环内部不要声明变量,尤其是大变量:对象(这好像不只是PHP里面要注意的问题吧?)
48、多维数组尽量不要循环嵌套赋值
49、在可以用PHP内部字符串操作函数的情况下,不要用正则表达式
50、foreach 效率更高,尽量用 foreach 代替 while 和 for 循环
51、用单引号替代双引号引用字符串
52、用i+=1代替i=i+1。符合c/c++的习惯,效率还高
53、对 global 变量,应该用完就 unset( )掉

PHP各版本特性

发表于 2016-08-23

#PHP各版本特性

PHP5.6

  1. 可以使用表达式定义常量

    https://php.net/manual/zh/migration56.new-features.php
    在之前的 PHP 版本中,必须使用静态值来定义常量,声明属性以及指定函数参数默认值。 现在你可以使用包括数值、字符串字面量以及其他常量在内的数值表达式来 定义常量、声明属性以及设置函数参数默认值。

     f()."
     ";
     echo C::SENTENCE;
     ?> 
     
可以通过 const 关键字来定义类型为 array 的常量。
<pre>
<?php
const ARR = ['a', 'b'];
echo ARR[0];
?>
</pre>
  1. 使用 … 运算符定义变长参数函数

    现在可以不依赖 func_get_args(), 使用 … 运算符 来实现 变长参数函数。

      1
         [1] => 2
         [2] => 3
     )
     ?>
     
  2. 使用 ** 进行幂运算

    加入右连接运算符 来进行幂运算。 同时还支持简写的 = 运算符,表示进行幂运算并赋值。

     printf(2 ** 3); // 8
     $a = 2;
     $a **= 3;
     printf($a);  // 8
     
  3. use function 以及 use const

    use 运算符可以在类中导入外部的函数和常量了。 对应的结构为 use function 和 use const。

<?php
namespace NameSpace {
    const FOO = 42;
    function f() { echo __FUNCTION__.""; }
}
namespace {
    use const NameSpaceFOO;
    use function NameSpacef;
    echo FOO."";
    f();    
}
?>
  1. 加入 hash_equals() 函数,以恒定的时间消耗来进行字符串比较,以避免时序攻击

    <?php
    $expected = crypt(‘12345’, ‘$2a$07$usesomesillystringforsalt$’);
    $incorrect = crypt(‘1234’, ‘$2a$07$usesomesillystringforsalt$’);

    var_dump(hash_equals($expected, $incorrect)); // false
    ?>

  2. 加入 __debugInfo()
    当使用 var_dump() 输出对象的时候,可以用来控制要输出的属性和值。

     prop = $val;
         }
         public function __debugInfo() {
             return $this->prop;
         }
     }
     var_dump(new C(42));
     ?>
     

PHP 5.5

  1. 新增 Generators

    yield关键字用于当函数需要返回一个迭代器的时候,逐个返回值。
    function number10()
    {

    for($i = 1; $i <= 10; $i += 1)
        yield $i;
    

    } 该函数的返回值是一个数组:
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

  2. 新增 finally 关键字 Finally处理流程

  3. foreach 支持 list() foreach 支持通过 list() 将嵌套数组分离到单独的变量。

<?php
$array = [
    [1, 2],
    [3, 4],
];

foreach ($array as list($a, $b)) {
    echo $a.$b;
}
?>
  1. empty() 支持传入一个任意表达式,而不仅是一个变量

    <?php
    function always_false() {

    return false;
    

    }

    if (empty(always_false())) {

    echo 'This will be printed.';
    

    }

  2. 直接通过下标获取访问数组和字符串字面量的元素或字符

    echo [1, 2, 3][0]; // 1
    echo ‘PHP’[0]; // P

  3. 新的密码哈希 API

    缺点是缺乏互操作性,在需要和其他语言对接时会比较麻烦。
    //加密
    echo $hash = password_hash(‘rasmuslerdorf’, PASSWORD_DEFAULT);
    //输出结果类似于:$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

    //验证
    if(password_verify(‘rasmuslerdorf’,’$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a’)) {

    echo "密码正确";
    

    } else {

    echo "密码错误";
    

    }

  4. 新增 boolval() 函数

    PHP已经实现了strval、intval和floatval的函数。为了达到一致性将添加boolval函数。

  5. 新增 array_column() 函数

    可用来返回数组中指定的一列。
    $records = array(

    array('id' => 2135,'name' => 'John'),
    array('id' => 3245,'name' => 'Smith'),
    array('id' => 5342,'name' => 'Peter')
    

    );

    //从结果集中取出 name 列
    $names = array_column($records, ‘name’);
    print_r($names);

    //从结果集中总取出 name 列,用相应的 id 作为键值
    $names = array_column($records, ‘name’, ‘id’);
    print_r($names);

    PHP 5.4

  6. 新增 Traits
    // Traits不能被单独实例化,只能被类所包含
    trait SayWorld
    {

    public function sayHello()
    {
        echo 'World!';
    }
    

    }

    class MyHelloWorld
    {

    // 将SayWorld中的成员包含进来
    use SayWorld;
    

    }

    $xxoo = new MyHelloWorld();
    // sayHello() 函数是来自 SayWorld 构件的
    $xxoo->sayHello();

  7. 新增短数组语法

    // 原来的数组写法
    $arr = array(“key” => “value”, “key2” => “value2”);
    $arr = array(1,2,3,4);
    // 简写形式
    $arr = [“key” => “value”, “key2” => “value2”];
    $arr = [1,2,3,4];

  8. 新增支持对函数返回数组的成员访问解析

    print func()[0];

  9. 无论 php.ini 中是否设置 short_open_tag, 格式总是可用。

    这种简写形式被称为 Short Open Tag, 在 PHP5.3 起被默认开启,在 PHP5.4 起总是可用。 使用这种简写形式在 HTML 中嵌入 PHP 变量将会非常方便。

  10. 内置用于开发的 CLI 模式的 web server
    //启动Web服务器
    php -S localhost:8000
    //启动时指定根目录
    php -S localhost:8000 -t /home/me/public_html/foo
    //使用路由(Router)脚本
    php -S localhost:8000 index.php //所有的请求都会由index.php来处理。6、新增在实例化时访问类成员
    (new Foo)->bar();7、新增了动态访问静态方法的方式
    $func = “funcXXOO”;
    A::{$func}();

  11. 闭包支持 $this

  12. 新增二进制直接量

    $bin = bindec(110011); //之前需要这样写
    $bin = 0b110011;
    echo $bin; //51

  13. session提供了上传进度支持

    通过 $_SESSION[“upload_progress_name”] 就可以获得当前文件上传的进度信息,结合 Ajax 就能很容易的实现上传进度条。

  14. 默认使用 mysqlnd

    现在mysql, mysqli, pdo_mysql默认使用mysqlnd本地库,在PHP5.4以前需要:./configure –with-mysqli=mysqlnd
    现在:./configure –with-mysqli

  15. 让 json 更懂中文

    echo json_encode(“中文”, JSON_UNESCAPED_UNICODE);
    //“中文” 13、default_charset从ISO-8859-1已经变为UTF-8
    默认发送“Content-Type: text/html; charset=utf-8”

    PHP 5.3

    1、支持命名空间
    <?php
    namespace my
    ame; // 定义命名空间

class MyClass {}
const MYCONST = 1;

$a = new my
ameMyClass;
$class = NAMESPACE.’MyClass’;
$b = new $class;

$c = my
ameMYCONST;
$d = namespaceMYCONST;

var_dump($a,$b,$c,$d);
/
object(my
ameMyClass)#1 (0) {
}
object(my
ameMyClass)#2 (0) {
}
int(1)
int(1)
/
?>2、增加后期静态绑定
在PHP中,我们可以在类中通过self关键字或者CLASS来判断或调用当前类。但有一个问题,如果我们是在子类中调用,得到的结果将是父类。因为在继承父类的时候,静态成员就已经被绑定了。
class A
{
static public function callFuncXXOO()
{
print self::funcXXOO();
}

static public function funcXXOO()
{
    return "A::funcXXOO()";
}

}

class B extends A
{
static public function funcXXOO()
{
return “B::funcXXOO”;
}
}

$b = new B;
$b->callFuncXXOO();
//输出
A::funcXXOO() PHP 5.3.0中增加了一个static关键字来引用当前类,即实现了延迟静态绑定:
class A
{
static public function callFuncXXOO()
{
print static::funcXXOO();
}

// ...

}
// …
//这样就会像预期一样输出了:
B::funcXXOO
3、增加 goto 操作符
goto 语句有可能会导致程序流程不清晰,可读性减弱,但在某些情况下具有其独特的方便之处,例如中断深度嵌套的循环和 if 语句。
<?php
goto test;
echo ‘1’;

test:
echo ‘2’;
?>

//以上运行时会输出 2
4、添加了原生的闭包(Lambda/匿名函数)支持
https://php.net/manual/zh/functions.anonymous.php
5、新增两个魔术方法, callStatic 和 invoke
用静态方式中调用一个不可访问方法时,callStatic() 会被调用。
当尝试以调用函数的方式调用一个对象时,
invoke() 方法会被自动调用。
class A
{
public function invoke($str)
{
print “A::
invoke(): {$str}”;
}
}

$a = new A;
$a(“Hello World”);
//输出
A::__invoke(): Hello World6、添加 Nowdoc 语法支持
<?php
$str = <<<’EOD’
Example of string
spanning multiple lines
using nowdoc syntax.
EOD;
就象 heredoc 结构类似于双引号字符串,Nowdoc 结构是类似于单引号字符串的。Nowdoc 结构很象 heredoc 结构,但是 nowdoc 中不进行解析操作。
7、Heredoc 结构中可以用双引号来声明标识符了。
<?php
echo <<<”FOOBAR”
Hello World!
FOOBAR;
?>8、const 关键字可用来在类定义之外定义常量了
<?php
define(“CONSTANT_A”, “Hello world”);
const CONSTANT_B = ‘Hello World’; const 形式仅适用于常量,不适用于运行时才能求值的表达式:
// 正确
const XXOO = 1234;
// 错误
const XXOO = 2 * 617; 和使用 define() 来定义常量不同的是,使用 const 关键字定义常量必须处于最顶端的作用域,因为用此方法是在编译时定义的。即不能在函数内,循环内以及 if 语句之内用 const 来定义常量。

9、三元运算符可以简写省略中间的部分
表达式 expr1 ?: expr3 ,当 expr1 为 TRUE 时返回 expr1,否则返回 expr3。
10、异常可以嵌套了
<?php

class MyException extends Exception { }

class Test {
public function testing() {
try {
try {
throw new MyException(‘foo!’);
} catch (MyException $e) {
/ rethrow it /
throw $e;
}
} catch (Exception $e) {
var_dump($e->getMessage());
}
}
}

$foo = new Test;
$foo->testing();
?>11、可以动态访问静态变量了
<?php
class C {
public static $foo = 123;
}

$a = “C”;
echo $a::$foo;
?> 上边运行时输出:123
12、mail()函数支持记录发送日志了
在配置文件 php.ini 中可设置日志路径。参数名:mail.log
参考资料
https://php.net/manual/zh/migration53.new-features.php
https://php.net/manual/zh/migration54.new-features.php
https://php.net/manual/zh/migration55.new-features.php
https://php.net/manual/zh/migration56.new-features.php
http://segmentfault.com/a/1190000000403307
http://blog.csdn.net/heiyeshuwu/article/details/16884725
http://segmentfault.com/a/1190000002790818

loc容器

发表于 2016-08-22   |   分类于 PHP

loc容器

  1. superman类依赖 power类。在superman构造函数new power应用
    • 单一的依赖
  2. superman类又依赖了Flight类,Force类,Shot类
    • 产生了跟多的依赖
  3. 工厂模式,依赖转移!
    • 是由原来对多个外部的依赖变成了对一个 “工厂” 的依赖

      我们不应该手动在 “超人” 类中固化了他的 “超能力” 初始化的行为,而转由外部负责,由外部创造超能力模组、装置或者芯片等(我们后面统一称为 “模组”),植入超人体内的某一个接口,这个接口是一个既定的,只要这个 “模组” 满足这个接口的装置都可以被超人所利用,可以提升、增加超人的某一种能力。这种由外部负责其依赖需求的行为,我们可以称其为 “控制反转(IoC)”。
      `class SuperModuleFactory
      {
      public function makeModule($moduleName, $options)
      {
      switch ($moduleName) {

      case 'Fight':     return new Fight($options[0], $options[1]);
      case 'Force':     return new Force($options[0]);
      case 'Shot':     return new Shot($options[0], $options[1], $options[2]);
      // case 'more': .......
      // case 'and more': .......
      // case 'and more': .......
      // case 'oh no! its too many!': .......
      

      }
      }
      }`

    • 工厂模式的缺点就是:接口未知(即没有一个很好的契约模型,关于这个我马上会有解释)、产生对象类型单一。
  4. 为了规范每一个超能力,需要定义一个接口加以规范, 每一个类继承接口

    • 因为一个 对象(object) 本身是由他的模板或者原型 —— 类 (class) ,经过实例化后产生的一个具体事物,而有时候,实现统一种方法且不同功能(或特性)的时候,会存在很多的类(class),这时候就需要有一个契约,让大家编写出可以被随时替换却不会产生影响的接口。
    • 只要不是由内部生产(比如初始化、构造函数 __construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的,都属于 依赖注入(DI)
      // 超能力模组 $superModule = new XPower; // 初始化一个超人,并注入一个超能力模组依赖 $superMan = new Superman($superModule);

    • 手动的创建了一个超能力模组、手动的创建超人并注入了刚刚创建超能力模组

一个类需要绑定、注册至容器中,才能被“制造”。

个类要被容器所能够提取,必须要先注册至这个容器。既然 laravel 称这个容器叫做服务容器,那么我们需要某个服务,就得先注册、绑定这个服务到容器,那么提供服务并绑定服务至容器的东西,就是 服务提供者

服务提供者 将需要的类 注册绑定到服务容器
服务提供者主要分为两个部分,register(注册) 和 boot(引导、初始化),具体参考文档。register 负责进行向容器注册“脚本”,但要注意注册部分不要有对未知事物的依赖,如果有,就要移步至 boot 部分。

youzan

发表于 2016-08-22   |   分类于 个人感悟

在有赞的半年–规范

从今年的年初第二天上班加入了有赞的大家庭,到七月十五号辞职,虽然时间不长,但是这段时间自身成长了很多。为此我想回顾一下这几个月来的成长经历
有赞在大学里就听过这家公司,那时候还叫口袋通,只知道是在手机开店的工具,最后慢慢了解这是阿里团队出来的,看到招聘信息什么的全员配备macbook,感觉很是高大上对于还未踏入职场我来说。到大四下学期也曾投过有赞的简历,那时候可能因为简历没什么内容,自然也就石沉大海了,最终进了同花顺,在同花顺工作了一年,感觉每天都是在重复造轮子,没什么技术上的提升,之后投了有赞的简历,最后也是收到了有赞的offer,在15年过年前辞去了同花顺的工作。然后在过年春节放假回来加入了有赞。
刚进有赞就开始了新人班的培训,这大概是有赞的一大特色,每个新入职的小伙伴都会接受一次新人班培训,主要是公司的几个合伙人讲讲公司的企业文化啊,业务发展,产品方向,未来战略等等,当然在这期间还要开一家有赞的店铺,熟悉业务嘛。为期二周的新人培训我收获最多了是认识了一堆优秀的人,我是我们小组最小的,其他大多都是工作四五年有着牛逼的经历的人。有日本归国的ios开发,有从阿里出来的PHP开发十年经验的,有厉害的产品设计师,有浙大毕业的测试工程师,反正各个在我看来都是牛逼哄哄的,于是自己也默默地对自己说等我到他么那个年龄一定要比他们更牛X。
新人培训完了还有二天的户外拓展,对于初入职场的我来说是第一次参加这种活动,很多看似不可能完成的任务,最终都能完成。转变思维,挑战自己,终将能够达到目标。
在有赞主要负责商家版后台相关的开发,包括店铺的一些设置,商品的一些调整,以及服务市场的功能模块的开发等。在这里学习最多的就是规范,代码规范,开发流程规范等。
使用gitflow协作开发,一开始接触git对很多命令原理都不熟悉,师兄推荐我用sourcetree,git的GUi操作界面,但是有时不太理解其中的原理总会在代码合并上传的是否出一些错误,最后主管叫我使用命令行,不要再使用操作界面,然后我就默默练git的命令行,慢慢的就熟悉掌握了很多命令,这些绝对是使用图像界面学不到的。其实打心里还是很佩服哪些使用命令行的人,尤其使用vi作为编辑器的小伙伴。
代码的规范也是团队一直强调的,最重要的环节就是codereview,我想每一个有理想的团队都应该去做codereview,这非常有助于团队的代码质量的提升,让别人发现你代码的不规范的地方,逻辑不合理的地方。在你的代码上线前经过团队的codereview后,bug出现的概念也会大大降低。
项目开发的规范主要取决于项目的管理,有赞有一只研发效率团队负责公司整体的项目开发进度控制,项目立项,PM,每日站会,看板,燃尽图,这些保障了项目如期上线。确实很多东西只有规范起来,才能有序高效的进行,不然一团乱麻,很难达到理想的状态。
有你有赞!

1234
周强

周强

个人站

32 日志
11 分类
16 标签
GitHub 知乎
Links
  • 个人站
  • laravel博客
  • 校园QA
© 2015 - 2016 周强
由 Hexo 强力驱动
主题 - NexT.Muse