资讯专栏INFORMATION COLUMN

PHP|开发必知的良好实践

bingo / 1465人阅读

摘要:使用类来管理日期和时间使用类来构造长度固定的时间段。时区的处理选择。预处理语句时的实例。简单而言,流是具有流式行为的资源对象。流的作用实际上是在出发地和目的地之间传输数据。错误由于某种原因导致无法运行,通常会触发错误。

过滤、验证、转义

所有这些外部资源都不能完全相信

$_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


预处理语句

为了防止SQL注入,使用PDO的预处理语句。

预处理语句时PDOStatement的实例。可以通过PDO实例的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原生的函数。

关于字符编码

一定要知道数据的字符编码

使用UTF8存储数据

使用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:// 流封装协议

file_get_contents

fopen

fwrite

fclose


php://流封装协议

php://stdin

php://stdout

php://memory

php://temp

自己编写流封装协议

PHP提供了一个示例streamWrapper类,编写自定义的流封装协议。

http://php.net/manual/class.streamwrapper.php

http://php.net/manual/stream.streamwrapper.example-1.php

流上下文

有些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由于某种原因导致无法运行,通常会触发错误。

我们可以使用

trigger_error()

自己触发错误。

我们可以使用

error_reporting()

或者php.ini中使用error_reporting指令,告诉PHP如何处理错误。

一定要遵守下述四个原则

一定要让PHP报告错误

在开发环境中显示错误

在生产环境中不能显示错误

都要记录错误

php.ini中:

//Dev
display_startup_errors = On
display_errors = On

error_reporting = -1
log_errors = On

//Prod
display_startup_errors = Off
display_errors = Off

error_reporting = E_ALL & ~E_NOTICE
log_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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21646.html

相关文章

  • 前端工程师知的性能优化技巧

    摘要:网站性能类似于二八定律,其中的优化将带来网站的性能提升。代码重用最大的性能缺陷之一是文件大小过大和不必要的浏览器呈现。最大程度上减少文件大小的快速方法就是尽可能多地重用样式。此外,图像可能被压缩,删除任何不必要的注释和颜色配置文件。 性能与组织 当能够扎实的理解并编写HTML和CSS这门专业知识。随着网站代码量和流量的增长,另一种新技能也开始发挥作用,这对于开发效率和用户体验都至关重要...

    crelaber 评论0 收藏0
  • 前端工程师知的性能优化技巧

    摘要:网站性能类似于二八定律,其中的优化将带来网站的性能提升。代码重用最大的性能缺陷之一是文件大小过大和不必要的浏览器呈现。最大程度上减少文件大小的快速方法就是尽可能多地重用样式。此外,图像可能被压缩,删除任何不必要的注释和颜色配置文件。 性能与组织 当能够扎实的理解并编写HTML和CSS这门专业知识。随着网站代码量和流量的增长,另一种新技能也开始发挥作用,这对于开发效率和用户体验都至关重要...

    DTeam 评论0 收藏0
  • 从零开始建网站,新手小白建站知的十大忠告

    摘要:对于从零开始建网站的新手,知道下面十大忠告,可以少走弯路,早日走上康庄大道。阿里云自助建站平台支持快速备案建一个手机网站手机网站具有让消费者随时随地随身访问的优势和方便快捷的不可取代的特点。对于从零开始建网站的新手,知道下面十大忠告,可以少走弯路,早日走上康庄大道。 1、一定要做网站规划方案   一个网站的成功与否与建站前的网站规划有着极为重要的关系。在建立网站前应明确建设网站的目的,确定网...

    0x584a 评论0 收藏0

发表评论

0条评论

bingo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<