Код
#статьи

Он вам не «пыха»: почему PHP один из лучших языков веб-программирования

Развенчиваем набившие оскомину стереотипы и разбираем основные фичи из последних версий.

Фото: Roland Weihrauch / Getty Images

Судя по едким комментариям на форумах и публикациям в айтишных медиа, за PHP давно закрепилась репутация медленного, устаревшего и местами нелогичного языка программирования. И хотя «исконный» и современный PHP — это практически два разных языка, некоторые критики, упражняясь в злословии, всё ещё воспроизводят стереотипы двадцатилетней давности. В этой статье я хочу порассуждать, почему они возникли и насколько справедливы сегодня.

Денис Тихонов

Ведущий разработчик в SW Development, эксперт Skillbox по бэкэнд-разработке и PHP.

История болезни

Первая версия PHP вышла в далёком 1995 году. Датский программист Расмус Лердорф написал и опубликовал набор CGI-скриптов, которые позволяли отслеживать посещения резюме в Сети. Вряд ли Расмус предполагал, что через 10 лет на них будет работать ¾ веба.

Скрипты получили название Tools for Personal Home Page. Позже оно сократилось до привычного PHP.

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

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

Технологическое отставание от конкурентов

PHP появился во времена, когда бал правили C/С++ и Java. В сравнении с ними молодому языку сильно не хватало скорости и функциональности. Кроме того, core-команда недостаточно оперативно реагировала на свежие тенденции, из-за чего PHP долго оставался в роли догоняющего.

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

Недостаток стандартов и поддержки

В 1990–2000-х годах у PHP были серьёзные проблемы со стандартизацией. Новые версии отличались от предыдущих так сильно, что приходилось чуть ли не учить язык заново.

Ближе к выходу пятой версии сформировалось сообщество, которое принимает все нововведения путём голосования. Помимо поддержания обратной совместимости, оно разрабатывает рекомендации по стилю, требования к безопасности, интерфейсам и другим аспектам. В общем, с тех пор язык стал более стабильным и предсказуемым.

Нестрогая типизация

В течение жизненного цикла программы на PHP переменная может хранить объекты любого типа. Из-за этого бывает трудно отлавливать ошибки в коде. Сегодня многие разработчики сходятся во мнении, что типы переменных должны указываться явно и только один раз — во время объявления. Поэтому большой популярностью пользуются языки со строгой типизацией, такие как TypeScript. Кто знает, может, недалёк тот день, когда мы увидим TypePHP :)

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

Низкий порог вхождения

Что? Да! Это тот случай, когда достоинство технологии является её недостатком. С одной стороны, PHP многим открыл дверь в веб-разработку, позволив создавать сайты без глубоких знаний в computer science. С другой — из-за этого у нас есть миллионы строк неоптимизированного кода, который приходится поддерживать. Не исключено, что негативные отзывы о языке от некоторых разработчиков — это результат работы с плохим легаси.

Начиная с «семёрки» развивается система стандартов и спецификаций PSR. Если им следовать, то код будет более строгим, а значит, и поддерживать его будет проще.

Какие фичи появились в последних версиях PHP

Сегодня PHP — это не та забагованная и медленная «пыха», которой её знали в начале 2000-х. Скрипты, написанные на седьмой версии, работают в два раза быстрее скриптов на PHP 5. В новых версиях появляются механизмы для повышения отказоустойчивости, быстродействия и читаемости кода. Расскажу о самых важных.

Стрелочные функции

Это сокращённый способ объявления функций, который появился в версии 7.4.

Стрелочные функции дают следующие преимущества:

  • производительность программ повышается, потому что стрелочные функции не создают дополнительных объектов и выполняют меньше операций;
  • объём кода уменьшается за счёт более лаконичного объявления и определения функций;
  • повышается читаемость кода (субъективно).

Пример кода:

// Стандартное объявление функции
<?php
function square_root($number)
{
    $result = $number ** (1 / 2);
}
echo square_root(25); // 5


// Использование стрелочной функции
<?php
$square_root = fn ($number) => $number ** (1 / 2);
echo $square_root(25);  // 5

Типизированные свойства, параметры методов и типы возвращаемых значений

