PHP|开发必知的良好实践
过滤、验证、转义
所有这些外部资源都不能完全相信
$_GET
$_POST
$_REQUEST
$_COOKIE
$argv
php://stdin
php://input
file_get_contents()
远程数据库
远程API
客户端的数据
过滤
使用htmlentities()过滤HTML,将特殊字符转换为HTML实体,转义输出,第二个参数使用ENT_QUOTES。
使用PDO预处理语句过滤SQL注入.
使用filter_var() & filter_input()函数来过滤和验证不同类型的输入。
Eg: email, number, char, 特殊字符
密码
最安全的哈希算法:bcrypt
使用:
password_hash()password_get_info()password_needs_rehash()password_verify()
函数来生成密码。
日期,时间,时区
使用PHP5.2.0引入的DateTime & DateInterval & DateTimeZone类来处理时间。
设置默认时区
在php.ini中,设置
date.timezone = 'country/city'
使用date_default_timezone_set()函数来设置默认时区。
DateTime Class
使用DateTime类来管理日期和时间
$datetime = new DateTime();
使用DateInterval类来构造长度固定的时间段。配合上一个类中的方法使用。
DateTimeZone Class
时区的处理选择。
$timezone = new DateTimeZone('Asia/Shanghai');$datetime = new DateTime('2016-05-20', $timezone);$datetime->setTimezone(new DateTimeZone('Asia/Hong_Kong'));
有时,我们需要迭代处理一段时间内反复出现的一系列日期和时间,重复在日程表中记事就是个好例子。DatePeriod类可以解决这种问题
DatePeriod实例就是迭代器,每次迭代会产出一个DateTime实例。
format('Y-m-d H:i:s'), PHP_EOL;}
DB
PDO扩展
http://php.net/manual/zh/pdo.drivers.php
prepare()方法获取与处理语句对象。
$sql = "select id from users where email = :email";
$statement = $pdo->prepare($sql);
$email = filter_input(INPUT_GET, 'email');
$statement->bindValue(':email', $email);
http://php.net/manual/pdo.constants.php继续:
$statement->execute();
while (($result = $statement->fetch(PDO::FETCH_ASSOC)) !== false) {
echo $result['email'];
}
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $result) {
echo $result['email'];
}
### PDO的事务
try {
$pdo = new PDO();
}catch(PDOExcetion $e){
//
}
$stmtSubtract = $pdo->prepare('
UPDATE accounts
SET amount = amount - :amount
WHERE name = :name
');
$stmtAdd = $pdo->prepare('
UPDATE accounts
SET amount = amount + :amount
WHERE name = :name
');
$pdo->beginTransaction();
$fromAccount = 'Checking';
$withdrawal = 50;
$stmtSubtract->bindParam(':name', $fromAccount);
$stmtSubtract->bindParam(':amount', $withDrawal, PDO::PARAM_INT);
$stmtSubtract->execute();
$toAccount = 'Savings';
$deposit = 50;
$stmtSubtract->bindParam(':name', $$toAccount);
$stmtSubtract->bindParam(':amount', $deposit, PDO::PARAM_INT);
$stmtSubtract->execute();
$pdo->commit();
## 多字节字符串PHP假设字符串中的每个自负都是八位字符,占一个字节的内存。然而考虑到国家化的时候,一个字符就不只占用一个字节了。为了避免处理多字节字符串出错,可以安装mbstring扩展。替换PHP原生的函数。关于字符编码1. 一定要知道数据的字符编码1. 使用UTF8存储数据1. 使用UTF8输出数据在php.ini中设置,告诉PHP使用UTF8:
default_charset = "UTF-8";
很多PHP函数都使用这个默认的字符集:
htmlentities()
html_entity_decode()
htmlspecialchars()
以及mbstring中的扩展函数
## 流流在PHP4.3.0中引入,作用是使用统一的方式处理文件,网络和数据压缩等共用同一套函数和用法的操作。简单而言,流是具有流式行为的资源对象。因此,流可以线性读写,或许还能使用fseek()函数定位到流中的任何位置。流的作用实际上是在出发地和目的地之间传输数据。出发地和目的地可以是文件,命令行进程,网络连接,zip, TAR压缩, 临时内存,标准输入输出,或者是通过php流封装协议实现的资源(http://php.net/manual/wrappers.php)### 流封装协议http://php.net/manual/wrappers.php流封装协议的作用是使用通用的接口封装读写文件系统的差异。每个流都有一个协议和目标
://
#### file:// 流封装协议1. file_get_contents1. fopen1. fwrite1. fclose
php://stdin
php://stdout
php://memory
php://temp
自己编写流封装协议
PHP提供了一个示例streamWrapper类,编写自定义的流封装协议。
流上下文
有些PHP流能接受一系列可选的参数,这些参数叫流上下文,用于定制流的行为。
使用
stream_context_create()
函数创建。
[ 'method' => 'POST', 'header' => "", 'content' => $requestBody, ],]);$response = file_get_contents('http://x/xapi', false, $context);
流过滤器
把过滤器附加到现有的流上,使用
stream_filter_append()
php://filter流协议把过滤器附加到流上。
$handle = fopen('php://filter/read=string.toupper/resource=data.txt', 'rb');
while () {
}
filter/read=/resource=://
我们还可以使用php_user_filter类来自定义流过滤器http://php.net/manual/en/class.php-user-filter.php
class DirtyWordsFilter extends php_user_filter
{
public function filter($in, $out, &$consumed, $closing)
{
$words = ['grime', 'dirt', 'grease'];
$wordData = [];
foreach ($words as $word) {
$replacement = array_fill(0, mb_strlen($word), '*');
$wordData[$word] = implode('', $replacement);
}
$bad = array_keys($wordData); $good = array_values($wordData); while ($bucket = stream_bucket_make_writeable($in)) { $bucket->data = str_replace($bad, $good, $bucket->data); $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } return PSFS_PASS_ON;}
}
然后,我们使用stream_filter_register()函数注册这个自定义的流过滤器
stream_filter_register('dirty_words_filter', 'DirtyWordsFilter');
## 异常处理示例
try {
//
} catch (PDOException $e) {
} catch (Exception $e) {
// 捕获除了PDOException之外的所有异常
} finally {
// 最终执行
}
### 异常处理程序PHP允许我们注册一个全局异常处理程序,捕获所有未被捕获的异常。
set_exception_handler(function (Exception $e) {
//
});
在某些情况下,代码执行完毕后,还需要还原成前一个异常处理程序。
restore_exception_handler()
php.ini中使用error_reporting指令,告诉PHP如何处理错误。
一定要遵守下述四个原则
一定要让PHP报告错误
在开发环境中显示错误
在生产环境中不能显示错误
都要记录错误
php.ini中:
//Devdisplay_startup_errors = Ondisplay_errors = Onerror_reporting = -1log_errors = On//Proddisplay_startup_errors = Offdisplay_errors = Offerror_reporting = E_ALL & ~E_NOTICElog_errors = On
错误处理的函数
set_error_handler(function ($error, $errstr, $errfile, $errline) { // Process error})
我们也可以把PHP的错误转换为异常
只能转换满足php.ini中error_reporting指令设置的错误
set_error_handler(function ($errno, $errstr, $errfile, $errline) { if (!(error_reporting() & $errno)) { return } throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);});
参考
- Modern PHP
关键字:php
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!