10

解释

PHP 在其语法中存在一些漏洞,在开发过程中,程序员偶尔会介入其中。这可能会导致很多挫败感,因为这些语法漏洞似乎无缘无故地存在。例如,不能轻易地创建一个数组并在同一行访问该数组的任意元素(func1()[100]不是有效的 PHP 语法)。此问题的解决方法是使用临时变量并将语句分成两行,但有时这会导致非常冗长、笨拙的代码。

挑战

我知道其中一些漏洞(我相信还有更多)。甚至很难想出一个解决方案,更不用说代码高尔夫风格了。获胜者是所有四个语法孔中字符总数最少的人。

规则

  1. 语句必须是这种形式的一行:$output = ...;,其中...不包含任何;'s。
  2. 只使用标准库函数(不允许自定义函数eval
  3. 语句的工作方式与假定的非工作语法的功能相同(即使在它失败的情况下)。
  4. 语句必须在没有任何类型的语法错误的情况下运行E_STRICT | E_ALL

语法漏洞

  1. $output = func_return_array()[$key];- 访问函数返回数组的任意偏移量(string或)integer
  2. $output = new {$class_base.$class_suffix}();- 用于创建新类的任意字符串连接
  3. $output = {$func_base.$func_suffix}();- 任意字符串连接被称为函数
  4. $output = func_return_closure()();- 调用从另一个函数返回的闭包
4

2 回答 2

8

我看到的唯一解决方案涉及一个临时变量,因此存在一些(最小的)命名空间污染。任何收紧临时变量代码的方法都会缩短所有这四个:

<?php

error_reporting(E_ALL | E_STRICT);

// 1
function func_return_array() { return array(0 => 'hello'); }
$key = 0;

$output = ${!${''}=func_return_array()}[$key];

echo '1: ' . $output . "\n";


// 2
class Thing {}
$class_base = 'Thi'; $class_suffix = 'ng';

$output = new ${!${''}=$class_base.$class_suffix}();

echo '2: ';
var_dump($output);


// 3
$func_base = 'func_'; $func_suffix = 'return_array';

$output = ${!${''}=$func_base.$func_suffix}();

echo '3: ';
var_dump($output);


// 4
function func_return_closure() {
    return function() {
        return 'This is a closure';
    };
}

$output = ${!${''}=func_return_closure()}();

echo '4: ';
var_dump($output);

输出:

1: hello
2: object(Thing)#1 (0) {
}
3: array(1) {
  [0]=>
  string(5) "hello"
}
4: string(17) "This is a closure"
于 2010-06-10T06:13:31.060 回答
2

我的解决方案比 Shauns 的稍长,但我想我还是会把它扔掉。即使在错误情况下,它也应该与原始语法相同。我基本上是利用三元语法来允许两行合二为一。我还将临时变量更改为${0}${''}因为它保存了一个字符,并且以数字开头的变量无效。

以下陈述,

line1;
$output = line2;

对于每种可能的情况,都与以下语句相同。

$output = (line1)&&0?:(line2);

我的解决方案:

<?php

error_reporting(E_ALL | E_STRICT);

// 1
function func_return_array() { return array(0 => 'hello'); }
$key = 0;

$output = (${0}=func_return_array())&&0?:${0}[$key];

echo '1: ' . $output . "\n";


// 2
class Thing {}
$class_base = 'Thi'; $class_suffix = 'ng';

$output = (${0}=$class_base.$class_suffix)&&0?:new ${0};

echo '2: ';
var_dump($output);


// 3
$func_base = 'func_'; $func_suffix = 'return_array';

$output = (${0}=$func_base.$func_suffix)&&0?:${0}();

echo '3: ';
var_dump($output);


// 4
function func_return_closure() {
    return function() {
        return 'This is a closure';
    };
}

$output = call_user_func(func_return_closure()); //more straight forward
//$output = (${0}=func_return_closure())&&0?:${0}();
echo '4: ';
var_dump($output);

?>
于 2010-06-15T02:53:15.250 回答