Pull to refresh

Comments 99

UFO just landed and posted this here
Там вроде статически линкуются so-шки (dll-ки). Из сорцов нужны только хедеры, чтобы FFI знал сигнатуры методов и смог автоматом их забиндить. То бишь сишные либы должны быть компилированные под нужную архитектуру заранее.
Код заданный через FFI::cdef будет компилироваться условно каждый раз (но не забываем про оптимизации php). Так же есть возможность подгрузить код из C-header файла через FFI::load, но т.к. это занимает значительное время в RFC рекомендуется делать это 1 раз на старте приложения, а работу с FFI оформить через lazy load синглтон дающий доступ к FFI с заданным scope, при этом заранее скомпилировать opcache для него. Пример для второго подхода есть в секции RFC «A Complete PHP/FFI/preloading example».

Если раньше в ногу стреляли, то теперь подвезли гранаты. :D

Насчет интерфейса внешних функций например на C я не понял этот код будет налету компилироваться всякий раз или только при первом запуске или еще как?

Зависит от настроек в php.ini. По умолчанию FFI доступен только в файлах, которые загружаются с помощью preload функционала (файлы для которого, напоминаю, тоже указываются в ini конфигах).


Пруфы:
1) ffi https://github.com/php/php-src/blob/master/php.ini-production#L1892
2) preload https://github.com/php/php-src/blob/master/php.ini-production#L1854


UPD: Персональное ИМХО по этому всему: Функционал с прелоадом и ffi будет очень слабо востребован в связи с тем, что его почти невозможно нормально использовать.

Почему вы думаете что прелоад будет слабо востребован? Что касается FFI то это инструмент, как мне видится, скорее для разработки библиотек нового уровня, там где требуются большие\сложные математические операции и т.д., то есть для машинного обучения и прочего.

Потому что он настраивается на уровне php.ini и как следствие — глобален на все проекты на сервере сразу (давайте временно забудем про докер и прочие штуки и возьмём в качестве примера типичный VPS прод или шаред).


Так что либо придётся прописывать opcache.preload=/home/username/site.org/vendor/preload.php
под один единственный проект. И при появлении site-2.org уже ничего с этим не сделать.


Либо делать тоже самое на уровне fpm конфигов в виде php_flag[opcache.preload]=xxx. Что примерно тоже самое, но получше, т.к. можно отдельно воркеры под каждый ресурс запилить.

Ой как не хочется в текущем веку забывать про контейнеризацию. На VPS то ее кстати тоже вполне можно сделать. А про shared хостинги, придется извращаться, вы правы.

Настраивать целый интерпретатор под один единственный проект и каждый раз мучать админов для перенастройки, если что пойдёт не так — это само по себе извращение.

Так докер — это как раз способ один раз настроить интерпретатор, зафиксировать базовый образ и дальше все проекты наследовать FROM этого образа.

Много ли у вас highload-проектов на докере? Просто интересно.

У меня сейчас уже третий)

Можете назвать их?
Какой стек используете?
Как доставляете?

В целом я бы не хотел заниматься неймдроппингом, если меня погуглить — всё найдёте. Сейчас я работаю вместе с автором статьи, это видно в хабра-профиле. Стек у нас — монолит на PHP с вынесенным в Java/Kotlin-сервисы performance critical функционалом, БД — Монго, KV — Redis, немного машинки на Питоне, куда без неё. Находимся в процессе переезда из AWS в свой ДЦ, о чём однажды выйдет супер увлекательная статья) Доставляем контейнерами (звучит почти как работа в логистической компании).

Отличный набор нововведений. Порадовал «Оператор распаковки в массивах»
… писать код на C непосредственно в PHP-коде…
а в C делать ассемблерные вставки!
Справедливости ради, там только декларации на С, что является довольно узким подмножеством языка)
Придется чутка пошаманить в шаблонах.
<?php foreach($somedataarray as $key=>$var):?>
Some HTML HERE
<?endforeach?>

