小池有话说

PHP 语法糖, 闭包和反射

2014-12-26

empty(func()); // not before 5.4

return_array()[3]; // not before 5.4

(new Foo())->doSomething(); // not before 5.4

闭包

<% highlight php %> function foo() { $a = 3; $c = 4; $func = function($b) use ($a, &$c) { // … $c = 5; } } <% endhighlight %>

反射(元编程)

不要用反射类了, 过时了

$class = 'PDO'; // 类名, 函数名和方法名不区分大小写, 变量名区分大小写, wtf
$pdo = new $class(); // namespace要写全
$method = "prepare";
$pdo->$method($sql);

get_class_methods('Pdo');
get_class_methods($pdo);

当然, 方法也是可以动态调用的

call_user_func('array_unshift', $arr, $e);

$a = [1, 2, 3, 4];
$b = [1, 4, 9, 16];
$c = [1, 16, 81, 256];
$args = [$a, $b, $c];
$combine_func = function() {return implode(' => ', func_get_args());};
array_unshift($args, $combine_func);
$a = call_user_func_array('array_map', $args);

call_user_func(function(){});

call_user_func([$pdo, 'prepare'], $sql); // $pdo->{'prepare'}($sql);

forward_static_call(['Pdo', 'getAvailableDrivers']);
$class::$method(); // more Semantic

有些看似很像function的, 但不是

array(), echo, empty(), eval(), exit(), isset(), list(), print or unset()

多个返回值

list($a, $b) = [$b, $a];

变量也是可以动态访问的

$name = 'foo';
$$name = 'bar';
var_dump($foo);

你可能会有疑问, 这个会有什么用呢?

来看一个真实的例子, 取自 编程中的“末行效应”

intens.x=OrSIMD(AndSIMD(BackgroundColor.x,no_hit_mask),
                AndNotSIMD(no_hit_mask,intens.x));
intens.y=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
                AndNotSIMD(no_hit_mask,intens.y));
intens.z=OrSIMD(AndSIMD(BackgroundColor.y,no_hit_mask),
                AndNotSIMD(no_hit_mask,intens.z));

程序员忘记把最后一行的中的“BackgroundColor.y”改成“BackgroundColor.z”

所以我推荐这样写

foreach([‘x’, ‘y’, ‘c’] as $prop) intens->$prop = OrSIMD(AndSIMD(BackgroundColor->$prop,no_hit_mask), AndNotSIMD(no_hit_mask,intens->$prop));

这样, 如果你错, 就错一大片, 不至于测不出来

可变参数 (override)

在 Java 中实现的很优雅

public void prop(String key); // get
public void prop(String key, String value); // set

在PHP中就比较丑陋, 和 JS 中一样

function prop($key)
{
    if (func_num_args() === 1) {
        // get
    } else {
        $value = func_get_arg(1);
        // set
    }
}

类型

PHP 不支持类型声明, 但…

类型转换

intval() // $n="19.99";intval($n*100); // prints 1998 // round()
boolval()
doubleval(), floatval()
strval()

(array)

类型判断

get_type(),
is_int(), is_long(), is_integer()
is_array()
is_bool()
is_double(), is_float(), is_real()
is_null() // prefer === null
is_object()
is_string()
is_callable()
is_numeric()
is_resource()
is_scalar()

序列化

serialize() 和 unserialize() 但用json_decode()和json_encode() 也可以.

var_export($var, true) 生成可以被PHP解析的代码.


专辑: