ModernPHP读书笔记(三)——PHP的良好实践
(原创内容,转载请注明来源,谢谢)
一、密码
1、密码不宜用明文存储,也不能用可以解密的方式进行存储;找回密码功能,给用户发送的邮件也应是发送令牌至邮箱,不应直接把原密码发送过去。
2、PHP5.5.0有原生的密码哈希API,可以对密码加密、解密、重加密。
加密方式:password_hash($password,PASSWORD_DEFAULT, $cost)
,第一个参数是原密码,第二个参数是加密方式,默认使用bcrypt,第三个参数是bcrypt的加密长度。
注:根据密码学的专家研究,发现bcrypt加密较为安全,当计算机硬件处理速度加快时,只需要提高cost的值即可保证安全。但是该加密方式加密速度较慢,其他加密方式还有md5、SHA1等。
验证密码方式:password_verify($password,$passwordHash)
,第一个参数为输入的密码,第二个参数为password_hash
的加密结果。
重新加密方式:password_needs_refresh()
。
3、在PHP5.5.0版本之前,可以用ircmaxell/password_compat
组件,该组件实现了上述三个函数,功能完全一样。
二、日期与时间
1、php.ini文件内可以设置默认时区,字段date.timezone = ‘Asia/Shanghai’
2、DateTime类
该类可以生成时间的实例,如$datetime= new DateTime()
3、DateInterval类
该类用于生成一段的时间示例,用于配合DateTime类的add、sub方法。
例:$datetime =new DateTime(‘2017-07-12 08:00:00’);
$interval= new DateInterval(‘P1Y’);
$datetime->add($interval);//实现加一年的功能
用法总结:构造DateInterval实例时,传入一个字符串参数,P开头,加上数组,再加上特殊字符。特殊字符包括YMDWHIS,分别表示年月日周时分秒。
4、DateTimeZone类
用于设置DateTime实例的时区。
例:$datetime =new DateTime(‘2017-07-12 08:00:00’);
$datetime->setTimeZone(newDateTimeZone(‘Asia/Shanghai’));
5、DatePeriod类
配合DateTime以及DateInterval类的实例,生成从DateTime开始时间,经过若干DateInterval,到一个指定的结束时间的实例。
三、数据库
1、数据库的配置文件不宜放置在项目中,如host、用户名、密码之类,如果放在项目中不慎被用户看到,可能造成严重后果。最好在项目根目录之外,写好一个配置文件,再用项目去include。
2、采用PDO的方式使用数据库,可以比较用到其占位符功能,比较安全。
例:
include(‘../sql_setting.php’);//根目录之外的配置文件,配置用户名密码等值
//第一步,用PDO连接数据库,其中的各关键信息,都存于sql_setting.php文件中,文件定义$sets = array(‘host’=>xxx,’dbname’=>xxx……)
$pdo= new PDO(
sprint(‘mysql:host=%s;dbname=%s;port=%s;charset=%s;’,
$sets[‘host’],$sets[‘dbname’],$sets[‘port’],$sets[‘charset’]),
$sets[‘user’],$sets[‘pwd’]
);
//第二步,构造查询,需要查询的关键内容用冒号加一个词语引入
$sql = ‘ selectname from db_users where email = :email ’;
$result =$pdo->prepare($sql);
//第三步,词语过滤与绑定
$email =filter_input($_POST[‘email’], ‘email’);
$result->bindValue(‘:email’,$email);
//第四步,执行查询
$result->execute();
3、获取查询结果共有4种方式。
1)fetch:获取下一行的内容,结果以“列名-列值”的数组键值对形式存储。该方式逐行获取查询结果,可以节约内存。
例:接上述代码
whild($sqlResult= $result->fetch())
2)fetch_all:该方式一次性获取全部结果,存储方式fetch,在结果集比较小的时候可以用,但是结果较多不建议使用。
3)fetch_column:获取指定列的结果,0为第一列。
4)fetch_object:把结果获取成类的形式。
四、多字节字符串
1、如中文等文字,都是多字节字符串,与默认的英文用8位字符存储方式不等。因此,用常用的字符串处理函数(如strlen()等函数)进行处理时,会得到错误的结果。
2、为了解决上述问题,PHP的mbstring扩展支持多字符处理,mb_strxxx可以代替原来的str开头的函数,如mb_strlen用于计算字符串长度等。
3、字符串转码函数
mb_convert_encoding(),在出现乱码时使用此将UTF-8和gbk互相进行转换可以解决问题。
五、流
1、流封装协议
流相当于一个管道,实现两头的通讯,如服务器之间、文件之间等。使用的函数包括fopen、fwrite、fgets、file_get_contents等。
协议采用“协议名://协议内容与路径”的方式。PHP默认的协议是file://,因此通常用fopen打开文件时,只需要写fopen(‘路径’),不用加上file://。但是如果用到http、php等其他协议,就需要加。
2、流上下文
file_get_contents函数是用于获取网页的内容,但是可以通过使用函数stream_context
_create,实现file_get_contents发送post请求。
例:
//第一步:构造json
$request= ‘{“username”:”lin”}’;
//第二步:拼接请求字段
$context= stream_context_create(
array(
‘http’ => array(
‘method’ => ‘POST’,
‘header’=> ‘context-Type:application/json;charset=utf-8;\r\n0\’.
‘context-length’.mb_strlen($request),
‘content’=> $request
)
)
);
//第三步:发送POST请求
$response =file_get_contents($url, false, $context);//url为自定义要发送请求的路径
3、流过滤器
使用stream_filter_append()函数,可以在文件打开后加以过滤。
4、自定义过滤器
需要扩展PHP的php_user_filter类,并且要实现filter、onCreate、onCLose方法,在通过stream_filter_register函数进行注册。
——written by linhxx 2017.07.12