Всё это появилось ещё в седьмой версии. Когда мы явно указываем тип свойств и параметров, читаемость кода повышается, а вероятность ошибки снижается. Разработчику не нужно гадать, какого типа объект хранит то или иное свойство и с какими объектами работает метод.

Например, если напротив свойства написано int, значит, оно будет хранить только целые числа, если string — строки:

class Foo
{
    protected static string $static = 'default';
    public int $a;
    public string $b;
    private Foo $foo;

    function sum(int $x, int $y): int
    {
        return $x + $y;
    }
}

Именованные аргументы

В последних версиях PHP не нужно запоминать порядок следования аргументов в функциях. Вместо этого можно явно указывать их названия, что исключает возникновение досадных ошибок:

<?php
       function foo(
                 $arg1 = '1_default_value', 
                 $arg2 = '2_default', 
                 $arg3 = '3_default') 
    {
        echo "Argument 1: {$arg1}\n";
        echo "Argument 2: {$arg2}\n";
        echo "Argument 3: {$arg3}\n";
    }

    // Вызов функции с позиционными аргументами
    foo('first', 'second', 'third'); 
// Результат:
// Аргумент 1: first
// Аргумент 2: second
// Аргумент 3: third

    // Вызов функции с использованием именованных аргументов
    foo(arg1: 'by_name', arg3: 'also_by_name');
//Результат:
//Аргумент 1: first
//Аргумент 2: 2_default
//Аргумент 3: third
?>

Оператор нулевого слияния

Ещё одно нововведение версии 7.0. Оператор нулевого слияния возвращает значение по умолчанию, если переменная, которую пытаются прочитать, не определена:

// До PHP 7.0
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// PHP 7.0
$username = $_GET['user'] ?? 'nobody';

Оператор null-safe

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

Предположим, мы хотим узнать имя автора книги (объект типа Book). Если в поле name есть строковый объект, то мы сохраним его в переменную и сможем обработать. Если же по какой-то причине имя не задано, то в переменную запишется null. Когда мы попытаемся сделать что-то с null, программа выбросит исключение.

Очевидным решением было бы сделать проверку через оператор if:

if ($book->name) {
    // Выполняем код, если у пользователя есть свойство name 
	$author_name = $book->name->getSurname();
}

Однако null-safe предлагает более элегантное решение:

// После
$book->name?->getSurname();

JIT-компиляция

Также в восьмой версии появилась just-in-time-компиляция, которая повышает скорость работы скриптов. Идея JIT-компиляции состоит в том, что машина собирает код на лету, причём транслирует только те фрагменты, которые изменились с прошлого запуска.

Неименованные исключения

Начиная с восьмой версии можно вынести обработку исключений в один блок catch.

Раньше, чтобы перехватить исключение, нужно было сохранить его в переменной, независимо от того, использовали ли вы эту переменную или нет:

try {
    // Ошибка 
} catch (FooException $exception) {
    Log::error("Something went wrong");
// Переменная не используется, но объявляется
}

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

try {
    // Ошибка
} catch (FooException) {
    Log::error("Something went wrong");
}

PHP vs конкуренты

Основные конкуренты PHP в веб-разработке — Python, Ruby, Java и .NET. У каждого есть свои преимущества и недостатки.

Python. У Python простой синтаксис, огромная стандартная библиотека и хороший интероп с языком C. А ещё он идеально подходит для работы с big data. Но, как я уже говорил выше, PHP поддерживают практически все серверы и он выигрывает в скорости простых вычислений.

В подтверждение приведу результаты тестов алгоритма «Решето Аткина», который используется для поиска простых чисел:

ЯзыкВремя, сПамять, МБ
PHP2,196 ± 0,023344,15 ± 0,24
Python (CPython)6,411 ± 0,043245,74 ± 0,11
C++ (GCC)0,213 ± 0,01088,98 ± 0,07
Java0,442 ± 0,061189,23 ± 2,52
JavaScript (Node.js)0,376 ± 0,026210,13 ± 0,44
Ruby2,815 ± 0,040160,56 ± 0,09

Как видно из таблицы, Java оказался намного быстрее и экономичнее, чем PHP. Чемпион по скорости и количеству потребляемой памяти — C++.

Java. На Java пишут высокопроизводительные и надёжные приложения. Однако разработка на ней — дело сложное и дороге. Да и джавистов сегодня найти непросто, потому что банки буквально пылесосят рынок. В последнее время PHP много чего заимствует у Java. Скоро, например, обещают завезти дженерики.

