PHP7之后提供了类似上下文概念,如下代码:
function open($file, $mode = 'r'){
$f = fopen($file, $mode);
yield $f;
fclose($f);
}
此函数用的是生成器,我们可以使用foreach循环,只需循环一次。
foreach(open('output.txt','w') as $file)
{
fwrite($file,'Hello World!');
}
程序员需要构建自己的上下文管理器,这是确保自己清理的一种更简洁的方法。
下一步举个例子,例如要使用PDO连接。首先连接到数据库,在事务中执行一些工作,然后自动提交结果。
类似如下代码:
try
{
$dbh = new PDO($dsn, $user, $pass, $options);
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into users (id, name, wechat) values (5, 'Eric', 'ericlu')");
$dbh->exec('insert into authors (id) values (5)');
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
换用上下文管理器进行相同的操作,代码则要简单很多:
function transaction()
{
$dbh = new PDO($dsn, $user, $pass, $options);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
yield $dbh;
try {
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
}
}
// Now use the transaction
foreach(transaction() as $dbh) {
$dbh->exec("insert into users (id, name, wechat) values (5, 'Eric', 'ericlu')");
$dbh->exec('insert into authors (id) values (5)');
}
这比第一个示例要复杂。
要点是数据库连接和事务的安装和卸载都发生在dtransaction()外,这里的函数可以和代码的其余部分位于单独的文件或命名空间中,从而使代码执行逻辑保持简洁,不必担心安装/卸载。
另外,在以上例子中使用Iterator接口的ContextManager对象加一个析构函数,对异常处理会更加强壮。
文件、数据库与资源的远程连接,锁,线程这些都是密集型的操作,使用上下文模式则会让代码更简洁,运行更流畅。
在Python和很多语言都利用了此模式。
这是一种让你的PHP代码更有作为的一种模式。诚然,它与以前的编写PHP的方式有些不同,也更加让人耳目一新。
网友评论