Destructing PHP
Johannes Schlüter
johannes@php.net
@johannescode
function foo($db, $data) {
$db->beginTransaction();
foreach ($data as $row) {
$db->insert($row);
}
$db->commit();
}
Exception Safety
Exception Safety
- No Exception Safety
- Basic Exception Safety (no-leak guarantee, might have side-effects)
- Strong Exception Safety (commit/rollback semantics, no side effects)
- No-throw Guarantee
(David Abrahams)
function foo($db, $data) {
$db->beginTransaction();
try {
foreach ($data as $row) {
$db->insert($row);
}
} catch(\Exception $e) {
$db->rollback();
throw $e;
}
$db->commit();
}
function runInTransaction($db, $cb) {
$db->beginTransaction();
try {
$cb();
} catch(\Exception $e) {
$db->rollback();
throw $e;
}
$db->commit();
}
function foo($db, $data) {
runInTransaction($db, function ()
use($db, $data) {
foreach ($data as $row) {
$db->insert($row);
}
});
}
function foo($db, $data) {
$transaction = new Transaction($db);
foreach ($data as $row) {
$db->insert($row);
}
$transaction->commit();
}
Deterministic Destructors!
class Transaction {
private $db;
private $success = false;
function __construct($db) {
$this->db = $db;
$db->begin();
}
function commit() {
$this->db->commit();
$this->success = true;
}
function __destruct() {
if (!$this->success) {
$this->db->rollback();
}
}
}
RAII
RAII
Resource Acquisition Is Initialization
YAY C++ \o/
Reference Counting
function foo() {
$a = new A();
$b = $a;
}
function a() {
try {
b();
} catch (\Exception $e) {
Logger::error($e);
}
}
function b() {
$o = new O();
c();
}
function c() {
throw new \Exception();
}
What else?
Ensure Usage of Return Value
echo expensiveCalculation(); // works
$a = expensiveCalculation();
unset($a); // will complain
class EnforceUsage {
private $value;
private $used = false;
function __construct($value) {
$this->value = $value;
}
function __toString() {
$this->used = true;
return (string)$this->value;
}
function __destruct() {
if (!$this->used) {
Logger::notice("Return value not used");
}
}
}
Useful? - Maybe ...
Short Rant
JAVA
A language built around non-deterministic Garbage Collection
finally
Java's initial solution
(no Java invention - at leat Object Pascal and Modula had finally before)
void foo(Database db, Object data) {
boolean success = false;
db.beginTransaction();
try {
db.insert(data);
db.commit();
success = true;
} finally {
if (!success) {
db.rollback();
}
}
}
Java 7
introduced try-with-resources
http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try (Transaction t =
new Transaction(db) {
db.insert();
t.commit();
}
So what does PHP do?
Introduce finally
In PHP 5.5
Destructors Are Powerful!
Know Your Language!
Thank You
Johannes Schlüter
johannes@php.net
@johannescode
https://slides.com/johannes4321/froscon15