Pull to refresh

Comments 51

Запрет динамических свойств легко обходится.
class FooBar {
    private array $properties = [];
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
    public function __get(string $name): mixed
    {
        return $this->properties[$name] ?? null;
    }
}
В статье об этом и упоминается. __get() / __set() никто не отменял
В статье сказано, что напрямую устанавливать динамические свойства будет запрещено.

В вашем примере выше динамические свойства никто и не устанавливает - идет работа с предопределенным массивом. Или я вас не так понял?

Так это и не напрямую

class FooBar {
    private array $properties = [];
    public function __set(string $name, mixed $value): void
    {
        $this->properties[$name] = $value;
    }
    public function __get(string $name): mixed
    {
        return $this->properties[$name] ?? null;
    }
    public function __isset(string $name): bool
    {
        return array_key_exists($name, $this->properties);
    }
}

$foo = new FooBar();
$foo->bar = 123;

var_dump(isset($foo->bar)); // true
var_dump(property_exists($foo, 'bar')); // false

Мы называем это депрекацией (deprecation), а про таковые фичи иногда говорим, что они устарели

translate.google.com/?sl=en&tl=ru&text=Deprecated&op=translate
Почему иногда? Иногда устарели, а иногда deprecated? Что мешает всегда называть «устаревшей», понты?
Простите, но тупой транслит уже порядком надоел.
Например, потому что слово deprecated имеет в английском языке не такой смысл, как слово «устаревший» в русском. Проще говоря, формально перевод из гугл-транслейта неверный. По смыслу ближе что-то вроде «неодобряемый».
В каком словаре найти правильный смысл? К тому-же, везде, где мне встречалось depricated переводили и использовали как устаревший, и ни у кого вопросов не возникало. И только в этом блоге, везде «деприкация»
Хорошие варианты. Если учесть, что depricated методы выводят из эксплуатации со временем (через релиз обычно или как заведено в команде), то «устаревший» имеет вполне устоявшийся (add: и достаточно однозначный) смысл, имхо.

Только deprecated.
Это тем более важно, что есть ещё depreciated.
Английская языка ошень трудный!

Верно, опечатался. У второго варианта, совсем другой смысл

Ну я бы не сказал, что совсем другой, кстати. "Потерявший ценность" и "осуждаемый" — в целом, подходит и для функционала, который deprecated. Просто оттенки другие.

Контест все-таки играет роль.
Ведь если код используют, то он ценность имеет, а в случае устаревания, он остается, но в другой форме.
А осуждаемый — тут на ум приходит только rm /usr /lib в bubmlebee и еще похожая ситуция была емнип. Откуда появилась куча мемов с Ди Каприо, вида
— Как ты почистил диск?
— Я установил/обновил bumblebee

Кстати, есть хорошие по смыслу понятия, описывающие стадии deprecated: подлежащий списанию и списанный. Но вряд ли они активно войдут в обиход.

Списанный — это уже удаленный функционал по сути)
add: и достаточно однозначный
В том то и дело, что не совсем. Из заголовка вроде «устаревшие вещи в таком-то языке» без контекста непонятно, о чем пойдет речь: о deprecated или о том, например, что автор лично считает устаревшим (outdated по-английски). С++, ага.

Если бы только транслит у них был тупым ) Остальной их промто-позор ещё и врёт )

PHP 8.2 объявляет устаревшими некоторые виды callable, которые не работают в виде  $callable().

Незатронутые виды callable

...

Эти виды callable будут работать без каких-либо уведомлений о депрекации.

Я этот пассаж могу понять только как «незатронутые виды тоже устарели, но на них [пока] не ругаются».

 Возьмем, к примеру, Laravel Elquent ORM, который очень сильно зависит от динамических свойств для своих свойств и взаимосвязей

...

Классы с магическими методами __get и __set

Не должно на него повлиять.

https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L2075

Согласен, здесь повлияет.

Нет, не влияет. Там есть проверка на существование метода. Все ORM-ки подвида ActiveRecord работают с массивом под капотом, а не просто несуществующие проперти проставляют.

Да, вы правы, к сожаленью комментарии нельзя редактировать, когда они на проверки у модератора. Я поспешил с первым комментом.

И при этом в 8.0 они ввели динамические свойства в конструкторе. Промоуцию, простите. Здесь играем, здесь не играем.

Они не динамические. Просто объявляются совместно с конструктором.

Ну скажем и не совсем статические

> Constructor Property Promotion is not internally handled as an Abstract Syntax Tree transformation. This means if you inspect the AST (with an extension such as php-ast), you will still see the code as written with property visibility modifiers right in the constructor.

https://php.watch/versions/8.0/constructor-property-promotion

Они всё равно становятся полями объектов, притом до того, как выполнение дойдёт до тела конструктора.

Оттуда же, следующий абзац:

Reflection API, it will seamlessly return information about both standard and constructor-promoted properties all the same.

И отличие только здесь:

In Reflection API, ReflectionProperty and ReflectionParameter classes will have a new method isPromoted to determine if the parameter/property was declared in a constructor.

Вы правы, и все же Reflection API не бесплатно:

https://gist.github.com/mindplay-dk/3359812

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

В других вещах такие вещи есть и ничего, хорошо себя чувствуют. Такие вещи очень классно для TDO заходят.

