Мені здається, критика PHP вже перетворилася на самостійний жанр. Лише статті PHP: фрактал поганого дизайну достатньо, щоб задуматися, чи варто взагалі його використовувати хоча б для сторінки замовлення піци. А якщо у вас все ж залишилися сумніви, зайдіть, наприклад, на PHP Sadness.
Чи PHP дійсно настільки поганий? Не стану кривити душею - я знаю занадто багато його недоліків. У моєму особистому списку на першому місці знаходиться неосудна система посилань на змінні, яка:
а) робить клонування об'єктів фактично марним і
б) все одно не дозволяє нормально користуватися функцією call_user_func (_ array) без хаку, який описаний в документації.
< upd > Гаразд описано у коментарі до офіційної документації. Прошу вибачення у всіх, кого ввів в оману. </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), то таке рішення набуває сенсу. Наприклад, використовуючи __ 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-то не оновиш, не те щоб встановити розширення, могли бути причиною раніше, та й то сумнівною.
Чесне слово, іноді шкодуєш про те, що PHP тьюринг-повний.
Ув'язнення
Може виникнути резонне питання - а навіщо взагалі тоді потрібен PHP, якщо як повноцінна мова програмування вона відверто слабка. Можна ж і на C писати. Або на Java. Та на чому завгодно. На мою думку, PHP дозволяє сконцентруватися на функціях власне програми, відокремивши його від гіпертекстового інтерфейсу, який просто і зручно розробляти на PHP. Адже логіку бази даних зручно розробляти з використанням засобів СУБД, а логіку користувацького інтерфейсу - на JS, Android SDK і так далі. Кожен інструмент хороший на своєму місці і поганий на всіх інших.
PHP має багато проблем, які роблять досвід програмування на ньому дуже неприємним. Пересилювання мови - це не те, чим хочеться займатися розробнику, метою якого є кінцевий продукт. Але PHP ховають не перший рік, проте поки він непогано себе почуває. Поліпшується сама мова і для неї з'являються нові, більш осмислені інструменти. Правда чим більше нововведень відбувається на потребу публіки шляхом бездумного копіювання з інших мов, тим більше виникає і сумнівів у користь PHP при наявності цих самих інших мов. Це особливо прикро, враховуючи, що у PHP є великий власний потенціал - на жаль, не реалізований.