Читается имхо хуже, чем <? foreach(): ?>
Дело привычки, мне сейчас кажется что эти 3 символа не решают.
Да и тем более, foreach в шаблоне это не такая частая вещь, обычно это что-то вроде
$view->renderPartial('element.template', $dataArray);  

Для всяких списков, таблиц, и т.д.
Тут вполне прокатит <?=
Я именно про циклы в шаблонах. Их довольно много обычно.
UFO just landed and posted this here
А что за костыли если не секрет?
Да там велосипеды из костылей обычно
UFO just landed and posted this here
В 2019 году кто-то все еще пользуется php_mysqli? О_о
UFO just landed and posted this here
А в чем проблема с mysqli?
Это не правда. Mysqli — актуальный драйвер для MySql наряду с PDO (Там есть ряд функциональности, недоступной в PDO для MySql). Устаревший драйвер называется Mysql и его нужно ставить отдельно из PECL, т.к. он удален из стандартной поставки PHP.
php_mysql устарел фактически.
php_mysqli морально.

Подскажите какой именно функционал недоступен в PDO, но доступен в php_mysqli?

Минусят по ходу битриксоиды, которые так и не смогли разобраться с ООП.
Подскажите какой именно функционал недоступен в PDO, но доступен в php_mysqli?

Асинхронные и неблокирующие запросы

Я не знаю нюансов, но мне кажется странной идея, что единственный "правильный" способ — это универсальная обёртка над всеми RDBMS. У движков баз всегда будут уникальные фичи, которые не впихиваются в наибольший общий делитель, поэтому голый полный API имеет право на существование.

Если вам кровь из носу требуются асинхронные запросы в веб приложении, значит у вас что-то не так в архитектуре приложения.

Давайте сравним
mysqli
+ асинхронные запросы

PDO
+ гарантированное получение в массив строки из БД без плясок с бубном
+ биндинг по значению, а не по ссылке
+ именованные плейсхолдеры для биндов
+ prepared statements на стороне клиента
+? при использовании кверибилдера позволяет полностью абстрагироваться от привязки к конкретной БД и осуществить переход от MySQL, например, на тот же PortgreSQL

Возможно, я несколько преувеличил масштабы в изначальном комментарии, но я согласен с мнением автора вот этой статьи о том, что PDO стоит использовать как решение по умолчанию, особенно для новичков, а mysqli использовать только в тех случаях, когда это абсолютно необходимо by design.
Я и не говорил, что нужно использовать направо и налево mysqli. Я сказал, что расширение актуальное, а не устаревшее.

Ясно дело, что для подавляющего большенства случаев нужно брать по-умолчанию PDO.

А mysqli нужен для тех, кто сильно завязан именно на MySQL и использует ее особенности, с которыми не умеет работать PDO.
При чем здесь ООП вообще, учитывая, что у mysqli есть объектный интерфейс наряду с процедурным?
Подскажите какой именно функционал недоступен в PDO, но доступен в php_mysqli?

LOAD DATA LOCAL INFILE запросы через PDO не работает
UFO just landed and posted this here
так и не смогли разобраться с ООП

в mysqli/mysqlnd вполне себе есть ООП
учу РНР с 5.3 версии. с каждой новой версией он развивается, улучшается
<? объявили устаревшыми и исключения в __toString — порадовали.
С изменением порядка операций будет адская веселуха. Зря они так.
Надеюсь депрекейтед нотисы помогут эту веселуху сгладить, но получается, это делает версию 7.4 обязательной для миграции, чтобы плавнее смигрировать на последующие версии. А само изменение хорошее, раньше было менее логично как по мне.
Если хотите чтобы я более подробно рассмотрел новые возможности типизации свойств объектов, отметьтесь в комментариях, и я напишу отдельную статью про них!


Отмечаюсь. Было бы интересно.

Одна из причин это совпадение с синтаксисом xml, где то писали об этом...

