Действительно ли PHP настолько плох? Не стану кривить душой — я знаю слишком много его недостатков. В моем личном списке на первом месте находится невменяемая система ссылок на переменные, которая:
а) делает клонирование объектов фактически бесполезным и
б) все равно не позволяет нормально пользоваться функцией call_user_func(_array) без хака,
<upd> Хак описан в комментарии к официальной документациии. Кроме того, в PHP 5.4 была запрещена передача в функцию ссылок, причём настолько, что приводит внезапно к Parse error'у в PHP 7. Прошу прощения у всех, кого ввёл в заблуждение.</upd>
Второе место занимает совершенно сумасшедшая система ошибок. В PHP существует 2,5 разновидности ошибок и на момент 7 версии аж 2,5 класса базовых исключений, ни один из которых никак не связан с другими кроме реализации интерфейса Throwable… который есть только в PHP 7 и в более ранних версиях его использование само по себе вызывает ошибку. И это не считая функций __halt_compiler и exit.
В общем всё плохо. Но PHP не меньше вредит нецелевое использование языка на всех уровнях разработки — начиная от проектирования систем и заканчивая решением отдельных функциональных задач. И вот о чём я…
Гипертекстовый препроцессор
PHP — это гипертекстовый препроцессор. В большинстве случаев (кроме совсем уж отдельных, смысл существования которых не поддаётся моему пониманию) PHP работает в текстовом окружении, будь то консольный вызов или HTTP-запрос. И отлично в нём себя чувствует, потому что имеет текстовую природу.
Основным типом данных в PHP является строка. На эту мысль, как минимум, может навести наличие единственного конверсионного магического метода __toString при полном отсутствии намёков на __toInt и прочих скалярных преобразователях. Если пристальнее взглянуть на это дело, то более логичными становятся массивы, фактически являющиеся словарями. Ведь если у нас нет целых чисел, то и индексов быть не может. Зато есть строковые ключи, частным случаем которых являются строки, содержащие целые числа (существующие преобразования ключа укрепляют в этой мысли). Сравнение, выдающее неожиданные результаты, тоже опирается на текстовое представление (хотя не стоит лишний раз себя обнадёживать).
Отсутствующий type hinting для скалярных типов и типов элементов массива подразумевает, что функции принимают в качестве аргументов строки, массивы строк и объекты, а возвращают строки. В версии 5.4 аргументами могут быть ещё и функции, а чуть раньше, в 5.3, появились Closure, которые уже не строки, а вызываемые объекты. Таким образом есть строковые данные и инструменты для их обработки — можно сказать, что это PHP в миниатюре. В 7 версии скалярные типы таки появились, но выглядят скорее как отмазка, как и ООП «прям как в Java». Кстати, о нём.
Магические методы __get и __set, присутствующие в PHP вместо нормальных геттеров и сеттеров, на первый взгляд кажутся какой-то глупостью. Но на самом деле они являются очень мощным инструментом, позволяющим работать со свойствами динамически, без знания чёткой структуры объекта на этапе написания его кода. Казалось бы, зачем это нужно? Если рассматривать объекты сами по себе, то это выглядит бессмысленным нагромождением, вынуждающим писать boilerplate. Однако если рассматривать объект как интерфейс для какого-то внешнего инструмента (скажем, расширения или API), то такое решение обретает смысл. Как и __call, который, кстати, очень похож на обработку сообщений объектами Smalltalk (неожиданная аналогия с самым ОО языком — тема для целой отдельной статьи). Например, используя __get, __set и __call, можно написать очень удобный объектный менеджер базы данных, взаимодействие с которой осуществляется посредством вызова хранимых процедур и изменения настроек.
Не менее важной является возможность сохранять состояние объекта между вызовами скрипта с помощью магических методов __sleep, __wakeup и __set_state. Опять же, с точки зрения объекта как вещи в себе это катастрофа, в труху ломающая инкапсуляцию. Однако если объект — это интерфейс для чего-то, работающего вне скрипта, то это не менее логично, чем постоянное соединение с той же базой данных из примера выше. PHP создан, чтобы умирать, а другими словами — предназначен для написания сценариев, а не приложений.
Соколиный удар
Мне нравится и скалярный type hinting, и ограничение видимости членов объекта, и в большинстве случаев бесполезные деструкторы — потому что теоретически это даёт дополнительные возможности. Но их схожесть с конструкциями знакомых нам языков программирования ведёт к выбору привычных подходов к разработке и дальнейшему неминуемому разочарованию в PHP, потому что в PHP они не работают.
PHP намного более силён в тактике, нежели в стратегии. Логика его работы похожа на хорошо известный приём борьбы с превосходящими силами под названием «ударил-убежал» (может быть, именно поэтому он и приходится по вкусу новичкам?). В вопросах функциональности он очень сильно полагается на расширения, которых у него в запасе огромное количество. Настолько, что обычно загружает их все при каждом вызове (хотя есть сомнительный dl). Последнее — спорная идея, но в PHP это как-то работает потому что в основном всё, что он загружает — это интерфейсы, а не сама функциональность. Это, впрочем, не мешает перерасходу ресурсов, частично устранив который исключением deprecated-функциональности PHP 7 значительно выиграл в скорости по сравнению с предыдущими версиями в том числе. Но как бы там ни было — то, что позволено Юпитеру, не позволено быку. А быки, в роли которых в данном случае выступают фрэймворки и CMS, следуют той же логике.
Для всех, кто имел дело с WordPress, очевидно, что эта CMS — не лучший пример. Но тем не менее это одна из самых популярных CMS, на которой работают аж 25% всех сайтов, если верить W3Techs. И вот что происходит на без малого четверти сайтов во всём мире. При каждом HTTP запросе, включая запросы к REST API (а иногда даже запросы к стилям и скриптам), происходит:
1) загрузка немаленького ядра самой CMS, содержащего массу инструментов на всякий случай, написанных на PHP,
2) загрузка всех плагинов, так же написанных на PHP, многие из которых обладают немалой функциональностью и нисколько не заботятся о том, чтобы определить, нужна она или нет в данный момент.
И всё это для того, чтобы отдать HTML-страничку сомнительной художественной ценности. Это напоминает женщину, которая час красится, чтобы сходить за хлебом в соседний магазин. Остаётся только надеяться, что никто не заходит на эти 25% сайтов.
Я не знаю, сколько процентов сайтов во всём мире используют PHP, но совершенно точно подавляющее их большинство так же использует фрэймворки. Вы видели Doctrine? Нет, они на полном серьёзе написали парсер DQL. На PHP. Это уже не говоря про декораторы. Эти же ребята, кстати, написали Twig. И тоже на PHP. Я не спорю, что это отличные продукты, на которые были потрачены силы и время классных специалистов. Я ничего подобного не сделал (что ж, мне есть к чему стремиться). Я только не понимаю, причём здесь PHP. С тем же успехом можно было написать всё это на шелле.
С моими аргументами можно спорить, но есть же Phalcon, который, судя по тестам, разделывает всех под орех. Хотя это и всего лишь шаг в верном, на мой взгляд, направлении, но пример весьма наглядный. Почему не сделать сервер приложений на C и работать с ним из PHP как с той же СУБД, заодно используя FastCGI? Копеечные хостинги, на которых версию PHP-то не обновишь, не то чтобы установить расширение, могли быть причиной раньше. (И то сомнительной, если вы не делаете страничку класса «орлы 10А».) Но сейчас настроенный VDS стоит не сильно дороже.
Честное слово, иногда жалеешь о том, что PHP тьюринг-полный.
Заключение
Может возникнуть резонный вопрос — а зачем вообще тогда нужен PHP, если как полноценный язык программирования он откровенно слаб. Можно ведь и на C писать. Или на Java. Да на чём угодно. На мой взгляд, PHP позволяет сконцентрироваться на функциях собственно приложения, отделив его от гипертекстового интерфейса, который просто и удобно разрабатывать на PHP. Ведь логику базы данных удобно разрабатывать с использованием средств СУБД, а логику пользовательского интерфейса — на JS, TS, Java и так далее. Каждый инструмент хорош на своём месте и плох на всех остальных.
Боюсь только, что PHP не доживёт до подобного использования. У него слишком много проблем, которые делают опыт программирования на нём очень неприятным. Пересилвание языка — это не то, чем хочется заниматься разработчику, целью которого является конечный продукт. В ситуации, когда на вопрос «Почему вы выбрали PHP?» большинство разработчиков в той или иной форме говорят об отсутствии особого выбора, PHP ничего хорошего ждать не приходится. А жаль. Могло бы получиться.
С другой стороны, PHP хоронят не первый год, однако пока он неплохо себя чувствует. Улучшается сам язык и для него появляются новые, более осмысленные инструменты. Правда чем больше нововведений происходит на потребу публики путём бездумного копирования из других языков, тем больше возникает и сомнений в пользе PHP при наличии этих самых других языков. Но может что и получится.
Комментарии (19)
Temirkhan
15.09.2016 14:05+2Главная ошибка, которую допускают люди, анализирующие недостатки PHP, в том, что они описывают всех программистов гиками-перфекционистами, которые мечтают «выпустить хороший продукт».
Это все равно, что считать, что в каждой стране все должны жить так же хорошо, как в тех, что входят в «тройку лидеров».OnYourLips
16.09.2016 08:56+3Главная ошибка — сравнивать только языки, а не экосистемы, включая стандарты, фреймворки, библиотеки, инструменты и т.д.
И тут внезапно оказывается, что PHP — восхитительная и очень качественная штука на фоне аналогов.Temirkhan
16.09.2016 09:00То есть, если сравнивать только языки, PHP — плохо, а если сравнивать его вместе с его экосистемой, то все очень хорошо?
lavkasnov
15.09.2016 14:18+4Статья какая то троличя, большинство описанных проблем вовсе не явлляются проблемами, 7 PHP очень даже хорош. Поставило в тупик замечание проcall_user_func_array — что там такого странного я так и не понял, даже полез в документацию и ничего странного не обнаружил
altgamer
15.09.2016 19:06Простите, с документацией я действительно погорячился — хак описан в комментарии к официальной документации (http://php.net/manual/ru/function.call-user-func-array.php#91503). Статью исправил и дополнил.
Дело в том, что начиная с версии 5.4 передача ссылок в функцию недопустима (http://php.net/manual/ru/language.references.pass.php). Это логично, но, например, конструкция
function (&$a, &$b) { return call_user_func_array('f', func_get_args()); }
перестала работать как ожидается.lavkasnov
15.09.2016 19:41+2Понятно, но причину проблемы вижу в использовании антипатернов языка: передача параметров по ссылке зло в PHP по многим причинам и если есть желание или необходимость, то следует пользоваться объектами. Любой язык позволяет творить всякую хрень и не вина языка в этом
altgamer
15.09.2016 21:50>> передача параметров по ссылке зло в PHP по многим причинам
Собственно моя претензия к языку в данном случае в том и заключается — почему это в нём вообще существует в таком странном виде.lavkasnov
15.09.2016 22:25Ну очевидно ведь — по историчиским причинам и обратной совместимости, ведь никто уже не помнит, что был PHP 3 b yb; и ниже
altgamer
16.09.2016 08:40-1О какой обратной совместимости речь, если вызов
f(&$a)
приводит:
— к непримечательному вызову в 5.2
— к Deprecated в 5.3
— к Fatal error в 5.4
— к Parse error в 7
Но не для call_user_func_array. Вот эта конструкция (её вполне можно встретить — не столь буквально конечно, что, правда, ещё хуже):
function f1($a, &$b) {
$a++;
$b++;
return $a + $b;
}
function f2(&$a, &$b) {
return call_user_func_array('f1', array(&$a, &$b));
}
$a = 1;
$b = 2;
$c = f2($a, $b);
var_dump($a, $b, $c);
без всяких предупреждений выводит:
— 2, 3, 5 в 5.3
— 1, 3, 5 в 5.4
dim_s
15.09.2016 14:54+1Я так понимаю, что на каждый пункт в статье, люди в комментариях должны приводить контр-аргументы?
MetaDone
15.09.2016 15:06+2Как работает http — делаем запрос -> получаем ответ
php заточен под web
как работает php — получили запрос -> отдали ответ -> умерли
стоит вспомнить про php-fpm, который не все время умирает
и такие вещи как https://github.com/reactphp, https://github.com/amphp — если нужно не умиратьaltgamer
15.09.2016 21:33В случае FastCGI не умирает интерпретатор, а интерес (по крайней мере, в данной статье) представляет скрипт, который он обрабатывает.
Можно реализовать и сервер (sockets: http://php.net/manual/ru/book.sockets.php), и многопоточность (pcntl: http://php.net/manual/ru/book.pcntl.php; phthreads: http://php.net/manual/ru/book.pthreads.php; generators: http://php.net/manual/ru/language.generators.overview.php) без всяких дополнительных либ, используя просто имеющиеся стандартные расширения.
В общем, дело не в том, что чего-то нельзя в скрипте написать. Просто правильная задача для PHP мне видится как раз в связывании расширений между собой, а не в реализации всей функциональности в скриптах. Продолжительность работы, естественная для приложений, для скриптов PHP больше напоминает эксперименты — это как-будто неизлечимо больного при смерти всё время держат под капельницей или упорно пытаются научить художника-заику петь.
Если приложение работает как расширение, то ему всё равно, в каком из тысячи возможных режимов работает PHP и обрабатываемый им скрипт, как и скрипт не пытается бороться сам с собой, с интерпретатором и средой.
serginho
15.09.2016 15:48+2В общем всё плохо
стоит ли вообще его использовать хотя бы для странички заказа пиццы.
И всё это для того, чтобы отдать HTML-страничку сомнительной художественной ценности.Перебор желчи
alexhott
15.09.2016 19:42есть у меня личный кабинет энергосбытовой компании на php+ms sql
при 70000 абонентов неплохо справляется со своей функцией
на лету формирует печатные формы счетов в PDF из реальной БД
и раз в месяц рассылает всем юрлицам (10000 договоро) весь пакет документов (счет, счет-фактиура, акт сверки, акт приема-передачи) менее чем за 8 часов. И это на сервере с 4-я ядрами и 16 гигами оперативки.
Так что хоронить рановато еще
Old_Chroft
15.09.2016 22:13+3Статья из разряда: «посоны, я отстрелил себе яйца из кольта 45 калибра. 45 — херня. Баллистическая ракета — лучше». Нытье про то, какой PHP плохой надоело уже. Да, это не самый подходящий инструмент для GUI и драйверов. С таким же успехом можно критиковать Си или Java: какие же они убогие, элементарное «Привет Мир!» в браузер вывести просто так не могут. А PHP может. МОЖЕТ:
Привет Мир!
Ни одной строчки кода.
Не устраивает поведение некоторых стандартных функций? Напиши свои, если ты такой крутой «Сишнег». Весь код ядра PHP открыт. Все спецификации открыты. Пиши расширение — и в путь.
«Глупо ругать молоток, если ударил им себе по пальцу» (с)altgamer
15.09.2016 23:25-1Наличие у файла расширения «php» ещё не делает его PHP-скриптом.
А в остальном — цитата из статьи:
«На мой взгляд, PHP позволяет сконцентрироваться на функциях собственно приложения, отделив его от гипертекстового интерфейса, который просто и удобно разрабатывать на PHP. <...> Каждый инструмент хорош на своём месте и плох на всех остальных.»
Смысл статьи не в критике PHP. Однако PHP развивается во многом благодаря критике — содержательной, разумеется, нытье ничего полезного не несёт, в этом вы совершенно правы.
Lure_of_Chaos
PHP, конечно, не без недостатков, но язык развивается, и 7ая версия совсем не так плоха, насколько была 4ая (или даже 5.0)
Но огорчает другое. Как известно, PHP процесс оживает при каждом запросе и умирает, только затем, чтобы отрендерить страницу или обработать данные (AJAX/REST) — это должно делаться за миллисекунды. Так зачем за эти миллисекунды заставляют поднимать кучу библиотек фреймворков со всей магией (ORM, процессинг аннотаций и т.д.) — на каждый запрос! Если это уместно на «долгоживущих» платформах, то неуместно на платформе PHP (и даже язык тут не имеет значения, а именно платформа)
NorthDakota
>> ORM, процессинг аннотаций и т.д
Если вы научитесь включать кеш приложения то эта проблема отпадет
altgamer
@проблема()