chris_archer: (Default)

Однажды я жаловался, что

foreach((function () {for ($i = 0; $i < 10; $i++) yield $i;})() as $i) echo $i;

в PHP не работает. Так вот. Начиная с PHP7 благодаря новому парсингу синтаксиса

foreach((function () {for ($i = 0; $i < 10; $i++) yield $i;})() as $i) echo $i; // 0123456789

очень даже работает.

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Внезапно до меня дошло как записать эту вещь в 1 строчку

foreach(call_user_func(function () {for ($i = 0; $i < 10; $i++) yield $i;}) as $i) echo $i;

Т.е. имеем такой синтаксис для "одноразовых" генераторов

$generator = call_user_func(function () {
while(1) {
yield generate_something();
}
});

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Пока мне не спится, набросал страницу для конвертации вордпрессовских Readme.txt в гитхабовский Markdown

В общем-то вся логика уже есть в интернетах, надо было только собрать всё воедино

wpreadme2markdown.com

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

function func($a, $b, ...$params)
{
var_dump($a, $b, $params);
}

func(1,2,3,4,5);
// int(1)
// int(2)
// array(3) {
// [0]=>
// int(3)
// [1]=>
// int(4)
// [2]=>
// int(5)
// }
// круто!

$a = [1,2,3,4,5];

func(...$a);
// int(1)
// int(2)
// array(3) {
// [0]=>
// int(3)
// [1]=>
// int(4)
// [2]=>
// int(5)
// }
// еще круче!

$a['qq'] = 'qq';

func(...$a);
// PHP Catchable fatal error:
// Cannot unpack array with string keys in /tmp/test.php on line 16
// ну ок

$b = [];
$b[1] = 1;
$b[4] = 4;
$b[2] = 2;
$b[5] = 5;
$b[3] = 3;

func(...$b);
// int(1)
// int(4)
// array(3) {
// [0]=>
// int(2)
// [1]=>
// int(5)
// [2]=>
// int(3)
// }
// WAT?

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

function func($a, $b, ...$params)
{
var_dump($a, $b, $params);
}

func(1,2,3,4,5);
// int(1)
// int(2)
// array(3) {
// [0]=>
// int(3)
// [1]=>
// int(4)
// [2]=>
// int(5)
// }
// круто!

$a = [1,2,3,4,5];

func(...$a);
// int(1)
// int(2)
// array(3) {
// [0]=>
// int(3)
// [1]=>
// int(4)
// [2]=>
// int(5)
// }
// еще круче!

$a['qq'] = 'qq';
// PHP Catchable fatal error:
// Cannot unpack array with string keys in /tmp/test.php on line 16
// ну ок

func(...$a);

$b = [];
$b[1] = 1;
$b[4] = 4;
$b[2] = 2;
$b[5] = 5;
$b[3] = 3;

func(...$b);
// int(1)
// int(4)
// array(3) {
// [0]=>
// int(2)
// [1]=>
// int(5)
// [2]=>
// int(3)
// }
// WAT?

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Написал свою версию плагина для Libravatar — Libravatar Replace. Точнее, пришлось форкнуть оригинал, т.к. автор упорно молчал на мои попытки связаться. Сначала я добавил все дефолты Либраватара в список, а потом понеслось

Фичи:

  • Плагин полностью заменяет Gravatar на Libravatar в WordPress, включая всё default images (лого только меняется соответствующе)
  • Services_Libravatar содержит мой патч, исправляющий работу с портами в SRV
  • Попытался сделать поддержку BuddyPress (там свой алгоритм генерации изображний-аватаров, причем писец какой запутанный) — вроде работает

WordPress Plugins: wordpress.org/plugins/libravatar-replace
BitBucket: code.sunchaser.info/libravatar

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Очень интересный и полезный момент сегодня всплыл в комментариях на Хабре. В PHP 5.5, как известно, сделали поддержку функций-генераторов, по типу питоновских. Там раньше были итераторы, но с адовым синтаксисом (как всё в SPL), а теперь ввели оператор ‘yield’ и всё волшебным образом упростилось.

Например, можно написать такой генератор, читающий построчно файл:

  1. function getLines($file) {
  2.     f = fopen($file, ‘r’);
  3.     while ($line = fgets($f)) {
  4.         yield $line;
  5.     }
  6.     fclose($f);
  7. }

‘yield’ означает «вернуть значение и продолжить с этого места при следующем вызове функции». Имея такой генератор, можно сделать вот такую печать файла:

  1. foreach (getLines("file.txt") as $line) {
  2.      echo $line;
  3. }

Удобно? Очень удобно. Оператор ‘yield’ выдаст все строки файла, а потом, когда файл закончится, произойдёт обычный ‘return’ из функции, который закроет генератор (и закончит цикл).

Но как известно, если всё идёт хорошо, значит, вы чего-то не заметили. Немного изменим наш цикл:

  1. foreach (getLines("file.txt") as $n => $line) {
  2.     if ($n > 5) break;
  3.     echo $line;
  4. }

Предположим, нас интересуют только первые шесть строк файла, а дальше мы хотим прервать цикл оператором ‘break’. Имеем на то полное право. Но что в этом случае произойдёт внутри генератора? А ничего. Он останется стоять на последнем исполненном yield-е и никогда не дойдёт до строки ‘fclose($f)’. И наш файл останется незакрытым.

Мы получили утечку ресурса (открытого файла). Понятно, что внутри генератора могут быть открыты любые ресурсы и объекты, и их необходимо правильно и предсказуемо закрывать. Но как это сделать, если юзер может в любой момент сделать break? Обычная документация (http://www.php.net/manual/en/language.generators.overview.php) никаких намёков не даёт.

Так вот, оказывается (и за это спасибо юзеру weirdan с Хабра: http://habrahabr.ru/post/189796/#comment_6594776), что читать в этом случае надо не документацию, а RFC по генераторам: https://wiki.php.net/rfc/generators#closing_a_generator. А в нём сказано, что при освобождении ссылки на генератор, у него внутри обязаны выполниться все блоки ‘finally’. И тогда мы получаем очень простой, красивый и безопасный код:

  1. function getLines($file) {
  2.     f = fopen($file, ‘r’);
  3.     try {
  4.         while ($line = fgets($f)) {
  5.             yield $line;
  6.         }
  7.     } finally {
  8.         fclose($f);
  9.     }
  10. }

В этом случае блок ‘finally’ выполнится и при нормальном выходе из цикла по генератору и при выходе по break-у. Ура.

Так что если вы пишете на PHP — имейте это в виду. Потому что, кажется, больше нигде про это узнать невозможно — ни в одной из читанных мною статей по генераторам не было ни слова об утечке ресурсов.

ru-php.livejournal.com/1566325.html

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Сервис-заглушка для системы Libravatar. Позволяет использовать одну картинку формата png для домена. Думаю, большинству этого вполне хватит :)

Стырить как всегда можно из моего репо для мелочей — code.sunchaser.info/miscellaneous

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Извращаюсь с новой игрушкой

  1. $a = function () {for ($i = 0; $i < 10; $i++) yield $i;};
  2. foreach ($a() as $i) echo $i; // 0123456789

Жаль, что не работает foreach ($a as $i) echo $i;, тогда можно было бы написать короче

  1. foreach(function () {for ($i = 0; $i < 10; $i++) yield $i;} as $i) echo $i;

Или будь PHP похож на одного из своих предков, можно было бы

  1. foreach((function () {for ($i = 0; $i < 10; $i++) yield $i;})() as $i) echo $i;

Даже извращения не работают типа

  1. foreach((function () {for ($i = 0; $i < 10; $i++) yield $i;})->__invoke() as $i) echo $i;

Если кто не догнал, я пытаюсь сделать вот это:

  1. (0..9).each { |i| print i }
Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Оппа, оппа, Java Style

Что делает эта программа?

  1. use SimplePHPEasyPlus\Number\NumberCollection;
  2. use SimplePHPEasyPlus\Number\SimpleNumber;
  3. use SimplePHPEasyPlus\Number\CollectionItemNumberProxy;
  4. use SimplePHPEasyPlus\Parser\SimpleNumberStringParser;
  5. use SimplePHPEasyPlus\Iterator\CallbackIterator;
  6. use SimplePHPEasyPlus\Operator\AdditionOperator;
  7. use SimplePHPEasyPlus\Operation\ArithmeticOperation;
  8. use SimplePHPEasyPlus\Operation\OperationStream;
  9. use SimplePHPEasyPlus\Engine;
  10. use SimplePHPEasyPlus\Calcul\Calcul;
  11. use SimplePHPEasyPlus\Calcul\CalculRunner;
  12.  
  13.  
  14. $numberCollection = new NumberCollection();
  15.  
  16. $numberParser = new SimpleNumberStringParser();
  17.  
  18. $firstParsedNumber = $numberParser->parse(’1′);
  19. $firstNumber = new SimpleNumber($firstParsedNumber);
  20. $firstNumberProxy = new CollectionItemNumberProxy($firstNumber);
  21.  
  22. $numberCollection->add($firstNumberProxy);
  23.  
  24. $secondParsedNumber = $numberParser->parse(’1′);
  25. $secondNumber = new SimpleNumber($secondParsedNumber);
  26. $secondNumberProxy = new CollectionItemNumberProxy($secondNumber);
  27.  
  28. $numberCollection->add($secondNumberProxy);
  29.  
  30. $addition = new AdditionOperator(‘SimplePHPEasyPlus\Number\SimpleNumber’);
  31.  
  32. $operation = new ArithmeticOperation($addition);
  33.  
  34. $engine = new Engine($operation);
  35.  
  36. $calcul = new Calcul($engine, $numberCollection);
  37.  
  38. $runner = new CalculRunner();
  39.  
  40. $runner->run($calcul);
  41.  
  42. $result = $calcul->getResult();
  43. $numericResult = $result->getValue(); // 2

Она вычисляет 1+1!!!

http://habrahabr.ru/post/172119/

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Начало конца PHP 5.3: репозиторий Les RPM de Remi отказался от поддержки PHP 5.3, теперь только PHP 5.4, только хардкор.

Впрочем, тормозной народ до сих пор сидит на PHP 5.2 и пишет в стиле PHP4.

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Вот еще забавность:

  1. <?php
  2.  
  3. namespace test;
  4.  
  5. class SomeName
  6. {
  7.         public static function SomeName()
  8.         {
  9.                 echo "something\n";
  10.         }
  11. }
  12.  
  13. $a = new SomeName();
  14. $a->SomeName();
  15. /* печатает something */
  1. <?php
  2.  
  3. // namespace test;
  4.  
  5. class SomeName
  6. {
  7.         public static function SomeName()
  8.         {
  9.                 echo "something\n";
  10.         }
  11. }
  12.  
  13. $a = new SomeName();
  14. $a->SomeName();
  15. /* PHP Fatal error:  Constructor SomeName::SomeName() cannot be static in /tmp/test.php on line 11 */

Причем если предыдущий пример был недоработкой по сути, то это фича

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

$b = new stdClass;
$b->method = function($x) { var_dump( $x); };
$b->method->__invoke('dads'); // string(4) "dads"
$b->method('dads'); // PHP Fatal error: Call to undefined method stdClass::method() in php shell code on line 1
($b->method)('dads'); // PHP Parse error: syntax error, unexpected '(' in php shell code on line 1

*задумался*

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Если у кого при переходе на PHP 5.4 отвалился плагин OpenID, вот пофиксенная версия — openid-php54-fixed.zip

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

От нечего делать наклепал свою сокращалку ссылок.

Посмотреть можно на http://url.sunchaser.info/
Взять на http://home.sunchaser.info/articles/web/php/urlsh.html

Фича — верификация по OpenID — должна отпугнуть от вашей сокращалки мошенников

Файлы add.php, auth.php и show.php можно инклудить, чтоб вписывалось в дизайн сайта. Но мене самого как всегда ломает

UPD: исправлена бага с Яндексом, качать там же, в common.inc.php новый параметр ($urlsh['url']['root'])

Originally published at Chase Your Dreams!. You can comment here or there.
chris_archer: (Default)

Читаю мануал PHP по обработке ошибок

Also note that it is your responsibility to die() if necessary.

We live for the One, we die() for the One.

Originally published at Chase Your Dreams!. You can comment here or there.

Profile

chris_archer: (Default)
chris_archer

June 2017

S M T W T F S
    123
456 78910
11121314151617
18192021222324
252627 282930 

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 18th, 2017 08:14 pm
Powered by Dreamwidth Studios