Я не понимаю в чем проблема просто оставить его выключенным по умолчанию?

Он и так сейчас выключен по умолчанию, уже больше пяти лет как. Но вы же видите ситуацию, выше в комментах люди даже не догадываются почему его удаляют, а на тостере полным-полно вопросов "почему гружу на продакшн и не работает".

Потому что идиоты.
Работает, удобно, красиво. Но им «не нравится». XML делали и раньше, и как то жили с этим.
Не люблю когда за меня решают что использовать, а что нет. Надеюсь что будет какая-то петиция для сохранения этого оператора.
Если не любите, чтобы за вас решали — сделайте форк. Язык развивается — будут и дальше выпиливать. Используйте уже шаблонизаторы, наконец!
Бесполезно что-то объяснять людям, которые не понимают слов «обратная совместимость» в энтерпрайзе.

Да какой, Ѣ, "энтерпрайз". Обновление — это осознанный шаг. Оно просто так никому не устанавливается, это не windows updates.


А если всё же приспичило обновить мажорную версию, то будьте добры прогнать код через какой-нибудь rector или в шторме кнопочку нажать на худой конец…

Так это и плохо, что обновления необязательны, что они ломают совместимость и приводят к удорожению разработки. Ведь обновления ускоряют время выполнения. Именно в этом претензия к индусам-разработчикам.

Поломка совместимости — это когда популярный функционал переделывается. А тут хрень, которая и так используется лишь новичками, которые начитались мануалов начал 2000х, да код, примерно с тех же самых времён.


А короткие теги уже лет 10 как помечены "НЕ ПИШИТЕ ТАК". За такое время можно было вполне снизойти. Ну а если за 10 лет не осилилось потратить 5 минут времени (ну мб 10 минут), то значит и не нужно это никому, и обновлять никому ничего не надо.

Обновления не приводят к удорожанию разработки, если их не накатывать. И их игнорирование не приводит прямо к удорожанию разработки или эксплуатации (мотивация разработчиков и риск-менеджмент отдельный вопрос).

За вас не решают, обновляться или нет решать вам.

Чтобы меньше было проблем "ваш код у меня не работает", а приводить это "не работает" может к утечке чувствительных данных.

Ковариантность/контравариантность
Что то тут не понятно, можно чуть более расширить пример.
Сначала думал там вместо типа сам объект указывается, но нет

Для типизации доступны все типы, за исключением void и callable.

Грустно, что нельзя будет указать свойству тип callable. Я понимаю, что это сделано, чтобы решить такую неоднозначность:


class Foo {
    public callable bar;
    public function bar() {}
    // ...
}

(new Foo)->bar(); // Вызовится свойство или метод?

Но это не отменяет необходимость иногда хранить функции в свойствах объекта.


Обратите внимание, что это работает только с неассоциативными массивами.

Не верю. Функция array_merge и оператор + прекрасно работают с ассоциативными массивами. Почему тогда оператор распаковки не может?

Опишите логику поведения распаковки в случае коллизии ключей.
Как на ваш взгляд оно должно работать?
UFO just landed and posted this here
Я не удивлен, я просто привел пример несостоятельности аргумента про коллизии ключей, в комментарии на который отвечал.

Оператор может работать точно также как функция array_merge. В вашем примере будет выбрано то значение, которое стоит правее.


Коллизия ключей может быть намеренной ситуацией. Например, когда параметры передаются в виде массива, и есть параметры по умолчанию:


function test(array $options) {
    $options = [
        'color' => 'red',
        'size' => 'big'
        ...$options
    ];
    return $options;
}

var_dump(test(['color' => 'green', 'mode' => 'demo']));
/*
[
    'color' => 'green',
    'size' => 'big',
    'mode' => 'demo'
]
*/
Обратите внимание, что это работает только с неассоциативными массивами.

Да, не внимательно прочитал, сорре. Мне тоже такая логика работы кажется странной

Грустно, что нельзя будет указать свойству тип callable. Я понимаю, что это сделано, чтобы решить такую неоднозначность
Немного не так.
public callable bar = ['ClassTest', 'methodTest'];

Это callable? Вроде да. В чем подвох? а может это все же array? ))

Но это не отменяет необходимость иногда хранить функции в свойствах объекта.
Так вроде никто и не мешает:
public ?Closure bar = null;

Указанная вами неоднозначность актуальна для всех остальных мест, где можно указывать тип. Closure — это лишь подтип callable; в большинстве случаев такое решение подойдёт, согласен.

Не очень что тут имееться ввиду, может кто обьяснить?


Вызов var_dump на экземпляре DateTime или DateTimeImmutable больше не делает доступными свойства объекта.
Исправлен вот этот баг bugs.php.net/bug.php?id=49382.

То есть теперь нет возможности сделать так:
$dt=new DateTime('1742-05-23 00:00:00'); echo $dt->date;
Notice: Undefined property: DateTime::$date

$dt=new DateTime('1742-05-23 00:00:00'); var_dump($dt); echo $dt->date;
DateTime Object ( [date] => 1742-05-23 00:00:00 [timezone_type] => 3 [timezone] => UTC ) 1742-05-23 00:00:00

Сколько всего интересного))) И ковариантность/контравариантность это супер. Давно не хватало.

Это что же получается в стрелочной функции нельзя будет написать аналог вот этого JS кода?
[1,2,3].map(item => {
    const newValue = '№' + item
    return newValue
})
Думаю, подразумелось, что нельзя две строки в теле функции.
Именно. Так-то в стрелочной функции можно много строк написать и, получается, их все будет сложно запихнуть в одну строку. Печально, но видимо на то были причины

Да они упоролись.


Что стрелочные функции наконец-то рожают — это, конечно, радость пришла в мой аул. Можно будет выкинуть весь богомерзкий строколямбдовый мусор из YaLinqo и войти в светлое будущее, когда LINQ не выглядит как говно. Особенно радует, что разрабы таки сделали полный захват области видимости, а то у меня были опасения, что они заставят явным use пользоваться.


Что идёт дальше — я не понял умора. Зачем-то выпилили <?, хотя это очень даже удобно. Не всегда и не везде нужна генерация XML, а если нужен XML, то недолго ровно в одном месте написать вывод через строчку. Для шаблонов удобно и красиво. Было.


Менять приоритет операторов — это гениальный ход. Народ-то думал, что синтаксические косяки придётся тащить во имя обратной совместимости, но разрабы PHP были полны решимости. Забавно, что какой-то маргинальный синтаксис с конкатенацией изменили, а повсеместно нужный тернарный оператор запретили. Наверное, в этом есть какой-то скрытый смысл, но выглядит странно.


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

Что идёт дальше — я не понял умора. Зачем-то выпилили <?, хотя это очень даже удобно

Он не нужен, очевидно и доставляет в разы больше проблем, нежели профита. Да и им пользуются лишь совсем новички. Покажите хоть один пакет в композере, где он используется?


Для шаблонов удобно и красиво. Было.

Для шаблонов есть шаблонизаторы.


Менять приоритет операторов — это гениальный ход. Народ-то думал, что синтаксические косяки придётся тащить во имя обратной совместимости, но разрабы PHP были полны решимости.

Рекомендую почитать пост и понять что поменяли. Сейчас это выглядит как "не читал, не понимаю что делают, но осуждаю". Я не представляю себе ни одной задачи, где бы текущий приоритет операторов решал какую-либо задачу, так что при использовании конкатенации использование скобок — дефолтное решение, а как следствие — никаких поломок обратной совместимости.


а повсеместно нужный тернарный оператор запретили

Тоже самое что и выше: "Не читал, но осуждаю". Никто не запрещал тернарных операторов. Запретили говнокод в тернарниках.

Он не нужен, очевидно и доставляет в разы больше проблем, нежели профита. Да и им пользуются лишь совсем новички. Покажите хоть один пакет в композере, где он используется?

<? не используется в публичных пакетах, потому что он непортируем. А вот в закрытых или личных проектах возможность писать шаблоны красиво — удобна. Чуваки из Битрикса, который каждый раз вспоминают при упоминании этого изменения, явно думали так же. Их код не нужно было запускать в условиях, когда <? недоступен.


Проблема с XML высосана из пальца: если генератор XML гоняется через PHP, то строчкой <?="<?"?> решаются все проблемы. Да, похапэшным разрабам хочется убрать побольше царского наследия, когда поведение языка зависит от недоступных для изменения опций, и это похвально, но выкидывание <? — мёрвому припарка.


Для шаблонов есть шаблонизаторы.

Начерта мне шаблонизаторы, если похапэ сам по себе — отличный шаблонизатор? =) Я понимаю, что на большом сайте с десятками подключенных пакетов и активной поддержкой кода плюс-минус шаблонизатор — это статистическая погрешность, но не всегда хочется тащить в миниатюрный проект (а это ненулевая ниша) лишние внешние зависимости. Это не прихоть, это желание не тратить время ещё и на портирование на новую версию зависимости, когда интерпретатор (компилятор?) обновляешь.


Тоже самое что и выше: "Не читал, но осуждаю". Никто не запрещал тернарных операторов. Запретили говнокод в тернарниках.

Спасибо, я уже поржал с анализа ситуации в RFC: в 1000 топовых пакетов нашлось 12 использований тернарных цепочек, из которых 9 — баги, а 3 — вроде как норма. Эпик фейл с левой ассоциативностью тернарного оператора уже не исправить, поэтому запрет — это рациональное решение, но вообще-то поломка обратной совместимости в минорной версии в приличном обществе допустимой не считается (джависты вон дженерики поломали, лишь бы виртуальную машину не обновлять — учитесь, что называется =) ). Тем более, когда это ломает 12 из топовых 1000 пакетов, причём ломает не на уровне "в такой ситуации возникнет баг", а на уровне "вообще не запускается". Я уж молчу про менее популярные пакеты.


С конкатенацией статистика заметно лучше (5 из 5 в топ 2000 — баги), но ссылка на RFC в статье поломана, и мне было лень искать нормальную, поэтому с первого захода не заценил.

Начерта мне шаблонизаторы, если похапэ сам по себе — отличный шаблонизатор?

Ну, скажем так, современные шаблонизаторы — это не только вывод с экранированием. И там нативному PHP до них как до луны.


Но я допускаю, что возможно из-за того, что вообще не помню когда последний раз писал echo не совсем объективен в этом плане.


поломка обратной совместимости в минорной версии

Мы все прекрасно знаем какие у PHP "минорные версии"))) Такой же php 5.2 -> 5.3, например, вообще полностью изменил язык в своё время.


джависты вон дженерики поломали

Джависты себе давно язык сломали (пользуясь случаем) =)


Тем более, когда это ломает 12 из топовых 1000 пакетов, причём ломает не на уровне "в такой ситуации возникнет баг", а на уровне "вообще не запускается"

Ну вообще это ССЗБ. Смотря на такой код: https://github.com/symfony/messenger/blob/4.1/DependencyInjection/MessengerPass.php#L118 Мне рыдать хочется. Блин, неужели так сложно разрабам скобки расставить было? А ещё пишут что в симфони норм код...


У меня нет, короче, контраргументов =) Ну убили совместимость, да, но как раз в тех местах за которые надо писателей на костёр отправлять.

PHP не придерживается semver. "Минорные" релизы всегда были с потерей BC, а "мажорные" всегда означали полное переписывание внутренностей движка. В теории могут быть "мажорные" релизы без потери BC, и даже без изменения самого языка и либ PHP.