Такие вещи дают возможность реализовывать неявное поведение, что вкупе с депрекейшенами динамических пропертей напоминает шизофрению. И я с вами согласен - для DTO это отличная штука. Но вот ведь в чем загвоздка, там где есть смысл рассуждать о DTO и о паттернах вообще, экономия на спичках в виде переноса объявления свойства в конструктор, не имеет смысла. А вот в крудописании крудов на скорость, которые послезавтра выкинут на свалку - очень годная фича.

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

при фактической возможности обходить эти ворнинги и делать то же самое

насколько я помню проблема не в том, что можно делать "то же самое", а в том, что под капотом динамические свойства (в том виде, в котором они объявляются устаревшими) создают проблемы.

И в целом, наверное, само по себе наличие плохой практики не должно являться достаточной причиной для ломающих изменений в языке.

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

Лично для меня это будет вырождаться в одну и ту же проблему: я не смогу взглянуть в начало класса и посмотреть какие свойства там есть. Мне нужно будет искать конструктор и смотреть, что запромоутилось оттуда. Конструктор не всегд пишут как первый метод. Вы можете возразить, что в случае иерархии все равно нужна IDE, чтобы смотреть что откуда пришло, а она и промоушены корректно отобразит. Только вот это означает, что простого синтаксического разбора чтобы понять, какие есть свойства уже недостаточно. Нужно делать рефлексию, что тяжелее.

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

У каждого инструмента свой область применения. У этого-это дтошки, где кроме этих свойств и нет ничего.
В остальных случаях пишем как обычно.

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

Вы смешиваете мух с котлетами. Ещё волшебные кавычки пожалейте. Или там результат сравнения 0 == "абв".


Выпиливание из пхп детских болезней не имеет никакого отношения к объявлению свойств в конструкторе.
У динамических свойств не было никакой "области применения", кроме говнокода. Поэтому они и выпиливаются. Всё просто как 5 копеек, а вы разводите какую-то философию на пустом месте.

На самом деле они не выпиливаются, а отсекается один из вариантов их реализации в угоду второму, правильному. За которые надо будет заплатить от полутора до трёх строк кода.

Ну а если в проекте они активно используются, то трейты спешат на помощь.

> Вы смешиваете мух с котлетами. Ещё волшебные кавычки пожалейте. Или там

> результат сравнения 0 == "абв".

Нет же. Динамические свойства, промоушен, волшебные кавычки - это способы сделать неочевидное поведение. А то что начиная с версии 8.0 починили сравнения числа со строкой - это очевидное поведение.

> Выпиливание из пхп детских болезней не имеет никакого отношения к

> объявлению свойств в конструкторе.

Так из языка и не выпиливают детские болезни, типа неконсистентности стандартной библиотеки, а буквально ищут где светло, а не там где надо.

> У динамических свойств не было никакой "области применения", кроме

> говнокода. Поэтому они и выпиливаются.

В этом я с вами согласен. Но создатели Eloquent с вами несогласны, и те кто им пользуется также. Наверняка есть создатели всяких десериализаторов, которые тоже посчитали так.

> Всё просто как 5 копеек, а вы разводите

> какую-то философию на пустом месте.

Да, для меня все просто, у PHP нет вменяемой стратегии развития. А это, без всякой философии, если судить по текущим подвижкам приведет к куче синтаксического сахара и оставлению детских болезней, типа стандартной библиотеки, однопоточного ядра, как есть.

Eloquent не использует динамические свойства, он работает через __get/__set и массив хранящий «динамические свойства» под капотом.

оставлению детских болезней, типа стандартной библиотеки, однопоточного ядра, как есть.

Стандартную библиотеку понемногу правят. Медленнее, чем стоило бы, но всё же:

1) https://wiki.php.net/rfc/mysqli_execute_query

2) https://wiki.php.net/rfc/random_extension_improvement

3) https://wiki.php.net/rfc/strtolower-ascii (тут бы я предпочёл выпилить сам setLocale как зло большее, чем магические кавычки)

4) https://wiki.php.net/rfc/mysqli_support_for_libmysql

5) https://wiki.php.net/rfc/remove_utf8_decode_and_utf8_encode

6) https://wiki.php.net/rfc/iterator_xyz_accept_array

7) https://wiki.php.net/rfc/redact_parameters_in_back_traces

8) https://github.com/php/php-src/blob/master/UPGRADING#L28-L39

На тему однопоточного ядра — что поделать, пока есть только Fiber и непонятно удастся ли завезти что-то более серьёзное.

По мне так вообще динамические свойства это плохая практика везде, за исключением stdClass (что и подтверждается авторами php). Единственное место когда я это юзал - это создать такой динамический объект "на лету" и сразу отдать в json например.

Имхо stdClass -- это костыль из древности времён PHP4, одно из самых неудачных решений дизайна стандартной библиотеки языка, который, к сожалению, за 15+ лет так и не отмер.

Обычно такой конструктор будет на первом месте вместо полей, так что вряд ли проблема сильно что-то отстрелит.

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

В любом случае не стоит проблемы стиля называть проблемами языка.

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

А всё равно не сможете, свойства могут быть объявлены в любой части класса ¯\_(ツ)_/¯

Так в конструкторе это ж другое вроде. В конструкторе мы при проектировании класса указываем какие свойства будем создавать, указывая соответственно их типы и модификаторы доступа. Это ж не та ситуация, когда из клиентского кода пихают что попало в объект используя ->

Sign up to leave a comment.