А вот ещё про пхп смешное

Есть у меня две переменные:

$a_error = array();
$a_neerror = array();

И есть у меня сложная логика, например есть некие “события”, у неких “событий” есть некий “тип” и мне надо учитывать сколько типов этих событий было успешно или нет. Страшной силы код:

if ( $status == 'ok' ) {
    if ( !isset($a_neerror[$event->type]) ) {
        $a_neerror[$event->type] = 0;
    }
    $a_neerror[$event->type]++;
}

И потом его ещё продублировать для ошибочного варианта. Сильно печалит меня дублирование кода и тут на помощь приходит “variable variable” (с таким названием и на помощь, ага), ну смысл в том что можно делать так:

$postfix = $status == 'ok' ? 'neerror' : 'error';
$var = "a_{$status}";
var_dump($$var);

И всё прекрасно работает, но стоит переписать предыдущий пример как:

$postfix = $status == 'ok' ? 'neerror' : 'error';
$var = "a_{$status}";
if ( !isset($$var[$event->type]) ) {
    $$var[$event->type] = 0;
}
$$var[$event->type]++;

Как всё перестаёт работать потому что пхп считает что это я пытаюсь забрать символа под номером “$event->type” из строки $var и потом уже этот символ подставить как имя переменной. Но есть решение, Даже два:

$postfix = $status == 'ok' ? 'neerror' : 'error';
$var_temp = "a_{$postfix}";
$var = &$var_temp;
if ( !isset($var[$event->type]) ) {
    $var[$event->type] = 0;
}
$var[$event->type]++;

Но ведь это некрасиво, лишняя переменная всё такое. Есть красивое решение:

$postfix = $status == 'ok' ? 'neerror' : 'error';
$var = "a_{$postfix}";
if ( !isset(${$var}[$event->type]) ) {
    ${$var}[$event->type] = 0;
}
${$var}[$event->type]++;

Или совсем красивое решение без введения лишних переменных:

$postfix = $status == 'ok' ? 'neerror' : 'error';
if ( !isset(${"a_{$postfix}"}[$event->type]) ) {
    ${"a_{$postfix}"}[$event->type] = 0;
}
${"a_{$postfix}"}[$event->type]++;

А вот сказать почему надо делать такую красоту? Потому что или так, ну чтобы красиво, или многострочный switch()/if() для выбора переменной, а вот так написать нельзя:

$postfix = $status == 'ok' ? &$a_neerror : &$a_error;
$postfix =& $status == 'ok' ? $a_neerror : $a_error;

Как после такого можно не любить пхп? А вот его надо любить потому что решение есть! Красиво и элегантное!!!

$postfix = $status == 'ok' ? 'neerror' : 'error';
$var = "a_{$postfix}";
$var = &$$var; // ЭТО ОНО!!!!
if ( !isset($var[$event->type]) ) {
    $var[$event->type] = 0;
}
$var[$event->type]++;

И, внимание, я считаю это победа, но один благодарный читатель мне посоветовал не страдать хернёй и воспользоваться проверенным решением:

$stats = array('neerror'=>array(), 'error'=>array());
$var = &$stats[$status == 'ok' ? 'neerror' : 'error'];
if ( !isset($var[$event->type]) ) {
    $var[$event->type] = 0;
}
$var[$event->type]++;

Тот же благодарный читатель сказал мне что я плохой неопытный недопрограммист и мой элегантный пример можно переписать короче:

$postfix = $status == 'ok' ? 'neerror' : 'error';
$var = &${"a_{$postfix}"}; // Вот так
if ( !isset($var[$event->type]) ) {
    $var[$event->type] = 0;
}
$var[$event->type]++;

Но я не знаю, мне так не хочется терять красивую конструкцию “$var = &$$var;”… Как же быть?

2013.02.13 20:25