Что такое дженерики

Дженерики — это коллекции, которые могут содержать объекты только одного типа. Они более безопасны, чем стандартные массивы PHP, хранящие вместе и числа, и строки, и булевы значения и много что ещё.

Допустим, есть массив пользователей (объекты типа User) и у каждого пользователя есть «имя» (свойство name). Нам нужно перебрать пользователей и получить инициалы их имён с помощью функции get_initials. Без дженерика пришлось бы проверять тип каждого объекта на тот случай, если в массиве случайно окажется объект другого типа. Если попытаться взять инициалы от объекта undefined, то программа «упадёт».

С дженериками такая возможность исключается. Ещё на этапе сборки мы получим ошибку property of undefined, которая явно укажет на то, что в функцию был передан некорректный аргумент. Поэтому код с ошибкой не доберётся до продакшена.

Ruby. Как и Python, Ruby обладает простым и понятным синтаксисом, но тесты показывают, что в некоторых задачах он уступает PHP по производительности.

Итог: какой он, современный PHP

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

Доступность

Освоить язык можно довольно быстро, при этом не обладая глубокими техническими знаниями. В интернете есть куча руководств, бесплатных книг и курсов как по PHP, так и по WordPress и Bitrix, которые на нём написаны. При правильном обучении уже через неделю вы напишете простой блог или сайт, а через месяц — интернет-магазин.

Большой набор фреймворков и CMS

Как уже было сказано, на PHP написаны WordPress и Bitrix, a также Joomla, Drupal и ещё множество CMS на любой вкус. У каждой из них есть большая библиотека шаблонов и плагинов.

Для более сложных проектов есть проверенные PHP-фреймворки: современный Laravel, консервативный, но надёжный Symfony, и Yii 2. Хотя последний постепенно уходит со сцены.

Поддержка большинства хостинг-провайдеров

Ваш проект будет работать практически на любом хостинге, без костылей и танцев с бубном. Достаточно лишь положить index.php в корневую папку.

Распространённость

Распространённость характеризует количество пользователей технологии. Согласно статистике W3Techs, бэкенд 76,8% всех сайтов написан на PHP — и это доказывает, что он всё ещё популярен.

На рынке много PHP-программистов, поэтому малому и среднему бизнесу проще их найти. Разработка на «пыхе», в сравнении с тем же Java, идёт гораздо быстрее. И вообще, если вы пишете продающий сайт или, скажем, CRM, а не банковское приложение, то вам не нужен Java. Ведь делать такое на Java — это всё равно что кататься на «ламборджини» в деревне: слишком дорого и скоростью особо не похвастаешь.

«Инерция»

Как бы язык ни ругали, все знают про WordPress и Bitrix, на которых написаны сотни тысяч магазинов и блогов. Нужно ли экспериментировать и пробовать что-то новое, если бюджет и время ограничены?

Есть и большие сервисы, такие как VK, которым тяжело и дорого переезжать на что-то модное вроде Golang. Чтобы сохранить кодовую базу, движок «Фейсбука»*, например, в 2014 году переписали на Hack — PHP-подобный язык программирования со статической типизацией.

* * *

Благодаря простоте и доступности PHP остаётся незаменимым инструментом для веб-разработчиков. Он широко используется для создания блогов, сайтов, форумов и других веб-приложений.

Для разработки высоконагруженных систем PHP может оказаться не самым оптимальным выбором. Но стоит отметить, что современные стандарты построения архитектуры веб-систем дают возможность использовать старый добрый PHP в связке с микросервисной архитектурой, написанной на тех же Golang или Node.js. Это с лихвой компенсирует недостатки языка, но при этом позволяет использовать его преимущества. Вот такая получается синергия в программировании.


* Решением суда запрещена «деятельность компании Meta Platforms Inc. по реализации продуктов — социальных сетей Facebook и Instagram на территории Российской Федерации по основаниям осуществления экстремистской деятельности».

Проверьте свой английский. Бесплатно ➞
Нескучные задания: small talk, поиск выдуманных слов — и не только. Подробный фидбэк от преподавателя + персональный план по повышению уровня.
Пройти тест
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована