Комментарии 316
Как же я буду рад, если это все произойдет!
Произойти должно не это. Авторы должны посмотреть как используют их язык и сделать все возможное что бы облегчить его использование. А сейчас в тренде у нас, например, аннотации, ради которых приходится парсить комментарии. Но конечно же, зачем думать как сделать нормальным данный механизм, сообщество еще пять лет будет одним глазом в доку смотреть, другим в код — это же так удобно. Они лучше пропуск параметров запилят
Нельзя сказать, что не смотрят на использование. Свойства вон добавляют. А то меня каждый раз передёргивает, когда ради свойств я парсю строчки.
Свойства это дальнейшее развитие __get/__set которым уже много-много лет. А «аннотации» появились недавно — по сути команда доктрины второй их перетащила в язык
«Магические» методы, оперирующие на строчках — это кривые костыли, и ничего более. Это не развитие, а переосмысление.
Тогда непонятно, зачем столько негодования и рассказов, что авторы языка должны делать.
Может потому, что данный язык не так давно был моим основным и мне интересно дальнейшее его развитие даже не смотря на то, что я вряд-ли когда-нибудь к нему вернусь?
yield очень порадовал!
Ага, это уже давняя мечта. С того момента, как увидел это в питоне.
После этого всего останется добавить строгую типизацию и приделать компилятор =)
Ну зачем же писать самим, генерить байткод для jvm и llvm
Чем не устраивают существующие кэши опкода или хипхоп?
В хипхопе очень много проблем, в нем развивают только те фичи, которые нужны Facebook.
Если, допустим, затачивать новый проект конкретно под хипхоп — еще вариант, то с компиляцией старых больших проектов, так сказать, пичалька.
Если, допустим, затачивать новый проект конкретно под хипхоп — еще вариант, то с компиляцией старых больших проектов, так сказать, пичалька.
А вы думаете, что в случае появления нативной компиляции и статической типизации старые большие проекты не придётся переписывать?
Ммм, компилировал ряд больших старых проектов хипхопом, не умер.
Из проблем только то, что пришлось ряд расширений PHP портировать под хипхоп (и что сторонние расширения хипхоп без плясок не подключает). В остальном никаких проблем. Каких фич не хватает?
Из проблем только то, что пришлось ряд расширений PHP портировать под хипхоп (и что сторонние расширения хипхоп без плясок не подключает). В остальном никаких проблем. Каких фич не хватает?
type hinting для всех типов данных решит, имхо, бОльшую часть проблем, которую решает статическая типизация.
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) { ... }
Нет никакого способа установить $report_errors = false без повторения двух других значений по умолчанию. Для решения этой проблемы предлагается использовать пропуск параметров:
create_query("deleted=0", "name", default, default, false);
Думаю, не сильно этот синтаксис поможет.
Сделали бы уже как в питоне
create_query("deleted=0", "name", $report_errors=false);
, было бы круто.Согласен
Именно так — нельзя, так как будет конфликтовать с текущим поведением. Скорее уж как-то так:
create_query("deleted=0", "name", "report_errors"=>false)
И в случае переименовывания параметров этого метода придется переписывать весь код, который его использовал? На фиг… «default» в этом плане гораздо нагляднее.
Если меняется api, то код тоже, скорее всего, поменяется
Может поменяться только имя параметра.
Рефакторинг
Почему в рамкать рефакторинга может поменяться имя переменной в заголовке, но не может поменятся название метода?
Всё, что внутри метода относится к внутренней реализации и внешний код не должно волновать как называется параметр функции — $cnt или $totalPages.
Переименование может быть выполнено для большей ясности (придумали более чёткое/правильное название), или в случае выноса части функционала в другие внутренние методы, когда в таком контексте эта переменная уже принимает некий другой смысл (более чёткий, или наоборот более общий), выполняя при этом ту же функцию.
В общем, для лучшей внутренней читаемости кода может потребоваться переименование внутренней реализации. Тем кто использует этот API снаружи вообще должно быть до лампочки до начинки.
Переименование может быть выполнено для большей ясности (придумали более чёткое/правильное название), или в случае выноса части функционала в другие внутренние методы, когда в таком контексте эта переменная уже принимает некий другой смысл (более чёткий, или наоборот более общий), выполняя при этом ту же функцию.
В общем, для лучшей внутренней читаемости кода может потребоваться переименование внутренней реализации. Тем кто использует этот API снаружи вообще должно быть до лампочки до начинки.
«Внутри метода» для меня начинается со знака { в Си-подобных языках. И мя параметра это интерфейс прежде всего, даже если он средой исполнения никак не контролируется. Если возникла необходимость переименовать реализацию, то просто сделайте первой строкой в теле метода $new_name = $old_name. А вот изменение имени параметра (части интерфейса) должно свидетельствовать об изменении поведения.
Всё, что внутри метода относится к внутренней реализации и внешний код не должно волновать как называется параметр функции — $cnt или $totalPages.
Это кто вам такое сказал? Есть куча языков и фреймворков, которые подтверждают ошибочность ваших слов.
В случае переименования функции тоже придётся переписывать код.
И вариант с именованными параметрами куда удобнее чем передавать массив типа $options, у которого неизвестно какие ключи.
Если переменные назвать сразу правильно и к месту, то переименовывать не придётся, а если и возникнет вдруг такая необходимость, то в нормальных средах есть рефакторинг кода.
Я только за введение именованных параметров:)
И вариант с именованными параметрами куда удобнее чем передавать массив типа $options, у которого неизвестно какие ключи.
Если переменные назвать сразу правильно и к месту, то переименовывать не придётся, а если и возникнет вдруг такая необходимость, то в нормальных средах есть рефакторинг кода.
Я только за введение именованных параметров:)
> И вариант с именованными параметрами куда удобнее чем передавать массив типа $options, у которого неизвестно какие ключи.
В качестве ключей можно использовать константы класса (многословно, да). Да и потом, тут многие пишут «20 параметров слишком много», какой смысл этой «фичи» при 4-5 параметрах? Никакого.
А насчет рефакторинга — не все IDE его поддерживают (привет PDT), к сожадению. Да и изменить только название метода гораздо быстрее и проще чем проверять и изменять еще и его аргументы (имена которых, ИМХО, вообще относятся к внутренней реализации метода и не должны никаким образом влиять на вызывающий код).
В качестве ключей можно использовать константы класса (многословно, да). Да и потом, тут многие пишут «20 параметров слишком много», какой смысл этой «фичи» при 4-5 параметрах? Никакого.
А насчет рефакторинга — не все IDE его поддерживают (привет PDT), к сожадению. Да и изменить только название метода гораздо быстрее и проще чем проверять и изменять еще и его аргументы (имена которых, ИМХО, вообще относятся к внутренней реализации метода и не должны никаким образом влиять на вызывающий код).
Возможен компромисс вида:
Как некое подобие передачи через массив
или
create_query("deleted=0", "name", $report_errors=>false)
Как некое подобие передачи через массив
create_query("deleted=0", "name", array($report_errors=>false))
или
create_query("deleted=0", "name", [$report_errors=>false])
Точно так же сейчас можно сказать, что если поменять порядок аргументов функции, то весь тоже придётся переписывать.
А я предложил бы просто ставить запятые без параметров:
Таким образом работает, например, цикл for. Сразу видно, сколько параметров, в каком порядке идут, и при рефакторинге если сменится имя входящего параметра функции — не будет никаких проблем.
create_query("deleted=0", "name", , , false);
Таким образом работает, например, цикл for. Сразу видно, сколько параметров, в каком порядке идут, и при рефакторинге если сменится имя входящего параметра функции — не будет никаких проблем.
Ваш вариант лучше предложенного, но тоже ужасен. Не должно быть методов с 20-ю аргументами, потому что такой код невозможно читать, не вызывая справку на каждой строчке.
Но что если такая функция уже есть, как встроенная?
Легче когда передаётся один-единственный массив, ключи которого вообще никак (средствами языка, и даже сторонними типа phpdoc) не документируются? Легче вместо «лезть в справку» (а хорошая IDE подсветит сигнатуру автоматом) лезть в тело и полностью его анализировать?
Мне тоже кажется это самым логичным синтаксисом. Очень давно такого не хватало.
Когда-то давно, когда первый раз возникла необходимость оставить не_последний параметр в значении по-умолчанию, я именно такой синтаксис и использовал. И убедился, что он не работает :)
Когда-то давно, когда первый раз возникла необходимость оставить не_последний параметр в значении по-умолчанию, я именно такой синтаксис и использовал. И убедился, что он не работает :)
Сможете закинуть с рассылку internals?
отличная мысль, гораздо лучше default, тем более, что в list() такое уже используется
На сколько я знаю, сейчас это можно сделать просто указав значение пропускаемого параметра, как NULL, и оно примет значение по умолчанию:
create_query("deleted=0", "name", NULL, NULL, false);
Если в функции это реализовано вручную, то да. А так нет.
function some($arg1, $arg2 = 'some', $arg3 = 5)
{
echo $arg1 . ' ' . gettype($arg1) . PHP_EOL; // 1.1 double
echo $arg2 . ' ' . gettype($arg2) . PHP_EOL; // NULL
echo $arg3 . ' ' . gettype($arg3) . PHP_EOL; // 100 integer
}
some(1.1, null, 100);
Хотя нет, я не прав, я внутри уже сам обрабатывал эти NULL, и преобразовывал в значения по умолчанию. Сорри а дезинформацию.
Нельзя — в метод будет передан null, а не значение по умолчанию.
Тоже хочу именованные аргументы…
А в VB это пишется так:
Но полагаю, что это не самый хороший вариант, так как можно случайно пропустить какойто параметр, а парсер на это даже ничего не скажет.
create_query("deleted=0", "name", , , false)
Но полагаю, что это не самый хороший вариант, так как можно случайно пропустить какойто параметр, а парсер на это даже ничего не скажет.
Отуствие аннотаций в списке свидетельствует о том, что язык развивается сам по себе, а приложения пишутся сами по себе. Впрочем, как по мне, тут вина не столько разработчиков языка, сколько фреймворков предлагающих их использовать.
Понравились getters, setters, генераторы (привет руби) и FooBar::class (привет он же).
Но чего реально нет, каких-то нормальных механизмов задавать конфигурацию на PHP. Массвы себя изжили, а аннотации (в нынешнем виде) не могут быть отлажены никак кроме как в реалтайме.
Понравились getters, setters, генераторы (привет руби) и FooBar::class (привет он же).
Но чего реально нет, каких-то нормальных механизмов задавать конфигурацию на PHP. Массвы себя изжили, а аннотации (в нынешнем виде) не могут быть отлажены никак кроме как в реалтайме.
И чем же массивы себя изжили? Не модно?
Тем же чем и аннотации — отуствие валидации. Т.е. правильность конфигурации не проверишь пока не запустишь приложение. Тем более не узнаешь, что неправильно написал конфигурацию кеша, пока твой сайт не упал под хабраэффектом.
Т.е. грубо говоря, хотелось, чтобы можно было задавать конфигурацию в соответствии со схемой.
И я не говорю, про XML. Я говорю, что сам язык должен иметь средства для задания такого рода конфигураций. Chained methods — как вариант. Но аннотации с интерфейсами были бы лучше.
И массивы изжили, да.
Т.е. грубо говоря, хотелось, чтобы можно было задавать конфигурацию в соответствии со схемой.
И я не говорю, про XML. Я говорю, что сам язык должен иметь средства для задания такого рода конфигураций. Chained methods — как вариант. Но аннотации с интерфейсами были бы лучше.
И массивы изжили, да.
По мне лучший формат — YAML.
То есть, вместо того, что бы написать над классом, что у поля name должна быть минимальная и максимальная длинна, оно не может быть null, лучше создать еще один файл с описанием классов, полей и какие методы валидации использовать.
yaml хорош, но аннотации — это нечто другое. Это мегаудобная метаинформация которую я могу получить в райнайме у объекта без лишних проблем.
yaml хорош, но аннотации — это нечто другое. Это мегаудобная метаинформация которую я могу получить в райнайме у объекта без лишних проблем.
После года на симфони2 я ненавижу аннотации. Они мешают читать код.
Приведите пример мешающих читать код аннотаций.
У меня дискомфорт когда у свойства 8 строчек комментариев. А свойств бывает более 10. 100 строчек на свойства — излишек.
А когда эти свойства разнесены по нескольким разным файлам у вас дискомфорта видимо нет?
Нет. Гармония.
Мы, в яве, это пережили, несколько лет назад. На людей любящих xml, в котором раньше любой чих любили описывать и которого иногда было больше нежели самого кода, теперь смотрят косо.
YAML не XML. Гораздо проще и понятнее.
Да какая разница, хоть json/bson, хоть любимый бинарный формат.
Это не читаемо, потому что:
1. это лежит хрен знает где.
2. это лежит хрен знает где в хрен знает каком формате.
3. этот формат хреново описан и хреново поддерживается (если конечно не промышленный стандарт, но там другая пичалька)
4. это далеко от того места где я пишу код (иде мне не подскажет где я не прав) а с аннотациями — на раз
5. этих хреней может быть много
Это не читаемо, потому что:
1. это лежит хрен знает где.
2. это лежит хрен знает где в хрен знает каком формате.
3. этот формат хреново описан и хреново поддерживается (если конечно не промышленный стандарт, но там другая пичалька)
4. это далеко от того места где я пишу код (иде мне не подскажет где я не прав) а с аннотациями — на раз
5. этих хреней может быть много
Ну и yaml нельзя валидировать по схеме. В этом XML выигрывает. Но он менее читабелен, это факт.
В мире EE из одной крайности в другую бросаются. Если вспомнить XML-ки того-же Hibernate, то они до занудства «правильные» и жутко избыточные. Впрочем, как и сам XML. С аннотациями, кстати, сильно лучше не стало (по крайней мере пока я ещё в теме был) потому как во-первых чтобы посмотреть на общую картину нужно было лезть в определённые классы, а во-вторых, конфиг, хоть и в аннотациях был не менее монстроподобным.
Да при любом раскладе лучше не станет, таков мир EE. Он странный, надутый и немного пугающий, сам по себе: смешно выглядит прописывание запросов на несколько строчек в аннотациях в качестве оптимизации запросов которые генерит ORM.
Общую картину на пару десятков (а то и сотен) сущностей думаю вряд-ли можно чем-нибудь посмотреть. Иногда даже схемы не спасение.
Общую картину на пару десятков (а то и сотен) сущностей думаю вряд-ли можно чем-нибудь посмотреть. Иногда даже схемы не спасение.
Вот собственно и пример того, что ни аннотации ни ямл не могут быть идеальным форматом конфигурации.
По мне так лучше задать этому полю value тип со всеми этими ограничениями. Возможно тип типа generic: IntegerInRange<1,5> вместо типа SchoolMark, описываемого отдельно.
Вообще-то что аннотации, что XML, что yaml — одно. Если вы не опишите правила по которым нужно валидировать конфигурацию, ничего валидироваться и не будет и, естественно, аннотации никаким боком не спасут ваше приложение от нагрузок, если вы в них прописали медленный бэкенд для кеша. Ровно как и массивы или yaml. Всё это — обёртка и к валидации отношения никакого не имеет.
Думаю тут под валидацией имелось в виду другое. Я думаю если бы можно было бы написать валидатор, который смог понимать при какой нагрузке что как использовать и пинал разработчика, то мы бы жили немного в другом мире.
Аннотация она часть кода — ее можно посмотреть, если поле объявлено как int, то туда не получиться запихнуть строку, а вот в конфиге yaml или xml — без правил пожалуйста, а проблема всплывет уже в рантайме.
Аннотация она часть кода — ее можно посмотреть, если поле объявлено как int, то туда не получиться запихнуть строку, а вот в конфиге yaml или xml — без правил пожалуйста, а проблема всплывет уже в рантайме.
если поле объявлено как int, то туда не получиться запихнуть строку,
Это называется статическая типизация, а не аннотации. Афаик, аннотации это не указания транслятору, это метаинформация для других частей проекта, которая корректно валидироваться может только в рантайме, по крайней мере для интерпретируемых языков со слабой типизацией, каковым является PHP.
Это называется статическая типизация, а не аннотации. Афаик, аннотации это не указания транслятору, это метаинформация для других частей проекта, которая корректно валидироваться может только в рантайме, по крайней мере для интерпретируемых языков со слабой типизацией, каковым является PHP.
Ну генераторы только в руби есть конечно же.
Асясяй? Какие грабли со свойствами в c#?
Какие грабли? В шарпе свойства реализованы офигительно. Отдельные уровни доступа, полиморфизм, вынесение в интерфейсы — всё есть.
Остальное — это уже культура программирования. Например, свойства при чтении должны возвращать только что записанное. Не быть тяжеловесными. Ну, то есть быть свойствами.
Остальное — это уже культура программирования. Например, свойства при чтении должны возвращать только что записанное. Не быть тяжеловесными. Ну, то есть быть свойствами.
inteface ISample {
int Prop {get; set;}
int ReadOnlyProp {get;}
}
Свойства в c# это вообще образец удобства синтаксиса описания свойств. Жаль что в Java/AS3 «пошли своим путем». А в PHP я magic __get/__set принципиально не использую, хотя иногда проперти бы и пригодились, но проще уж через get/set методы, они хоть в автокомплите нормально всплывают. Лично я очень раз что в PHP потянули именно такой синтаксис свойств. Запилят — сразу начну использовать.
int Prop {get; set;}
int ReadOnlyProp {get;}
}
Свойства в c# это вообще образец удобства синтаксиса описания свойств. Жаль что в Java/AS3 «пошли своим путем». А в PHP я magic __get/__set принципиально не использую, хотя иногда проперти бы и пригодились, но проще уж через get/set методы, они хоть в автокомплите нормально всплывают. Лично я очень раз что в PHP потянули именно такой синтаксис свойств. Запилят — сразу начну использовать.
О, поколение, не видевшее Делфи…
Очень обрадует наличие Простого API для хеширования пароля
Не совсем понятно, как с солью? Это просто надежнее хеш без соли так? Тогда можно было еще параметр влепить для соли.
Соль, как я понял, автоматически добавляется. возможно, будет и отдельный метод для её генерации.
А чем конкатенация не угодила?
Влепили:
password_hash(string $password, int $algo, array $options = array()) — … The $options array allows for passing in algorithm specific options. In the case of bcrypt, two options are supported: salt and cost. The salt parameter, if provided, will be used in place of an auto-generated salt
password_hash(string $password, int $algo, array $options = array()) — … The $options array allows for passing in algorithm specific options. In the case of bcrypt, two options are supported: salt and cost. The salt parameter, if provided, will be used in place of an auto-generated salt
По поводу пропуска параметров согласен, не удачный вариант.
Я бы предложил нечто такое:
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) {… }
И вызов:
$query = create_query('is_active=1', *5 = false);
Где любая конструкция начинающая с *[1, ...] будет расцениваться как не явный аргумент функции и интерпретироваться уже после того, как все аргументы проставлены.
Например:
$query = create_query('is_active=1', 'name ASC', *2 = 'country DESC');
Таким образом *2 = 'country DESC' оверайдит уже заданный второй аргумент 'name ASC'.
Я бы предложил нечто такое:
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) {… }
И вызов:
$query = create_query('is_active=1', *5 = false);
Где любая конструкция начинающая с *[1, ...] будет расцениваться как не явный аргумент функции и интерпретироваться уже после того, как все аргументы проставлены.
Например:
$query = create_query('is_active=1', 'name ASC', *2 = 'country DESC');
Таким образом *2 = 'country DESC' оверайдит уже заданный второй аргумент 'name ASC'.
Эм…
if(!function_exists('array_column')){ function array_column(…){…}}
не?Учитывая существование пространств имён, если программист использует глобальное пространство — то он ССЗБ.
В древний код можно добавить пространства. Никто никогда не обещал 100%-ной обратной совместимости.
В древний код можно добавить пространства. Никто никогда не обещал 100%-ной обратной совместимости.
Ваше решение проблемы? Не добавлять новые функции? Добавлять в пространство имён PHP_internal_do_no_use? :)
Представьте себе, именно так:
Мануал по пространствам имен на php.net
Note:
Namespace names PHP and php, and compound names starting with these names (like PHP\Classes) are reserved for internal language use and should not be used in the userspace code.
Мануал по пространствам имен на php.net
Как минимум разнести старые функции стандартной библиотеки по пространствам имён \PHP\… с соответствующим переименованием (вместо \array_merge \PHP\Array\merge), объявив старые depricated aliases. Это позволило бы к следующей (6.0?) версии избавиться от унаследованного именования вообще.
Looks like Python.
Вам default и куча аргументов не нравится? Как же интересно должна выглядеть createThumbnail($source, $destination, $cropX1, $cropY1, $cropX2, $cropY2, $backgroundColor, $quality, $forceRegenerate)?
Я не пойму, кому может нравиться такое:
Как скажите в наследнике переопределять эти вещи? parent::set($value) что-ли? И нормально ли будет дебажить тормоза, когда $this->hour = 5, делает меняет не только $hour (да и вообще вдруг тормозит). Это же функция с побочным эффектом, но завуалированная под аттрибут.
Я не пойму, кому может нравиться такое:
public $hours {
get { return $this->seconds / 3600; }
set { $this->seconds = $value * 3600; }
}
Как скажите в наследнике переопределять эти вещи? parent::set($value) что-ли? И нормально ли будет дебажить тормоза, когда $this->hour = 5, делает меняет не только $hour (да и вообще вдруг тормозит). Это же функция с побочным эффектом, но завуалированная под аттрибут.
<?php
$imagine = new Imagine\Gd\Imagine();
// or
$imagine = new Imagine\Imagick\Imagine();
// or
$imagine = new Imagine\Gmagick\Imagine();
$size = new Imagine\Image\Box(40, 40);
$mode = Imagine\Image\ImageInterface::THUMBNAIL_INSET;
// or
$mode = Imagine\Image\ImageInterface::THUMBNAIL_OUTBOUND;
$imagine->open('/path/to/large_image.jpg')
->thumbnail($size, $mode)
->save('/path/to/thumbnail.png')
;
github.com/avalanche123/Imagine/
Предложенный вариант, как было замечено выше, очень походит на зачатки реализации свойств в C#. Но в нем есть модификатор new, который позволяет заменить родительское свойство, а к замененному обращаться через приведение типов.
Переопределять в предложенном варианте PHP, полагаю, так:
Переопределять в предложенном варианте PHP, полагаю, так:
public $hours {
get { return parent::$hours; }
set { parent::$hours = $value; }
}
ClassName::$varName уже для переменных переменных используется.
Не все так плохо.
public $hours = {
get { inherit; }
set { /* Set value here ... */ }
}
Для меня пока что самое ожидаемое нововведение — это когда к объектам можно будет обращаться через точку "."
Ради субъективной читабельности что-ли, так скорее как в Scala -> будет автозаменяться на → в IDEшках, а язык будет поддерживать и то и другое. А точка уже закреплена за конкатенацией, так что не дождетесь :)
Никогда, наверное. Иначе как отличить от конкатенации?
Заменить конкатенацию. на +? :)
«1» + «1»?
Для PHP это не проблема :)
В смысле ещё одно «это невозможно понять, это нужно запомнить».
Так что должно получиться «11» или 2?
Капитан php стал еще могущественнее!
itmages.ru/image/view/585443/11cf38f0
itmages.ru/image/view/585443/11cf38f0
Отказ от поддержки Windows XP и 2003
Мне-то пофиг, конечно, но интересно, что такого есть в семёрке, чего нет в хрюшке, что требует ощутимой работы по поддержке.
Получение полного имени класса
Ещё бы они получение имени функции сделали, чтобы не было «указателей на функцию» в виде
array('Foo', 'bar')
, которые IDE не могут валидировать. Хочу array(Foo::class, Foo::bar)
или что-нибудь вроде того.Пропуск параметров
Этим ужасом никто пользоваться не будет. Что это за синтаксический сахар, если используется длиннющее «default»? Сделали бы именованное обращение к аргументам при вызове функции, если уж так хочется поддерживать говнокодерство с методами на 20 аргументов.
Контроль типа для скалярных значений
Наконец-то они одумались! Нужна не строгая проверка на тип, а приведение.
Getters и setters
Наконец-то! Ненавижу, когда ради обращения к свойству приходится производить кучу операций на строках — курам на смех.
Генераторы
Выделение списков и выражения-генераторы
Звучит офигительно! Хочу. Особенно учитывая, какой кошмарный код приходится писать для реализации LINQ в PHP — при использовании ленивых вычислений код становится трудно читаемым.
Этим ужасом никто пользоваться не будет… если уж так хочется поддерживать говнокодерство с методами на 20 аргументов
Ошибаетесь. И я еще жду ответа на вопрос как разговнокодить createThumbnail($source, $destination, $cropX1, $cropY1, $cropX2, $cropY2, $backgroundColor, $quality, $forceRegenerate)
> И я еще жду ответа на вопрос как разговнокодить createThumbnail
В идеально мире: создать класс Thumbnail, в конструктор передавать $source, также добавить в него методы для установки всех свойств (setCrop и т.д.) и потом вызывать create($destination).
В идеально мире: создать класс Thumbnail, в конструктор передавать $source, также добавить в него методы для установки всех свойств (setCrop и т.д.) и потом вызывать create($destination).
также добавить в него методы для установки всех свойств
Фигня это, а не идеальный мир, имхо. Нафига писать 7 вызовов set* и в конце 1 create вместо того чтобы вызвать create с 8 параметрами? И, кстати, а чего для desination отдельного set не предусмотрели?
Фигня это, а не идеальный мир, имхо. Нафига писать 7 вызовов set* и в конце 1 create вместо того чтобы вызвать create с 8 параметрами? И, кстати, а чего для desination отдельного set не предусмотрели?
> Нафига писать 7 вызовов set* и в конце 1 create вместо того чтобы вызвать create с 8 параметрами?
Ниже ashofthedream почти тоже самое написал, но если вам непонятно в виде слов, то вот код:
$thumb = new Thumbnail($source).
$thumb->setCrop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb->setBackgroundColor($backgroundColor);
$thumb->setQuality($quality);
$create = $thumb->create($destination, $forceRegenerate);
if (!$create) {
// bla bla bla
}
Непонятно где вы тут семь сеттеров насчитали. На последний вопрос думаю не нужно отвечать?
Ниже ashofthedream почти тоже самое написал, но если вам непонятно в виде слов, то вот код:
$thumb = new Thumbnail($source).
$thumb->setCrop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb->setBackgroundColor($backgroundColor);
$thumb->setQuality($quality);
$create = $thumb->create($destination, $forceRegenerate);
if (!$create) {
// bla bla bla
}
Непонятно где вы тут семь сеттеров насчитали. На последний вопрос думаю не нужно отвечать?
Мне сложно оценить семантику, но почему не setCropAndBackgroundColor? И что будет если не задать Crop или Quality? Имхо, сеттерами можно либо задавать необязательные параметры, либо изменять установленные конструктором 9в особых случаях рефлексией). Но если математической формуле требуется 8 параметров, то и нужно ей передать 8 параметров. В крайнейм случае сгруппировав их в объекты/массивы, то есть код должен быть типа такого:
Причём $crop введена лишь для удобства чтения, можно было её вставить
$crop = new Crop($cropX1, $cropY1, $cropX2, $cropY2);
$thumb = new Thumbnail($source, $crop, $backgroundColor);
$create = $thumb->create($destination, $forceRegenerate);
if (!$create) {
// bla bla bla
}
Причём $crop введена лишь для удобства чтения, можно было её вставить
new Crop($cropX1, $cropY1, $cropX2, $cropY2);
в конструктор Thumbnail
непосредственно.> Мне сложно оценить семантику, но почему не setCropAndBackgroundColor?
Потому что мне так удобнее :) Если что-то не указано, то будут использованы параметры по умолчанию, которые в *моей* реализации имеют подходящие для моего случая значения.
> $crop = new Crop($cropX1, $cropY1, $cropX2, $cropY2);
Если Crop используется только для хранения четырех значений, то он, ИМХО, лишний и лучше просто передать их в метод.
> $thumb = new Thumbnail($source, $crop, $backgroundColor);
Это практически ничем не отличатся от такого:
$thumb->setCrop($crop);
$thumb->setBackgroundColor($backgroundColor);
Все зависит от личных предпочтений разработчика, кому то вон цепочки нравятся :)
Потому что мне так удобнее :) Если что-то не указано, то будут использованы параметры по умолчанию, которые в *моей* реализации имеют подходящие для моего случая значения.
> $crop = new Crop($cropX1, $cropY1, $cropX2, $cropY2);
Если Crop используется только для хранения четырех значений, то он, ИМХО, лишний и лучше просто передать их в метод.
> $thumb = new Thumbnail($source, $crop, $backgroundColor);
Это практически ничем не отличатся от такого:
$thumb->setCrop($crop);
$thumb->setBackgroundColor($backgroundColor);
Все зависит от личных предпочтений разработчика, кому то вон цепочки нравятся :)
Потому что мне так удобнее :)
Вопросов больше нет :(
Вопросов больше нет :(
> Вопросов больше нет :(
А что вы хотели услышать? Что не логично (как минимум) изменять совершенно разные по смыслу свойства через один метод? Ну, так, это вроде и так всем известно. Смысл повторяться?
С тем что «каждый в итоге пишет именно так как ему удобнее в конкретном проекте» (например, вам все сразу передать в конструкторов, мне — изменить позже через сеттеры) спорить не будете? Поэтому нет никакого смысла обсуждать обычные пять строк кода, тем более, что он полностью отвечает на изначально заданный вопрос (хотя и он сам по себе излишен — все написано в первом комментарии).
А что вы хотели услышать? Что не логично (как минимум) изменять совершенно разные по смыслу свойства через один метод? Ну, так, это вроде и так всем известно. Смысл повторяться?
С тем что «каждый в итоге пишет именно так как ему удобнее в конкретном проекте» (например, вам все сразу передать в конструкторов, мне — изменить позже через сеттеры) спорить не будете? Поэтому нет никакого смысла обсуждать обычные пять строк кода, тем более, что он полностью отвечает на изначально заданный вопрос (хотя и он сам по себе излишен — все написано в первом комментарии).
Просто очень разговнокодить, достаточно сделать из вызова одного метода некий билдер.
Thumbnail.from(source)
.crop(100, 100)
.quality(3)
.forceRegenerate(true)
.blabla(somearg)
.create(destination);
Функция не обязательно должна иметь много параметров, что бы захотеть их пропустить:
3 параметра, 2 из которых не обязательны — это много или мало?
htmlspecialchars(<4 параметра>) — это кривая функция?
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' ]] )
3 параметра, 2 из которых не обязательны — это много или мало?
htmlspecialchars(<4 параметра>) — это кривая функция?
Что htmlspecialchars, что html_entity_decode — не совсем красивые (да, тут наверное можно упомянуть слово кривые) функции, по хорошему они должны выглядеть так:
htmlspecialchars разбивается так же, ну вот не нужно мне указывать какие-то там флаги, зачем мне писать их, если я хочу указать кодировку? Правильно — незачем.
Но, к сожалению, дизайн языка не позволяет делать function overloading и поэтому мы имеем то, что имеем
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' ]] )
html_entity_decode( string $string [, string $encoding = 'UTF-8' ] )
html_entity_decode( string $string [, int $flags = ENT_COMPAT | ENT_HTML401])
htmlspecialchars разбивается так же, ну вот не нужно мне указывать какие-то там флаги, зачем мне писать их, если я хочу указать кодировку? Правильно — незачем.
Но, к сожалению, дизайн языка не позволяет делать function overloading и поэтому мы имеем то, что имеем
зачем мне писать их, если я хочу указать кодировку?
Ну так не пишите:
html_entity_decode($string, , 'UTF-8'); // Отличный, удобный вариант.
// Это универсальнее, проще и понятнее чем function overloading.
Неудобно когда надо еще условие, например:
html_entity_decode($string, empty($param) ? default : $param, 'UTF-8');
В таком исключительном случае, вы можете передать дефолтное значение
Но:
1. такое приходится писать крайне редко. И ради 1% случаев заставлять писать себя «default» во всех остальных 99% случаев как то не гуманно. Мне в 100500 раз проще написать "" чем «default».
2. Я бы вообще не использовал тернарные условия внутри других длинных выражений. Тернарники и без того имеют сложно-читаемый синтаксис, по этому я бы разнёс на две строки:
3.!!! САМЫЙ ГЛАВНЫЙ ДОВОД!!! Предложенный вами синтаксис не локаничен! Например, я не могу разбить его на 2 строки:
4. define('default', 'custom'); // Что произойдёт? Или теперь нельзя создавать константу с именем 'default'? Ох, сколько же ещё зарезирвированных слов придумают изобретатели php и как все эти слова запомнить?
html_entity_decode($string, empty($param) ? (ENT_COMPAT | ENT_HTML401) : $param, 'UTF-8');
Но:
1. такое приходится писать крайне редко. И ради 1% случаев заставлять писать себя «default» во всех остальных 99% случаев как то не гуманно. Мне в 100500 раз проще написать "" чем «default».
2. Я бы вообще не использовал тернарные условия внутри других длинных выражений. Тернарники и без того имеют сложно-читаемый синтаксис, по этому я бы разнёс на две строки:
$flags = empty($param) ? (ENT_COMPAT | ENT_HTML401) : $param;
html_entity_decode($string, $flags, 'UTF-8');
3.!!! САМЫЙ ГЛАВНЫЙ ДОВОД!!! Предложенный вами синтаксис не локаничен! Например, я не могу разбить его на 2 строки:
$flags = empty($param) ? default : $param; // что здесь обозначает default ???
html_entity_decode($string, $flags, 'UTF-8');
4. define('default', 'custom'); // Что произойдёт? Или теперь нельзя создавать константу с именем 'default'? Ох, сколько же ещё зарезирвированных слов придумают изобретатели php и как все эти слова запомнить?
По поводу (4) — скорее всего да, думаю будет зарезервированное слово, как null, true, false. И тогда конечно будет работать и (3) пункт (самый главный довод).
По поводу тернарных (2) — оффтопик, конечно лучше на другой строке, а вообще всё индивидуально.
Касательно (1) — писать default в 99% случаях — на это есть питоновский дзен — «Явное лучше, чем неявное».
По поводу тернарных (2) — оффтопик, конечно лучше на другой строке, а вообще всё индивидуально.
Касательно (1) — писать default в 99% случаях — на это есть питоновский дзен — «Явное лучше, чем неявное».
По поводу (4): зачем ещё одно зарезервированное, если можно без него? Как же питоновский дзен? Представьте себе сколько появится вопросов на форумах от пхп-джуниров: «что такое default?».
Самый главный пункт №3 работать НЕ будет, потому что придётся ещё вводить новый специальный тип значений. «тип значение» != «зарезервированному слову». Иначе, представляете такой код:
По поводу №1. Это гораздо нагляднее:
чем это:
В первом случае всё чётко и понятно: параметр не указан! Даже джуниоры не будут задавать вопросы на форумах — всё чётко и понятно!
Во втором случае надо ВЧИТАТЬСЯ и ОСМЫСЛИТЬ, вспомнить зарезервированное слово default, не перепутать его с null и константой defence :). Возможно у питонщиков это уже вшито в мозг с рождения, но у нас пэхапэшников пока нет.
Самый главный пункт №3 работать НЕ будет, потому что придётся ещё вводить новый специальный тип значений. «тип значение» != «зарезервированному слову». Иначе, представляете такой код:
$flags = empty($param) ? default : $param;
var_dump($flags); // что здесь будет?
По поводу №1. Это гораздо нагляднее:
html_entity_decode($string, , 'UTF-8');
чем это:
html_entity_decode($string, default, 'UTF-8');
В первом случае всё чётко и понятно: параметр не указан! Даже джуниоры не будут задавать вопросы на форумах — всё чётко и понятно!
Во втором случае надо ВЧИТАТЬСЯ и ОСМЫСЛИТЬ, вспомнить зарезервированное слово default, не перепутать его с null и константой defence :). Возможно у питонщиков это уже вшито в мозг с рождения, но у нас пэхапэшников пока нет.
зачем ещё одно зарезервированное, если можно без него?
Оно уже зарезервировано для использования в switch..case..default. Так что нового зарезервированного слова не появляется.
точно точно! вы правы!
Я пропустил параметр. Что может быть более явным обозначением пропущенного параметра?
А ещё я представляю себе две строчки в документации:
Ну и ещё один питоновский дзен:
есть питоновский дзен — «Явное лучше, чем неявное».
html_entity_decode($string, , 'UTF-8');
Я пропустил параметр. Что может быть более явным обозначением пропущенного параметра?
А ещё я представляю себе две строчки в документации:
Что бы пропустить не обязательный параметр, пропустите этот параметр
// vs
Что бы пропустить не обязательный параметр, укажите специальную конструкцию языка "default"
А почему не empty?Ну и ещё один питоновский дзен:
Особые случаи не настолько особые, чтобы нарушать правила.
это уж вопросы не ко мне, я бы тоже предпочел отсутствие параметра специальному слову — хотя бы для консистентности с list(,$val) = each($arr)
Я пропустил параметр. Что может быть более явным обозначением пропущенного параметра?
Зная любовь PHP ко всяким неявным приведениям типов я, имхо, имею полное право считать, что пропуск параметра приведётся к NULL. Никто мне не докажет, что это менее логично, чем принятие значения по умолчанию в сигнатуре функции. Вот default, да, говорит о том, что если не знаешь о чём это, то нужно заглянуть в ман.
P.S. А константы я бы вообще запретил именовать как-то кроме upper case на уровне синтаксиса.
Зная любовь PHP ко всяким неявным приведениям типов я, имхо, имею полное право считать, что пропуск параметра приведётся к NULL. Никто мне не докажет, что это менее логично, чем принятие значения по умолчанию в сигнатуре функции. Вот default, да, говорит о том, что если не знаешь о чём это, то нужно заглянуть в ман.
P.S. А константы я бы вообще запретил именовать как-то кроме upper case на уровне синтаксиса.
имею полное право считать, что пропуск параметра приведётся к NULL
Не имеете:
$x = ; // это не работает.
Хотя, если «правильно» посчитать, то можно со спокойной совестью пропускать параметры используя null уже сейчас:html_entity_decode($string, null, 'UTF-8');
null — это же ведь «ничто», т.е. я как бы «передал ничто» или «ничего не передал». В оффициальной документации вообще написано, что переменная считается null-ом если она была удалена с помощью unset(). :) Т.е. отстутвующая переменная приравнивается к null.Я это всё к тому, что «считалка» не работает и не надо ничего считать Это же php :(
Это кстати, не единственный приведённый мной аргумент в пользу «пропуска параметра пропуском параметра». Ещё очень важна читабельность (см. 5 комментов выше).
Ну и мне ещё не охото каждый раз как мартышка печатать «default» там где можно ничего не печатать.
P.S. я бы тоже этого хотел. И ещё очень хочу что бы все уровни ошибок были включены без возможности отключения, даже NOTICE.
«передал ничто» ни в коем случае не равно «ничего не передал». Транзакция по счёту на ноль рублей не равна отсутствию транзакции (и даже баланс может измениться при транзакции). Молчание в ответ на вопрос не равно отсутствию того кому вопрос задавать…
Хотя стоп-стоп! Сейчас можно определять константу default!!!
Я проверил на php 5.3.11:
Правда при попытки её использования вылетает ошибка
Но дефайнить её никто не запрещал :) Возвращаю свой плюс обратно :)
Я проверил на php 5.3.11:
define('default', 'custom');
var_dump('test');
Отлично отрабатывает.Правда при попытки её использования вылетает ошибка
define('default', 'custom');
var_dump(default); // Parse error: syntax error, unexpected ...
Но дефайнить её никто не запрещал :) Возвращаю свой плюс обратно :)
Да дефайнить можно что угодно, хоть одинарную кавычку. Использовать потом, правда, неудобно, только через constant();
define("'", 123);
var_dump(constant("'")); // 123
Не всё:
define('true', false); // Notice: Constant true already defined
Кроме уже определенных констант. Это подразумевалось по умолчанию.
Гы.
Это просто жесть :)
var_dump(FALSE);
// bool(false)
var_dump(TRUE);
// bool(true)
define('TRUE', false);
define('FALSE', true);
var_dump(TRUE);
// bool(false)
var_dump(FALSE);
// bool(true)
Это просто жесть :)
Это вы в какой версии нашли?
shock@shock-notebook:~$ php -v
PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch (cli) (built: Jun 13 2012 17:20:55)
Copyright © 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright © 1998-2012 Zend Technologies
shock@shock-notebook:~$ php define.php
bool(false)
bool(true)
bool(true)
bool(false)
function overloading по типу параметров для задания параметров по умолчанию — это костыль, имхо. Пропуск параметров, ключевое слово или именованные параметры выглядят куда лучше этого костыля. У них есть свои плюсы и минусы, но любой из них лучше.
Плюс, как вы предлагаете быть с функцией, у которой 3 строковых параметра, два из которых необязательные?
Плюс, как вы предлагаете быть с функцией, у которой 3 строковых параметра, два из которых необязательные?
Создать класс CreateThumbnailParams. По вкусу можно добавить в CreateThumbnailParams конструктор, присваивающий значения полям по переданному ассоциативному массиву. Будет так:
Ну да, без такого конструктора вызов будет выглядеть не очень лаконично. Но его хотя бы можно будет прочитать, не заглядывая в документацию.
Ну да, с таким конструктором обращение к полям будет через строчки, что в IDE не проверяется. Но IDE можно доработать, в теории.
createThumbnail($mySource, $myDestination, new CreateThumbnailParams(array('quality' => 10)))
Ну да, без такого конструктора вызов будет выглядеть не очень лаконично. Но его хотя бы можно будет прочитать, не заглядывая в документацию.
Ну да, с таким конструктором обращение к полям будет через строчки, что в IDE не проверяется. Но IDE можно доработать, в теории.
Превращать опциональные аргументы в массив аргументов — это еще хуже, не формализованно. Сеттеры как у lastdragon и цепочки вызовов ashofthedream, все это еще куда ни шло. Но когда речь идет о, скажем, непубличной функции, то создавать вместо нее класс — имхо как из пушки по воробьям. Иногда функция таки зависит от 20 параметров. Есть что-то интересно в ObjectiveC стиле, вроде createThubnail($cropX1=>10, $forceRegenerate=>true), но наверное и правда неудобно рефакторить.
20 параметров для функции — это слишком много. Что она должна делать то при этом? А так, люди давно эту проблему решили, в корне, например в том же ObjectiveC. В любом языке должна быть такая вещь:
Все, читаемо, понятно, удобно, быстро, красиво.
foo.do(bar: "this is the bar", really: true);
Все, читаемо, понятно, удобно, быстро, красиво.
Согласен, именованные аргументы хорошая штука
ну так никто не мешает сделать прямо сейчас в php
foo.do({ 'bar' => "this is the bar", 'really' => true });
Еще хуже: как я узнаю, не заглянув фунцкию какие аргументы она принимает, какого они должны быть типа, какие обязательные, а какие нет?
из описания функции вестимо
Опять держать открытым мануал? А если это функция напиана Васей который сидит в трех метрах от меня и правлена Петей который сидит за васей, а комменты он подправить забыл?
Зачем мануал — phpdoc достаточно и нормальный IDE работает по нему или показывает хотя бы. Вася, Петя… вы бы еще про уборщицу вспомнили, которая в теле изменила бы параметр, а в заголовке нет :)
Проблема документации в том, что она очень часто в своих проектах не соответсвует действительности. Да что говорить о документации-то, когда некоторые личности после рефакторинга тесты мьютят потому что лень править и «ну как-нибудь потом»
> вы бы еще про уборщицу вспомнили, которая в теле изменила бы параметр, а в заголовке нет
А вот запросто, видел кучу кода (да и вот прямо сейчас гляжу на него) в котором в phpdoc вообще нет названий аргументов, только их типы. Поэтому phpdoc, в отличие от автокомплита, можно полноценно использовать только в идеальном мире. Да и от его *устаревания* никто не застрахован.
А вот запросто, видел кучу кода (да и вот прямо сейчас гляжу на него) в котором в phpdoc вообще нет названий аргументов, только их типы. Поэтому phpdoc, в отличие от автокомплита, можно полноценно использовать только в идеальном мире. Да и от его *устаревания* никто не застрахован.
Если на уровне синтаксиса будет поддерживаться
то это будет лучше для всех, имхо. Разве что любители удалять гланды через ж… будут недовольны.
foo.do($bar => "this is the bar", $really => true );
то это будет лучше для всех, имхо. Разве что любители удалять гланды через ж… будут недовольны.
> Все, читаемо, понятно, удобно, быстро, красиво.
И куча проблем при рефакторинге.
> 20 параметров для функции — это слишком много.
А при небольшом кол-ве параметров функции эта «фича» совершенно лишняя.
И куча проблем при рефакторинге.
> 20 параметров для функции — это слишком много.
А при небольшом кол-ве параметров функции эта «фича» совершенно лишняя.
эта фича совершенно не лишняя, если даже у нас 3-4 параметра для функции, один из которых не обязателен, а другие просто можем испльзовать в различных вариациях. Таких функций в пхп over 9k и часто приходиться пропускать аргументы
Именованные параметры могут помочь и с повышением читаемости вызова при большом количестве аргументов. Например, возьмем Imagick:
Такой подход заметно упрощает чтение и рефакторинг в использовании метода, особенно при поддержке IDE.
Правда остается непонятно, что при этом делать в случае рефакторинга имен параметров в библиотеке, однако мне не кажется это такой большой проблемой: о том, что трудно поменять параметры местами или что-то добавить ведь никто не плачется?
$im->floodfillpaintimage($iPixel,10,$tPixel,$startX,$startY,false,Imagick::CHANNEL_DEFAULT);
// versus
$im->floodfillpaintimage({
$fill=>$iPixel,
$fuzz=>10,
$bordercolor=>$tPixel,
$x=>$startX,
$y=>$startY,
$invert=>false,
$CHANNEL=>Imagick::CHANNEL_DEFAULT
});
Такой подход заметно упрощает чтение и рефакторинг в использовании метода, особенно при поддержке IDE.
Правда остается непонятно, что при этом делать в случае рефакторинга имен параметров в библиотеке, однако мне не кажется это такой большой проблемой: о том, что трудно поменять параметры местами или что-то добавить ведь никто не плачется?
Черт, никак не запомню как тут правильно код выделять, а предросмотр глючит…
$im->floodfillpaintimage($iPixel,10,$tPixel,$startX,$startY,false,Imagick::CHANNEL_DEFAULT);
// versus
$im->floodfillpaintimage({
$fill=>$iPixel,
$fuzz=>10,
$bordercolor=>$tPixel,
$x=>$startX,
$y=>$startY,
$invert=>false,
$CHANNEL=>Imagick::CHANNEL_DEFAULT });
что при этом делать в случае рефакторинга имен параметров в библиотеке
Это по определению не будет называться рефакторингом, это уже изменение интерфейса со всеми вытекающими…
Это по определению не будет называться рефакторингом, это уже изменение интерфейса со всеми вытекающими…
Будет. Тут нет изменений в интерфейсе (по крайней мере до тех пор пока нет именованных параметров).
Для меня это уже сейчас изменение интерфейса. Думаете замена метода Stack::popArray($countToPop) на метод Stack::popArray($countToLeave) для клиентов метода не будет означать необходимости изменения логики их обращения к методу? Синтаксически, конечно, не будет, но вот семантически скорее всего потребует, и я бы предпочёл чтобы «компилятор» мне выдал Fatal Error, а не утекла база данных несоленых паролей :)
Конкретно этот пример будет, только у вас же кроме изменения параметра, изменена и логика метода => оставить прежнее название не очень хорошее решение.
А вот если было что-то типа b($a, $b), а стало b($start, $length), то нет.
А вот если было что-то типа b($a, $b), а стало b($start, $length), то нет.
Откуда вы знаете, что она изменена? :) Именование параметров внутренне дело функции же! Захотел и изменил имя параметра без изменения логики, захотел изменил логику без изменения имени параметра. Но мне кажется, что чаще встречаются ситуации когда либо меняется и имена параметров, и логика (мой пример), либо имена функции и ей параметров (доведенный до логического конца ваш пример, например, xrange($start, $length) )
>Превращать опциональные аргументы в массив аргументов — это еще хуже, не формализованно.
что с ними не так?
что с ними не так?
Хотя бы что нужно постоянно в документацию лазить, чтобы узнать какие параметры есть. Впрочем, это отчасти решается константами класса (CreateThumbnailParams::QUALITY), но получается многословно.
Интерфейс достаточно описать в описании функции и дока в нормальном IDE будет всегда рядом
Для ключей массивов ни одна IDE не делает авкомплит. Отслеживать изменения в них гораздо сложнее (вручную). Нет проверки в рантайме со стороны языка (снова вручную и при вызове и в самой функции). и т.д.
Ответил выше
ну, как вариант:
use Vendor\Image\Convert as imgconv;
imgconv\from("source.jpg")
->crop([10, 10, 40, 40])
->background(0xaabbcc)
->quality(80)
->regenerate(true)
->to("thumb.jpg");
// vs
createThumbnail("source.jpg", "thumb.jpg", 10, 10, 40, 40, 0xaabbcc, 80, true);
Судя по комментам, написанным во время написания моего — такой вариант весьма мейнстримен
В случае с именованными параметрами это будет выглядеть также читабельно, при этом это уже будет частью языка(то есть не нужно реализовывать функции типа crop, quality).
createThumbnail(
$from => "source.jpg",
$crop => [10, 10, 40, 40],
$background => 0xaabbcc,
$quality => 80,
$regenerate => true,
$to => "thumb.jpg"
);
Если с ООП, то можно наверное так:
Бр… как громоздко… первое что пришло в голову… ну или второе:
Уж извините, спать хочется, возможно завтра будет стыдно за то что написал… В общем позвольте пог… кодить на ночь глядя :) Ну в общем функции с длинным списком параметров были есть и будут.
class Crop
{
public static $x1=0;
public static $x2=0;
public static $y1=0;
public static $y2=0;
public static function set($x1, $y1, $x2, $y2);
}
class ThumbPipe
{
public static $source;
public static $destination;
public static function set($source, $destination);
}
class ThumbProperty
{
public static $backround;
public static $quality;
public static $forceRegenerate;
public static set($bg, $quality=80, $forceRegenerate=false);
}
$crop = Crop::set(1, 10, 52, 30);
$thumb = ThumbPipe::set('/srv/ht...', '/srv..');
$params = ThubmParams::set('#FFEE33');
createThumbnail(ThumbPipe $thumb, Crop $crop, ThumbParams $params);
Бр… как громоздко… первое что пришло в голову… ну или второе:
$crop = array(1, 50, 20, 30);
$params = array('#FFFAAA', 85, true);
createThumbnail($source, $destination, array $crop, array $params);
Уж извините, спать хочется, возможно завтра будет стыдно за то что написал… В общем позвольте пог… кодить на ночь глядя :) Ну в общем функции с длинным списком параметров были есть и будут.
Так однозначно хуже читается. На мой вкус.
Ну в общем меня зациклило на «ну в общем», ну в общем вошел в рекурсию, ну в общем спать.
$crop = array(1, 50, 20, 30);
$params = array('#FFFAAA', 85, true);
createThumbnail($source, $destination, array $crop, array $params);
Здесь абсолютно не решается проблема вызова функции с $source, $destination и $forceRegenerate, не вызывать же createThumbnail($source, $destination, array(), array(null, null, true);
Класс же со статическими методами вообще не тру. Его ни расширить, ни замокать чтобы потестить, ни передать аргументом, ни завести два инстанса (следующий затирает предыдущий).
Наконец-то они одумались! Нужна не строгая проверка на тип, а приведение.У меня несколько иное мнение на этот счет. Можете почитать эту ветку комментов, например. А если коротко — то в современных фреймворках объект, инкапсулирующий запрос, имеет методы для получения ключей с приведеднием к заданному типу. Поэтому строгая типизация, без приведения, лучше, чем приведение «без потерь», так как разработчик всегда знает, какой тип нужно ожидать в том или ином ключе, а строгая типизация делает валидацию неизбежной.
Уже читал эту ветку, и она меня только лишний раз меня убеждает, что строгая проверка не есть хорошо. Собственно:
Строгая типизация — это не PHP-way. PHP — это язык с нестрогой динамической типизацией. Не нужно выворачивать его наизнанку. Если вам хочется чего-то другого, то есть другие языки.
Итого: если вы пользовались тем, что вы описали — то для вас с появлением хинтов ничего не меняется. А если вы не пользовались этим всем — то введение хинтов на скаляры добавит головной боли.
Строгая типизация — это не PHP-way. PHP — это язык с нестрогой динамической типизацией. Не нужно выворачивать его наизнанку. Если вам хочется чего-то другого, то есть другие языки.
По мне так динамичность типизации практически не используется в нормальном коде и от добавления к ней опционально статической хуже никому не будет (ну почти, как не стило почти никому хуже от добавления областей видимости для членов класса). A PHP язык всё же со слабой типизацией, это особый вид нестрогой, но почему-то самый, вроде, популярный в вебе: PHP, JavaScript, ActionScript(не уверен).
>Ещё бы они получение имени функции сделали, чтобы не было «указателей на функцию» в виде array('Foo', 'bar'), которые IDE не могут валидировать. Хочу array(Foo::class, Foo::bar) или что-нибудь вроде того.
Тогда уж просто
Тогда уж просто
Foo::bar
сойдет, указание на класс же есть.Еще предлагаю убрать ключевое словов function (как минимум из декларации методов класса).
Не случится. :-( У разрабов похапэ религия: «Код должен быть читаемым, даже если ты не знаешь язык». :-/ Они фичу по сокращению записи замыканий завернули с таким результатом — это при том, что прилагался патч и всё такое.
Это неплохая вообщем-то религия :)
Для того чтобы не напрягать пальцы есть IDE, а вот с сокращениями надо быть осторожным, ведь найдется кто-нибудь кто их сразу все использует, я вот в Perl с этим столкнулся, вы как-нить посмотрите на досуге, там даже аски-картины рисовать можно :)
Для того чтобы не напрягать пальцы есть IDE, а вот с сокращениями надо быть осторожным, ведь найдется кто-нибудь кто их сразу все использует, я вот в Perl с этим столкнулся, вы как-нить посмотрите на досуге, там даже аски-картины рисовать можно :)
Было бы желание…
#include<stdint.h>// 4
#include<stdio.h>/* 76. 1
..2321 1 57 3
21.... . .. .11 1 2
1 88..1321 2 33 5512 1 277 14 1
099..12.... . .. .... 1 4 11111...111 122 5.1 .
11...221.821112411123455676489 51.176543232666 902 .27 1
10111...1.....................11.417...........1...21..11.
..2239921176566156225563322299887...6533233233182469196894
22...............................111......................
*/// 3269548556987776665556662131223412347543332334543322223456
/*
13.3.37 */char C[120] [60 ];int R[120][60],W,H,J,K,B[61][61],/*
12.2.39 */r,i,j,c,*q =& H,t=7200,x,y,k;int64_t*U,T[28800],*S=/*
11.2.40 */T,O[120], Z[ 120],v,z;void D(){for(k=-1;7200>++k;S[/*
10.39 */k]=v)r=! ~(v=U[k])&&*R[k/60]?2:S[k]-v?1:r;;;;}/*
9.36 */void L( ){for(r=1;r==1;){r=3;;for(i=0;120>/*
9.31 */i;i++){ for(k=z=1,j=0;v=R[i][j];j++)O/*
8.3.32 */[i]|=( 1LL <<v)-1<<k,k+=v,0,Z[i]=z|=1LL<</*
7.3.30 */k++;; v=~ (3LL<<k-2);for(j=-61;++j<60;/*
5.3.29 */v=( v|~ z)&(j<0?v>>1:v<<1|1))v=S[60/*
3.1.3.1.28 */* i +(j < 0?~j:j)]|=j?v:~3;}for(z=0;/*
1.2.4.31 ; */ 7200 >z;z++)i=z/60,j=z%60,(B[i<60?/*
7.5.31 */i:j][ i<60? j:i-60]=~S[z]&O[i]?~S[z]&Z[i]/*
1.6.5.30 ; */?r=0 :(U=O ,1):(U=Z,2))?k=i<60?j+60:j,S/*
5.10.12.16 */[i% 60+60*k]|= ~U[k]:0;U=S; S-=t*=-1;D();z/*
5.11.5.4.12.4 */*9; }}int main( ){for (;K= scanf("%d",R [*/*
15.2.4.4.11.5 */q+c*60]+j)<1? q= &W,j --,2 >++c:'\n';j =-K/*
16.3.4.2.2.5.5 */+getchar()?j+1 :++ *q*0 ); L( );;if (!r/*
14.8.7.3 */)for(K=0;K<W *60;K++) if(K%60 </*
12.1.4.1.6.2 */W&!B[K/60] [ K%60 ] ){for( /*
11.3.4.6.1 */c=64;c--; )if (!(1 &S[K/* ;
10.1.8.8.5.1 */]>>c))U= S ,000,S+= J=14400, D()/* ;
9.8.11.5 */,S[K]=~ (1LL<<c) ,L(),S-=J,S [K]/*
9.5.6.1.2.4.1 */|=r==2? 1LL<< c:0;L( ) ;} q=/* ;
9.3.5.1.5 */&K;;for (J= K=i=0 ; 120/*
3.2.6.5.1 */> i; Z[i]=k --,/* ;
2.6.3.5.1 */ i>59?q =&J :0,/* ;
2.1.2.6.3.6.1 */ * q< k?*q=k :0, 0,C[/* ;
2.1.2.2.1.5.2.5.1 */ i ++ ][ k ]=' ' ){ j=k/* ;
2.1.2.5.5.6.3 */ = 0; for(; x=R[i ][j++] ;/*
4.1.9.7.5.1 */0) k +=sprintf ((00,C[ i]+/* ;
5.19.6.1.2 */k), "%d.",x);}i=~J;;r&1 ||puts ( /*
24.6.3.3 */r?"invalid":"failed"); for(;i <H; i/*
24.1.2.9.7.4 */++,puts(""))for(j=~K;j < W; )putchar( i<0?j<0 ||/*
25.1.2.25 */(k=i+Z[j+60])<0?' ':C[j + 60 ][k]:j<00?(k=j+Z[i])<0?/*
28.1.26 */' ':C[i][k]:"?X "[B[i][j]] ) ,j++;return 0;} /* 2012 */
зачем?
что бы в место него писать возвращаемый тип, или ничего, как в любом нормальном языке. Смешно в 2012-м году такие вещи в коментариях писать
Ну тип это хорошо, но дополнительно, а не как замена.
В питоне и руби def, в джаваскрипте и пхп function. Зачем убирать? Про возвращаемый тип — согласен.
Эмм… Как вы себе это представляете? Так, чтобы в коде не было разночтений?
Чем же вам так не угодил function, если 90% IDE после набора fu по Tab-у сам вставляют слово целиком?
Лично мне «function» не угодил разницей между
и
(Выдуманный синтаксис.)
Впрочем, лично я не за то, чтобы искоренять «function», а чтобы добавить альтернативную краткую запись.
from($categories)
->orderBy(function ($cat) { return $cat['name']; })
->groupJoin(
from($products)
->where(function ($prod) { return $prod["quantity"] > 0; })
->orderByDescending(function ($prod) { return $prod["quantity"]; })
->thenBy(function ($prod) { return $prod["name"]; }),
function ($cat) { return $cat["id"]; },
function ($prod) { return $prod["catId"]; },
function ($cat, $prods) { return array("name" => $cat["name"], "products" => $prods); }
);
и
from($categories)
->orderBy($cat ==> $cat['name'])
->groupJoin(
from($products)
->where($prod ==> $prod["quantity"] > 0)
->orderByDescending($prod ==> $prod["quantity"])
->thenBy($prod ==> $prod["name"]),
$cat ==> $cat["id"],
$prod ==> $prod["catId"],
($cat, $prods) ==> array("name" => $cat["name"], "products" => $prods)
);
(Выдуманный синтаксис.)
Впрочем, лично я не за то, чтобы искоренять «function», а чтобы добавить альтернативную краткую запись.
А как будет выглядеть такой упрощённый синтаксис в случае если у функции больше одного параметра?
Последняя «лямбда» — как раз пример функции с двумя параметрами. Они в скобки берутся.
Тут другой вопрос интереснее — в отличие от того же C# все используемые извне переменные нужно объявлять вручную с помощью use(). Поэтому, если стремиться покрыть и этот функционал, то надо что-то придумывать. Можно такую же абракадабру, как в C++, устроить… [var1, &var2] (arg1, arg2) {...}.
Тут другой вопрос интереснее — в отличие от того же C# все используемые извне переменные нужно объявлять вручную с помощью use(). Поэтому, если стремиться покрыть и этот функционал, то надо что-то придумывать. Можно такую же абракадабру, как в C++, устроить… [var1, &var2] (arg1, arg2) {...}.
Приятно, что язык развивается. Ридонли свойства, геттеры и сеттеры, пропуск параметров, контроль скалярных аргументов — это всё очень вкусно. Интересно, что будет дальше. Именованные параметры в функциях?
В чем ключевое различие между использованием:
— preg_replace для замены строки и preg_replace /e для выполнения кода;
— preg_replace для замены строки и preg_replace_callback для выполнения кода?
— preg_replace для замены строки и preg_replace /e для выполнения кода;
— preg_replace для замены строки и preg_replace_callback для выполнения кода?
Геттеры и Сеттеры порадовали
А меня бы очень порадовала такая конструкция:
function some($param1, $param2, $param3)
{
echo $param1.' '.$param2.' '.$param3;
}
$params = array(1,2,3);
some(*$params); // 1 2 3
// Сейчас вместо этого приходится писать call_user_func_array, а в случае с конструктором вообще использовать Reflection
Печально.
Продолжаем дальше плодить глобальные функции :(
Я надеялся на функции привязанные к пространству имен, хотя бы.
Хотя getters и setters — это очень хорошо.
Продолжаем дальше плодить глобальные функции :(
Я надеялся на функции привязанные к пространству имен, хотя бы.
Хотя getters и setters — это очень хорошо.
Никите Попову 17 лет (!) и он рулит развитием PHP. Парень явно далеко пойдет. Честь и хвала. Чувствую себя нубом, в хорошем смысле.
P.S. кстати, блоги указанных людей очень рекоммендую:
Nikita Popov
Anthony Ferrara
P.S. кстати, блоги указанных людей очень рекоммендую:
Nikita Popov
Anthony Ferrara
PHP 5.5 больше не поддерживает Windows XP и 2003. Этим системам около десяти лет, поэтому PHP отказалось от них.Я очень глубоко скорблю.
Мне нравиться что язык развивают и мне нравиться нововведения ( привет python! )
Но что мне не нравиться так это какая-то ползучая революция. Имхо надо как-то лучше управлять и новшествами и потерей совместимости. Повторяется история с 5.3, новшества которого просто не имеет смысл иметь в виду, пока он не стал повсеместным. Конечно тихой сапой он пролезает в шаринг хостинги и в пакеты, но пока не стал mainstream и может еще год не станет. Я даже не представляю когда будет актуальны изменения в 5.4, а уж 5.5 вообще боюсь не дождаться :)
Также для меня странно что внутри одной ветки 5.x есть какие-то потери совместимости.
Я думаю надо планировать стабильную и достаточно цельную по фичам версию, зарелизить ее через год и потом активно толкать ее хостерам и маинтейнерам. Иначе php так и будет в версии 5.2, в лучшем случае 5.3, до конца времен.
Но что мне не нравиться так это какая-то ползучая революция. Имхо надо как-то лучше управлять и новшествами и потерей совместимости. Повторяется история с 5.3, новшества которого просто не имеет смысл иметь в виду, пока он не стал повсеместным. Конечно тихой сапой он пролезает в шаринг хостинги и в пакеты, но пока не стал mainstream и может еще год не станет. Я даже не представляю когда будет актуальны изменения в 5.4, а уж 5.5 вообще боюсь не дождаться :)
Также для меня странно что внутри одной ветки 5.x есть какие-то потери совместимости.
Я думаю надо планировать стабильную и достаточно цельную по фичам версию, зарелизить ее через год и потом активно толкать ее хостерам и маинтейнерам. Иначе php так и будет в версии 5.2, в лучшем случае 5.3, до конца времен.
Все вокруг меня используют PHP 5.4.
Ну вы пробовали сделать публичный продукт на php?
Согласен про застой, но он ненадолго, да и касается только домашних страничек (остальные берут выделенный сервер). Symfony2, Doctrine2, другие популярные фреймворки (с неймспейсами) уже требуют 5.3, а с набором их популярности (т.е. уже) и хостеры зашевелятся.
Делаем публичный продукт на 5.4
Везёт вам :(
Господи, у меня вытекли глаза от этого комментария.
Имхо, 5.3 давно уже мэйнстрим, хотя и приходится некоторых хостеров переключать на него с 4.x через тиккеты. 5.4, да, self hosting only практически сейчас. Но в целом динамика апдейтов мэйнстрима радует больше чем при переходе с 3 на 4 и с 4 на 5.
А Chrome и примкнувший к нему Firefox вообще приучили меня не обращать внимания на минорный это релиз или мажорный, номер версии просто идентификатор, собираешься перейти на новый — смотри ченжлогги если не нужны неприятные сюрпризы.
А Chrome и примкнувший к нему Firefox вообще приучили меня не обращать внимания на минорный это релиз или мажорный, номер версии просто идентификатор, собираешься перейти на новый — смотри ченжлогги если не нужны неприятные сюрпризы.
Изменения конечно радуют… но, дайте же наконец типизировать возвращаемые значения методов, ну и перезагрузку методов сразу уж бы…
Как бы Вы применяли перегрузку методов?
Если говорить про плюс, то мне бы арифметику объектов типа Money:
А если о перегрузке метода в зависимости от типа аргумента то тоже неплохо
$total = $price1 + 2*$price2
$total->getValue();
$total->getValueWithTaxes();
А если о перегрузке метода в зависимости от типа аргумента то тоже неплохо
min($price1, $price2)
round($price)
ну например можно было бы избавится от проверки instanceof, когда в качестве аргумента метод принимает объекты разных типов.
А зачем типизировать возвращаемые значения, когда в PHP сплошь и рядом слабая типизация и как такового типа переменной не существует? В связи с этим и перегрузка методов выглядит под сомнением — при каждом вызове делать проверку типов дорого, наверное, будет. Компиляторц проще — он один раз проверил и всё, а унас интерпретатор.
А, РНР 6? Оно же тоже как-то должно выглядеть? Или же после РНР 5.5 появится РНР 7.0?
create_query(«deleted=0», «name», default, default, false); — чем это лучше такого:
create_query(«deleted=0», «name», null, null, false);
непонятно… Просто так добавить в язык еще одно ключевое слово?
create_query(«deleted=0», «name», null, null, false);
непонятно… Просто так добавить в язык еще одно ключевое слово?
yield ???
Даже не знаю как реагировать…
То ли кричать ура, то ли перебираться уже на python, где есть и разыменовывание, и генераторы, и именованные параметры и даже врапперы.
Не движется ли PHP в сторону Python?
Мне PHP очень нравился своей пробитой СИ-шностью!
Даже не знаю как реагировать…
То ли кричать ура, то ли перебираться уже на python, где есть и разыменовывание, и генераторы, и именованные параметры и даже врапперы.
Не движется ли PHP в сторону Python?
Мне PHP очень нравился своей пробитой СИ-шностью!
если честно, я там больше джавости вижу =)
Заимствует лучшее у конкурентов. Это радует. Не радует, что тянет груз BC и никак не рискнёт хотя бы всю стандартную библиотеку объявить depricated и упорядочить её по нэймспэйсам и в параметрах порядок навести. Как раз от 5.5. этого ждал (без всяких оснований), чтобы к 6.0 избавиться от груза PHP3.
Мне совсем не понятно, зачем вводить новое ключевое слово «class» (в примере с
FooBar::class
). Ведь есть же уже константа __CLASS__
, которая делает ровно то же самое, только доступная изнутри класса. Почему бы не сделать её доступной и снаружи: FooBar::__CLASS__
. Хотелось бы, чтобы array_column(s) принимал массив колонок.
array_columns($array, ['one', 'two'])
array_columns($array, ['one', 'two'])
И что тогда будет возвращать функция?
Верно, это должна быть другая функция для немного другой цели. Матрицу, в которой есть только эти столбцы. И ещё аналогичную функцию, возвращающую матрицу без «колонок», переданных в вторым аргументом.
Понятно, да, отдельная функция типа
array_columnS()
для этой цели могла бы быть полезна. Исключаемые столбцы можно было бы передавать в неё же третьим параметром:array_columns($array, ['cols', 'to', 'keep'], ['cols', 'to', 'remove']);
Какой смысл исключать столбцы третьим параметром, если второй параметр и так отрежет всё, кроме перечисленных в нём? :)
Второй параметр можно было бы пропускать, например, передавая в него
null
. Впрочем, для удаления столбцов, пожалуй, действительно целесообразнее отдельная функция типа array_columns_remove()
или array_columns_exclude()
. Либо в функции array_columns()
третий параметр сделать булевым переключателем: если true
, то функциональность инвертируется, и указанные во втором параметре столбцы не сохраняются, а удаляются.Много вещей, которые несомненно радуют.
Но какие-то все-таки эти ребята непоследовательные. C времен php 5.3 жду __getStatic() и __setStatic() вслед за __callStatic() и ничего… тихо.
Но какие-то все-таки эти ребята непоследовательные. C времен php 5.3 жду __getStatic() и __setStatic() вслед за __callStatic() и ничего… тихо.
Последовательность никогда не была сильной стороной PHP. Я так жду уже более десяти лет того, чтобы если где-то допустима сущность какого-то типа, то там было допустимо и любое выражение этого типа. Прежде всего это касается «операторов» (в нынешнем PHP их можно назвать таковыми только в кавычках) [],, -> и (). Чтобы конструкция типа $a[$b]($c)->$d была валидной на этапе «компиляции».
hash_pbkdf2() о боже!
Убивает введение несовместимости с виндой. Оно конечно, если вы пишите «под» конкретного провайдера, сайт тот же, — тогда да. Но если ваш код должен делать какую-то штуку вроде системной архивации, придется использовать пхп 5.0.3, например, и «тянуть его» за скриптами.
Меня вот до сих пор преследуют private function(){} в классах, которые приводят к… дополнительному заработку когда вебмастера сами переносят сайт на новый сервер. Но лучше, бы обойтись без этого.
Меня вот до сих пор преследуют private function(){} в классах, которые приводят к… дополнительному заработку когда вебмастера сами переносят сайт на новый сервер. Но лучше, бы обойтись без этого.
*xp виндой.
Вы видимо не очень внимательно читали.
Прекращается всего лишь прекращается поддержка хп и 2003.
Это не означает что на них все перестанет работать, это будет значить то, что авторы не гарантируют корректной работы.
Прекращается всего лишь прекращается поддержка хп и 2003.
Это не означает что на них все перестанет работать, это будет значить то, что авторы не гарантируют корректной работы.
Меня вот до сих пор преследуют private function(){} в классах
Не буду спрашивать есть ли где-то PHP4, не буду спрашивать есть ли скрипты в продакшене, работающие только под ним. Но, блин, нахрена их переносить с хоста, где они работали чуть ли не 10 лет на хост, где они почти гарантированно работать не будут?!?!?!
Не буду спрашивать есть ли где-то PHP4, не буду спрашивать есть ли скрипты в продакшене, работающие только под ним. Но, блин, нахрена их переносить с хоста, где они работали чуть ли не 10 лет на хост, где они почти гарантированно работать не будут?!?!?!
В пару к
На входе:
На выходе:
Если указан третий параметр, то значениями результирующего массива были бы значения указанного в третьем параметре столбца:
array_column()
была бы полезна функция для преобразования списка массивов в массив, где в качестве ключа использовалось бы значение указанного столбца. Примерно так:function array_column_to_key($input, $keyCol, $valueCol = null) {
$output = array();
if (null === $valueCol) {
foreach ($input as $row) {
$output[$row[$keyCol]] = $row;
}
}
else {
foreach ($input as $row) {
$output[$row[$keyCol]] = $row[$valueCol];
}
}
return $output;
}
На входе:
[
[
'id' => 3,
'name' => 'lorem'
],
[
'id' => 5,
'name' => 'ipsum'
]
]
На выходе:
[
3 => ['name' => 'lorem'],
5 => ['name' => 'ipsum']
]
Если указан третий параметр, то значениями результирующего массива были бы значения указанного в третьем параметре столбца:
[
3 => 'lorem',
5 => 'ipsum'
]
Для второго случая можно будет сделать так:
Вот только будут проблемы, если ключи не обязательные и есть не у всех элементов.
$b = array_combine(array_column($a, 'id'), array_column($a, 'name'));
Вот только будут проблемы, если ключи не обязательные и есть не у всех элементов.
Native-реализация потенциально выгодно отличается от скриптовой более высоким быстродействием. А в случае непредвиденной ситуации следует просто выбрасывать соответствующее исключение (Exception).
Возможность использовать в качестве ключа произвольный столбец теперь, начиная с PHP 5.5.0beta1, включена непосредственно в
Возможности использования целиком «строк» в качестве значений результирующего массива посвящён баг-репорт № 64493.
array_column()
(имя столбца-ключа указывается в третьем необязательном параметре).Возможности использования целиком «строк» в качестве значений результирующего массива посвящён баг-репорт № 64493.
Я, честно говоря, когда начал читать описание новой функции сразу подумал, что она будет делать именно то, что вы описали.
А зачем нужна она в том виде, что есть — мало понятно. Лично мне. Этот вариант, ИМХО, куда более востребованный.
А зачем нужна она в том виде, что есть — мало понятно. Лично мне. Этот вариант, ИМХО, куда более востребованный.
array_column — давно пора.
Как может выглядеть PHP 5.5