- PHP 5.3: security fixes only
- PHP 5.4: old stable
- PHP 5.5: stable
- PHP 5.6: the mysterious future
[short, array, syntax]
register_globals
yield
xrange()
class RangeIterator implements Iterator {
private $start;
private $limit;
private $step;
private $current;
public function __construct($start, $limit, $step = 1) {
$this->start = $start;
$this->limit = $limit;
$this->step = $step;
$this->current = $start;
}
public function current() {
return $this->current;
}
public function key() {
return ($this->current - $this->start) / $this->step;
}
public function next() {
$this->current += $this->step;
}
public function rewind() {
$this->current = $this->start;
}
public function valid() {
return ($this->current >= $this->start && $this->current <= $this->limit);
}
}
function xrange($start, $limit, $step = 1) {
return new RangeIterator($start, $limit, $step);
}
function xrange($start, $limit, $step = 1) {
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
}
function xrange($start, $limit, $step = 1) {
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
}
foreach (xrange(1, 9, 2) as $number) {
echo "$number\n";
}
1
3
5
7
9
(yield $key => $value);
yield;
function xrange($start, $limit, $step = 1) {
for ($i = $start; $i <= $limit; $i += $step) {
$command = (yield $i);
if ($command == 'stop') {
return;
}
}
}
$gen = xrange(1, 9, 2);
foreach ($gen as $number) {
echo "$number\n";
$gen->send('stop');
}
1
function this_week() {
$date = new DateTimeImmutable('6 days ago');
$now = new DateTimeImmutable;
while ($date <= $now) {
$formatted = $date->format('Y-m-d');
(yield $date => $formatted);
$date = $date->add(new DateInterval('P1D'));
}
}
foreach (this_week() as $dt => $formatted) {
echo $dt->format(DateTime::ISO8601)."\n";
}
function this_week() {
$date = new DateTimeImmutable('6 days ago');
$now = new DateTimeImmutable;
while ($date <= $now) {
$formatted = $date->format('Y-m-d');
(yield $date => $formatted);
$date = $date->add(new DateInterval('P1D'));
}
}
2013-11-02T07:18:59-0700
2013-11-03T07:18:59-0800
2013-11-04T07:18:59-0800
2013-11-05T07:18:59-0800
2013-11-06T07:18:59-0800
2013-11-07T07:18:59-0800
2013-11-08T07:18:59-0800
finally
finally
function do_something() {
$temp = tempnam('/tmp', 'foo');
try {
...
unlink($temp);
} catch (FrameworkException $e) {
...
unlink($temp);
} catch (Exception $e) {
unlink($temp);
throw $e;
}
}
finally
class TemporaryFile {
function __construct($directory, $prefix) {
$this->file = tempnam($directory, $prefix);
}
function __destruct() { unlink($this->file); }
function __toString() { return $this->file; }
}
function do_something() {
$temp = new TemporaryFile('/tmp, 'foo');
try { ... }
catch (FrameworkException $e) { ... }
}
finally
function do_something() {
$temp = tempnam('/tmp', 'FOO');
try {
...
} catch (FrameworkException $e) {
...
} finally {
unlink($temp);
}
}
finally
function f() {
try {
return 'try';
} finally {
return 'finally';
}
}
echo f();
finally
crypt()
echo crypt('foo', '$2a$01234567890123456789a');
$2zJyhpjk3l9E
password_hash($password, $algo, $options)
password_verify($password, $hash)
password_get_info($hash)
password_needs_rehash($hash, $algo, $options)
// Creating a hash:
$hash = password_hash($passwd, PASSWORD_DEFAULT);
// Verifying a password:
if (password_verify($passwd, $hash)) {
// do stuff
}
$2y$10$6z7GKa9kpDN7KC3ICW1Hi.fdO/to7Y/x36WUKNPOIndHdkdR9Ae3K
$2y$10$6z7GKa9kpDN7KC3ICW1Hi.fdO/to7Y/x36WUKNPOIndHdkdR9Ae3K
Hash type
$2y$10$6z7GKa9kpDN7KC3ICW1Hi.fdO/to7Y/x36WUKNPOIndHdkdR9Ae3K
Hash options
$2y$10$6z7GKa9kpDN7KC3ICW1Hi.fdO/to7Y/x36WUKNPOIndHdkdR9Ae3K
Randomly generated salt
$2y$10$6z7GKa9kpDN7KC3ICW1Hi.fdO/to7Y/x36WUKNPOIndHdkdR9Ae3K
Hashed data
PASSWORD_DEFAULT
is equivalent to PASSWORD_BCRYPT
right nowpassword_hash()
hashes are forward compatiblePASSWORD_DEFAULT
may change in new versions
// Verifying a password:
if (password_verify($passwd, $hash)) {
// do stuff
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
// rehash with password_hash() and save
}
}
password_compat
zend_extension=${extension_dir}/opcache.so
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1
http://php.net/opcache.installation
5.4 | 5.5 | 5.5 + OPcache | |
---|---|---|---|
php.net | 78.77 | 77.23 | 134.09 |
Laravel 4.0.9 | 30.07 | 29.51 | 161.83 |
WordPress 3.7.1 | 9.27 | 9.44 | 31.66 |
foreach
unpacking
$array = [[1, 2], [3, 4]];
foreach ($array as $item) {
list($a, $b) = $item;
// ...
}
foreach
unpacking
$array = [[1, 2], [3, 4]];
foreach ($array as list($a, $b)) {
// ...
}
empty()
empty(my_function());
var_dump([1, 2, 3][0]);
var_dump('PHP'[0]);
var_dump([1, 2, 3][0]);
var_dump('PHP'[0]);
1
P
::class
namespace Name\Space;
class ClassName {}
echo ClassName::class;
::class
namespace Name\Space;
class ClassName {}
echo ClassName::class;
Name\Space\ClassName
DateTime
DateTimeImmutable
add()
, modify()
and sub()
return a new object
DateTime
$dbh->lastInsertId();
$dbh->lastinsertid();
$dbh->lastınsertıd();
function función() {}
FUNCIÓN();
pack()
and unpack()
a
and A
format codes behave like Perl nowZ
for the old behaviourmysql_connect()
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead
$db = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('db', $db);
$id = mysql_real_escape_string($_GET['id'], $db);
$st = mysql_query("SELECT name FROM user WHERE id = $id");
while ($row = mysql_fetch_assoc($st)) {
echo "Hi, $row[name]!";
}
$db = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('db', $db);
$id = mysql_real_escape_string($_GET['id'], $db);
$st = mysql_query("SELECT name FROM user WHERE id = $id");
while ($row = mysql_fetch_assoc($st)) {
echo "Hi, $row[name]!";
}
$db = new PDO('mysql:host=localhost;dbname=db', 'user', 'pass');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$st = $db->prepare('SELECT name FROM user WHERE id = :id');
$st->execute(['id' => $_GET['id']]);
while ($row = $st->fetch(PDO::FETCH_ASSOC)) {
echo "Hi, $row[name]!";
}
preg_replace()
/e
modifier
preg_replace(
'(<h([1-6])>(.*?)</h\1>)e',
'"<h$1>" . strtoupper("$2") . "</h$1>"',
$html
);
preg_replace()
/e
modifier
preg_replace_callback(
'(<h([1-6])>(.*?)</h\1>)',
eval('"<h$1>" . strtoupper("$2") . "</h$1>"'),
$html
)
preg_replace()
/e
modifier
preg_replace_callback(
'(<h([1-6])>(.*?)</h\1>)',
eval('"<h$1>" . strtoupper("$2") . "</h$1>"'),
$html
)
preg_replace()
/e
modifier
preg_replace_callback(
'(<h([1-6])>(.*?)</h\1>)',
function (array $matches) {
return "<h$matches[1]>"
.strtoupper($matches[2])
."</h$matches[1]>";
},
$html
)
apt-get build-dep php5
is your friend on Debian-based distros
function query($query, ...$params) {
foreach ($params as $param) {
$this->setParameter($param);
}
}
function query($query, DateTime ...$params) {
foreach ($params as $param) {
$this->setParameter($param);
}
}
function query($query, DateTime &...$params) {
foreach ($params as $param) {
$this->setParameter($param);
}
}
class A {
function foo() { // $this is B, not A }
}
class B {
function bar() { A::foo(); }
}
(new B)->bar();
Deprecated: Non-static method A::foo() should not be called statically, assuming $this from incompatible context