Есть у меня две переменные:
$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
Некоторое время назад я начал задуматься о смене ноутбука. Ну, чтобы быстрее, легче, меньше и лучше (по некоторым из параметров, конечно же), но ведь, буду честен, и мой текущий ноутбук не слишком тяжёл, достаточно быстр и, по некоторым из параметров, даже лучше чем потенциальный приемник. Учитывая же его принадлежность к славному роду ThinkPad’ов он счёл недостойным на меня обижаться и продолжает работать так будто бы я прямо с него не искал ему замену. Как будто ничего не произошло.
Но, совсем недавно, он начал бить меня током из firewire порта. Я этим портом никогда не пользовался и знать не знаю зачем он нужен, но током он меня бить начал исправно. Несильно, но зато часто. Терпел я недели две и сегодня, наконец, заклеил порт куском изоленты.
Удар я, получается, успешно парировал. Что же будет дальше?
2013.01.30 15:11
И третий пост подряд (сразу видно что я мало того что появился на работе, а даже открыл редактор!)
Сериализация в пхп работет быстро, но нечестно — при ансериализации сеттеры повторно не срабатывают.
class FRIENDSHIP_IS_MAGIC { private $Applejack; public function __set ( $key, $value ) { if ( $key != 'Applejack' ) { die ("Only Applejack you bastard!\n"); } if ( $value != '<3' ) { die ("No love -- no runtime!\n"); } $this->Applejack = $value; } public function __get ( $key ) { if ( $key != 'Applejack' ) { die ("Only Applejack you bastard!\n"); } return $this->Applejack; } } $pony = new FRIENDSHIP_IS_MAGIC(); $pony->Applejack = '<3'; // I LOVE YOU! var_dump($pony->Applejack); // string(2) "<3" $packed_pony = serialize($pony); $packed_pony = str_replace('s:2:"<3"', 'b:0', $packed_pony); // BLACK MAGIC $pony = unserialize($packed_pony); var_dump($pony->Applejack); // bool(false) -- WHERE IS MY LOVE ???
Конечно же тут я делают str_replace(), но в реальной жизни оно вполне себе может быть так что сначала засериализовали объект, сохранили в базу, а потом сеттер изменили и он уже валидирует иначе. Это беда на самом деле, прийдётся прикручивать какой-нибудь костыль.
2013.01.29 00:47
Вот в прошлом посте я осуждал сериализацию в пхп. Зачем я это делал? А вот я сейчас расскажу.
По науке если у класса есть некая переменная то она должна быть приватной, а обращаться к ней нужно через сеттер и геттер. Ну, чтобы там проверочьки, пыщ-пыщ, всё такое. А я вот такой волшебный человек и хочу заиспользовать магические методы __set() и __get() для этого:
class FRIENDSHIP_IS_MAGIC { public $PinkiePie; private $Applejack; public function __set ( $key, $value ) { if ( strlen($value) == 0 ) { return 42; } $this->$key = $value; } public function __get ( $key ) { return $this->$key; } } $pony = new FRIENDSHIP_IS_MAGIC(); var_dump($pony->Applejack = ''); // string(0) "" var_dump($pony->Applejack); // NULL var_dump($pony->Applejack = '<3'); // string(2) "<3" var_dump($pony->Applejack); // string(2) var_dump($pony->PinkiePie); // NULL var_dump($pony->PinkiePie = ''); // string(0) "" var_dump($pony->PinkiePie); // string(0) ""
Нет, ну это, конечно, очевидно что не каждый будет любить Applejack, а Pinky Pie личность сомнительного карактера. Но несмотря на то что в документации написано “__set() is run when writing data to inaccessible properties.” меня это раздражает. Какого чёрта. Не нравится мне такая логика.
Так вот почему я осуждал: чтобы сеттер срабатывал мне надо было сделать область видимости отличной от публичной и вполне логично было бы сделать её приватной, но не всё так просто %).
PS: я тут перечитал и ничего не понял. Смысл поста в том что если переменная публичная, то сеттер не сработает.
2013.01.28 21:26
Иногда бывает так что длина сериализованных данных не безразлична. Например, когда надо сохранить много объектов, но не хочется терять удобство всяких там сеттеров и геттеров сохраняя просто в stdClass или массив. И уж тем более не хочется мутить костыли с сохранением в массив, сериализацией, а потом обратным восстановлением и проходом по всем ключам массива с воссозданием нужного объекта. Но пхп не перестаёт удивлять :(.
Сериализуем объект с публичными переменными:
class C_PUBLIC { public $var1 = 1; public $var2 = 2; public $var3 = 3; } var_dump(serialize(new C_PUBLIC())); // string(64) "O:8:"C_PUBLIC":3:{s:4:"var1";i:1;s:4:"var2";i:2;s:4:"var3";i:3;}"
64 символа, по сути тот же массив, только что имя класса указывается. Ок.
Сериализуем с защищёнными переменными:
class C_PROTECTED { protected $var1 = 1; protected $var2 = 2; protected $var3 = 3; } var_dump(serialize(new C_PROTECTED())); // string(77) "O:11:"C_PROTECTED":3:{s:7:"*var1";i:1;s:7:"*var2";i:2;s:7:"*var3";i:3;}"
77 символов. Добавилось три звёздочки (по одной на переменную) и изменилось имя класса. Ну и почему-то внутри уже s:7 а не s:4. Ну да ладно.
Сериализуем с приватными переменными:
class C_PRIVATE { private $var1 = 1; private $var2 = 2; private $var3 = 3; } var_dump(serialize(new C_PRIVATE())); //string(101) "O:9:"C_PRIVATE":3:{s:15:"C_PRIVATEvar1";i:1;s:15:"C_PRIVATEvar2";i:2;s:15:"C_PRIVATEvar3";i:3;}"
101 символ. LOLWUT?
Очень удивился когда вместо 193 символов с protected я получил 432 с private. Неожиданно. Поленились ребята немного доработать сериализацию.
2013.01.28 20:38
Голоса в моим интернетах порассказали мне про то что некоторые вещи бывают идеальными. Например, оказывается, я отказывался в это верить, существует идеальная собака.
Такого пса приручить — уже жизнь прожита не зря. А обнять такую тушу так вообще задохнуться можно от радости. Хороший пёс, красивый.
2013.01.26 14:11
hshhhhh@blog % whoami hshhhhh hshhhhh@blog % blog post list 1. Окно в европу 2. Про стим и доту 2 3. Про пхп и тяжёлые наркотики 4. Про ручки 5. Про прекрасный шрифт 6. Испытание аналоговой параметрики 7. Про гуглотранслейт 8. Про забавное 9 . Про время 10. Про переименование файлов 11. Про велосипед и зиму 12. yeahconsole 13. Cassandra DB 14. Про работу и ещё про ненависть hshhhhh@blog % blog post new Title: Пост консоль, рекурсию и мечту Text: Есть некоторые вещи которые в хроме, всё же, сделаны плохо из-за их стремления следовать стандартам, например они убрали поддержку
2013.01.24 01:57
Работа находится по адр. ул Светланская 72 г. Владивосток. Идея заключается в использовании элементов фасада и силуэта здания и включении этих элементов в композицию. Окна, трубы, пристройки, дверные проемы и тротуарные фонари стали частью небольшой европейской деревни.Визуальная структура работы базируется на воспроизведении единства градостроительных решений таких городов как Прага,Брюгге, Старый Дубровник.
Я в шоке. Смотреть смотреть смотреть.
2013.01.24 01:18
Мне тут стим сделал приятное и дал 10 (десять!!!) копий второй доты, говорит чтобы я дарил друзьям и нёс радость. Никому не надо? Не знаю что с ними теперь делать.
Только, говорит, в Китай дарить эти копии нельзя, так что извините мои дорогие китайские товарищи, вам не смогу подарить :(.
2013.01.21 00:24
В пхп, доброе-утро, появились анонимные функции. И заодно замыкания. Про синтаксис замыканий я, пожалуй, говорить ничего не буду, а то прийдётся ругаться, но вот анонимные решают.
Например, можно присвоить некой переменной анонимную функцию, положить её в массив и вызвать. А вот положить её в свойство объекта её положить уже нельзя:
$f = function($a) { return 5 + $a; }; // Не забываем везде ставить ; !!!!!11
var_dump(gettype($f)); // string(6) "object"
var_dump($f(5)); // int(10)
$a = array($f);
var_dump(gettype($a)); // string(5) "array"
var_dump(gettype($a[0])); // string(6) "object"
var_dump($a[0](5)); // int(10)
$o = new stdClass();
$o->f = $f;
var_dump(gettype($o)); // string(6) "object"
var_dump(gettype($o->f)); // string(6) "object"
var_dump($o->f(5)); // Fatal error: Call to undefined method stdClass::f()
Но данное ограничение легко обходится простым, прости-боже за такие слова, снипплетом:
var_dump(call_user_func(function($object_vars, $var_name, $param) { return $object_vars[$var_name]($param); }, get_object_vars($o), 'f', 5)); // int(10)
2013.01.21 00:04
Одно из больших разочарований связанных с моей текущей жизнью — полное отсутствие необходимости писать. 99,9(9)% текста я набираю на клавиатуре и практически не пишу. Нет, я не люблю писать, мне не очень нравится, но я безумно люблю чернильные ручки. Но чернильной ручкой нельзя пользоваться раз в месяц.
Нашёл прекрасное в этом блоге (и вообще могу его порекомендовать):
2013.01.20 15:06
Нашёл прекрасный, чудесный, божественный шрифт. Одним богам понятно как мне нравится, но они (боги) злы — в шрифте, конечно же, нет (внимание, глубокие познания в предмете) киррилической гарнитуры. Печаль.
2013.01.16 08:54
Я, правда, не понимаю что хотели донести до меня и что я доношу до вас, мои глубокоуважаемые читатели (все полтора), но это прекрасно.
Испытание аналоговой параметрики. Делается моментально, смысловые показатели зашкаливают. Участники и тьюторы в восторге. Опыта вагон.
Отсюда вот: http://monogroup.by/archives/11412
2013.01.14 18:32
Внезапно узнал что с гуглотранслейтом можно общаться через жаббер, а жаббер нынче есть у каждого приличного человека. Это нынче и в фейсбуке, и в гуглотолке, и, прости боже, даже в контакте есть. Так что если добавить к себе в ростер контакт типа en2ru@bot.talk.google.com и написать ему “hello”, то он ответит “привет”. Не добавит, конечно, еще 27 вариантов перевода, но тоже очень приятный функционал.
Языков понимает много:
You can send a chat to these bots to get your messages translated:
Languages
|
Bots
|
|
Arabic – English | ar2en | en2ar |
Bulgarian – English | bg2en | en2bg |
Czech – English | cs2en | en2cs |
Danish – English | da2en | en2da |
German – English | de2en | en2de |
German – French | de2fr | fr2de |
Greek – English | el2en | en2el |
Spanish – English | es2en | en2es |
Finnish – English | fi2en | en2fi |
French – English | fr2en | en2fr |
Hindi – English | hi2en | en2hi |
Croatian – English | hr2en | en2hr |
Italian – English | it2en | en2it |
Japanese – English | ja2en | en2ja |
Korean – English | ko2en | en2ko |
Dutch – English | nl2en | en2nl |
Norwegian – English | no2en | en2no |
Polish – English | pl2en | en2pl |
Portuguese – English | pt2en | en2pt |
Romanian – English | ro2en | en2ro |
Russian – English | ru2en | en2ru |
Swedish – English | sv2en | en2sv |
Chinese – English | zh2en | en2zh |
Traditional Chinese – English | zh-hant2en | en2zh-hant |
Traditional Chinese – Chinese | zh-hant2zh> | zh2zh-hant |
* don’t forget to add @bot.talk.google.com.
2013.01.14 01:22
Самое забавное что я видел за эту неделю это как пользователь макбука запускает midnight commander и пользуется им как файл менеджером. Так мило :).
2013.01.10 00:47