Почему это 7.4 минорная версия?
Команда давно отошла от классического semver
7 — «версия» zend engine
4 — мажорщина с крайне вероятной обратной несовместимостью
остальное — фичи без нарушения обратной совместимости в пределах мажорщины, фиксы и прочая мелочь
с крайне вероятной обратной несовместимостью

При обсуждении изменений собрали статистику. Один только RFC по тернарным операторам ломает до уровня "не запускается" 12 из 1000 самых популярных пакетов. Так что это не "вероятность". =)


Может, разрабы не хотят уподобляться Хрому?

ну я в общем :) щас ломает сильно, 7.1 и 7.2 не очень

Барбара Лисков довольно улыбается

Обнаружилась интересная штука с типизированными свойствами


If a typed property does not have a default value, no implicit null default value is implied (even if the property is nullable). Instead, the property is considered to be uninitialized. Reads from uninitialized properties will generate a TypeError (unless __get() is defined, see next section).

То есть, получается, что у нас меняется привычное поведение


class A
{
    /**
     * @var string|null
     */
    public $a;

    public ?string $b;
}
$a = new A();
var_dump($a->a); // NULL
var_dump($a->b); // Fatal error: Uncaught Error: Typed property A::$b must not be accessed before initialization

Я что-то не уверен, что это правильно.

Ну, то есть понятно, что код мигрирует на PHP 7.4 по другому.


class A
{
    /**
     * @var string|null
     */
    public $a;

    public ?string $b = null;
}

Но мне кажется это как-то не так должно быть.

Вполне нормальное решение, по-моему. Если мы не объявим дефолтное значение не для ?string $b, а для string $b, то null быть не должно в принципе там. А делать алгоритим типа: если тип объявлен и он не нуллабл, то бросать ошибку при попытке чтения неиницализованого значения, а если не объявлен или объявлен, но он нуллбл, то инициализровать null, как-то больше усложнит всё.

Тут согласен. Наверное так и правда правильней, но меня смутило то, что переход на type hinting в свойствах класса будет не так очевиден как хотелось бы. Боюсь многие наступят на эти грабли.

Как по мне. то и без перехода на 7.5 не должно быть кода, который рассчитывает на дефолтный null без его явного задания.

Тут скорее не "рассчитывает на дефолтный null без его явного задания", а "не рассчитывает на Fatal error без его явного задания".


Проблема не в том, что логика приложение может быть построена на том, что значение по умолчанию null. Проблема в том, что обращение к свойству может быть и не в биснес логике, а где-то на низкоуровневых слоях в сторонних библиотеках типа форм, движка БД, шаблонгизатора и т.д. где скорее важно есть ли значение у свойства или нет.


К примеру, ты можешь не ожидать, что этот шаблон может падать с Fatal error у некоторых пользователей:


Возраст пользователя {{ app.user.age }}

Или форма после отправки может падать с Fatal error если пользователь заполнил не все поля формы или подменил какие-то поля формы.

Точнее нет. После отправки формы скорей можно схлопотать TypeError, а Fatal error скорей при рендере или валидации формы.

Ну, такие кейсы должны быть обнаружены когда принимается решение затипизировать давно существующее свойство. И, скорее всего для начала это будет nullable с явным null, как раз чтобы избежать подобного.

Я об этом и говорю, что необходимость объявления свойства как nullable в явном виде при переходе на PHP 7.4 не очевидна.
Не смотря на то, что я изучал вопрос type hunting свойств класса, я упустил из виду эту особенность. Безусловно это полностью моя вина и невнимательность, но я не вижу, что бы кто либо делал акцент на этой особенности. И в RFC этот нюанс описан вскользь и при беглом осмотре его легко упустить. Отсюда я предполагаю, что с этой проблемой могу столкнуться не только я, а ещё очень многие разработчики которые не слишком внимательно следят за всеми фичами в PHP. Хотя возможно мои домыслы надуманы и ни какой проблемы нет. Время покажет.

Sign up to leave a comment.