psalm php что это
Статический анализ в PHP
Все мы привыкли к определению, что PHP – это язык со слабой динамической типизацией. В этом одновременно его преимущество и недостаток. Преимущества заключаются в том, что вы имеете больше возможностей по работе с динамическими данными: вызывать функции или объекты из строки, передавать и возвращать mixed типы и многое другое. В конце концов, только в PHP вы можете одновременно увидеть ужасные реализации паттерна ActiceRecord с динамическими свойствами (которые физически не определены в классе) и элегантные контейнеры внедрения зависимостей, которые дают значительно больше возможностей, чем аналогичные контейнеры в языках с сильной статической типизацией. Если говорить о недостатках, то это, разумеется, баги, связанные как раз с тем, что мы точно не знаем, что нам может вернуть, например, та же анонимная функция, каких типов параметры она принимает, какие ключи есть в массиве и так далее. По этой причине вам приходится обогащать свой код проверками в духе isset($data[‘key’]) и тому подобное.
Преимущество компилируемых языков состоит в том, что еще на этапе компиляции происходит верификация всех типов вашей кодовой базы, что в большинстве случаев избавляет вас от неприятных багов в рантайме. В php в силу его природы такое невозможно. или все-таки возможно? На самом деле возможно, и реализуется это благодаря статическому анализу. В данном случае слово «статический» означает, что код анализируется еще до запуска: например, в CI (Continuous Integration). На данный момент существуют два самых популярных инструмента статического анализа: psalm и phpstan. В этой статье мы рассмотрим psalm, инструмент, которым я пользуюсь во всех своих проектах.
Так что же позволяет делать psalm, что поможет нам избавиться от багов в рантайме? Чтобы в этом разобраться, ниже я приведу многочисленные снипеты кода с правильным определением типов, а также прикреплю ссылку на онлайн-редактор psalm, где вы сможете убедиться в том, что этот инструмент действительно помогает находить ошибки.
Замыкания
Замыкания, или анонимные функции, или, как их еще часто называют, лямбды, – это функции без имени, которые удобны тем, что могут быть переданы в другие функции в качестве аргумента. Такие функции называются функциями высшего порядка. Например, представим, что у нас есть анонимная функция, которая принимает два числа и возвращает булево значение.
Как мы могли бы описать такое, например, в Kotlin:
Удобно, согласитесь? Это не только безопасный код, но и самодокументируемый, так как нам не приходится гадать, каких типов аргументы мы должны передать и что оттуда вернется. Можно ли такое повторить в php? Можно, повторяем:
Многие могут возразить, что это же всего лишь комментарии, а не код. Но пока для человека это комментарии, для псалма – это метаинформация, которая помогает ему следить за тем, чтобы в эту функцию не передали анонимную функцию с другими аргументами. Можете убедиться в этом сами, открыв редактор псалма. Сейчас вы увидете там ошибку, потому что я намеренно первым аргументом функции сделал string. Замените его на int, чтобы убедиться, что все работает правильно.
Если вы хотите вернуть nullable булев тип, вам необходимо добавить знак вопроса перед типом. Точно так же, как мы это делаем на уровне самого языка:
После этого мы вольны вернуть null из функции, как это показано в примере. Тут я использовал аннотацию @psalm-param, а не просто @param, потому что phpdoc не поддерживает некоторые особенности синтаксиса псалма. Однако я советую всегда, даже для простых типов, использовать @psalm-param, это позволит в будущем подключить другой статический анализатор, например, phpstan, где есть такая же аннотация @phpstan-param. Так вы сможете избежать конфликта анализаторов, если вдруг phpstan не поймет синтаксис псалма, указанный в аннотациях @param, @return, и наоборот. Поехали дальше.
Что если сама анонимная функция должна быть nullable?
В данном случае мы окружили скобками наш callable, чтобы null стал частью типа именно нашей переменной $max, а не частью возвращаемого типа анонимной функции.
Массивы
Массивы – один из самых мощных инструментов языка. Это одновременно и списки, и кортежи, и ассоциативные массивы. В то же время в php нет встроенных инструментов для описания типов массива. Но не с псалмом. Псалм позволяет вам описать ассоциативный массив любой вложенности и любых типов, а также проконтролирует, что вы правильно используете элементы массива. Давайте проверим:
Более того, в phpstorm не так давно была завезена поддержка автокомплита таких массивов, как показано на картинке. Еще одно преимущество описания типов в копилку. К сожалению, это пока не работает с вложенными типами.
Теперь зайдите в редактор псалма и убедитесь, что он действительно валидирует массив на соответствие типов и вхождений всех ключей. Поправьте ключи так, чтобы не было ошибок.
Если вы хотите передать список чисел, то можете это описать следующим образом:
Psalm это в том числе провалидирует правильно.
Вы также можете использовать кортежи – упорядоченные последовательности элементов.
Теперь вы можете безопасно обращаться к индексу 0 или 1 и осуществлять соответствующие типу операции. Обратите внимание на этот пример в редакторе псалма. Он не только валидирует операции, допустимые над типом, но и то, что вы не вышли за длину массива, так как элементов всего 2.
Если вы хотите описать статичный массив, где все ключи одного типа, а значения – другого, вы можете использовать следующий синтаксис:
Но поскольку в этом случае вы не можете быть уверены, что в массиве есть ключ с индексом 0, вам придется проверять его наличие. Но даже в этом случае псалм проверяет, что над строкой производятся допустимые операции.
Кстати, для описания std объекта вы можете использовать аналогичный синтаксис, как для описания ассоциативного массива:
Разумеется, psalm провалидирует и такие случаи.
Примитивные типы
Для примитивных типов psalm также предоставляет дополнительные возможности.
Например, вы можете описать, что ждете только не пустую строку:
Или только позитивное число:
Или только конкретные числа (аналогично работает и со строками):
Если у вас есть список констант с одинаковым префиксом, вы можете использовать следующий синтаксис, чтобы ограничить диапазон допустимых значений строк:
Если в качестве аргумента функция ждет название конкретного класса, это можно описать следующим образом:
Также допускается указать просто class-string, если вам не важен тип класса, а только то, что это fqcn от класса:
Дженерики
Дженерик-тип – это инструмент обобщенного программирования, который позволяет работать с различными типами.
Возьмем популярный пример – Stack – и на его примере посмотрим, как это работает:
Сначала мы вводим некоторый тип T, который нам пока неизвестен. Используем этот T как тип данных наших элементов в методах add() и last(). В момент создания объекта мы должны указать конкретный тип нашего T с помощью такого синтаксиса:
Похожий синтаксис есть практически во всех языках с нативной поддержкой дженериков, с той лишь разницей, что там это вынесено на уровень синтаксиса.
Таким образом, наш стек может хранить как строки, так и числа, объекты и массивы. А чтобы убедиться, что это работает, загляните в редактор псалма.
Другой пример использования дженерика:
В данном случае у нас есть некоторый контейнер, который умеет по полному имени класса (который пока что обозначим как T) вернуть объект. Таким образом мы можем получить любой T, который контейнер по его имени найдет у себя в зависимостях. Чтобы оценить всю мощь дженериков, попрактикуйтесь на простых задачах, а также почитайте документацию псалма.
Также в этом коде есть одна важная особенность: нам не нужно указывать в аннотации к нашему $result тип дженерика, так как этот тип берется из аргумента метода get.
Другие возможности Psalm
Кроме того, что psalm может определять, что переменная не используется, что вы сделали бессмысленное условие (например, проверяете на null не null тип), что вы ошиблись в синтаксисе, у него есть и другие киллер-фичи, благодаря которым он отличается от других статических анализаторов.
Условные типы
Иногда ваш код может вернуть два абсолютно разных типа в зависимости от входящего типа аргумента. Было бы хорошо такое описать, правда? И psalm это умеет!
В данном случае если передать null в функцию, мы получим false и не можем обращаться к ответу как к массиву, и psalm закономерно будет ругаться.
Ассерты
Часто бывает такое, что у вас есть поле, которое может быть null, и метод, который проверяет, что то, что установлено в этом поле, не равно null. Если результат поля вы захотите передать в функцию/метод, которые null не принимают, вам необходимо убедиться в том, что null там нет. С помощью синтаксиса ассертов вы можете указать псалму, что вы уже проверили тип данного поля. Сделать это можно следующим образом:
Про остальные возможности советую прочитать в документации. Их там много.
А как этим пользоваться?
Для того, чтобы начать пользоваться psalm’ом, прочитайте секцию Get Started в их документации.
Надеюсь, данная статья убедила вас хотя бы попробовать этот инструмент. Поверьте, со статическом анализом вы избавитесь от глупых ошибок обращения к null как к объекту, передачи неверного типа, обращения к несуществующему ключу массива и многое другое.
Psalm php что это
В этом разделе помещены уроки по PHP скриптам, которые Вы сможете использовать на своих ресурсах.
Фильтрация данных с помощью zend-filter
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Контекстное экранирование с помощью zend-escaper
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Подключение Zend модулей к Expressive
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Совет: отправка информации в Google Analytics через API
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Совет: активация отображения всех ошибок в PHP
При поднятии PHP проекта на новом рабочем окружении могут возникнуть ошибки отображение которых изначально скрыто базовыми настройками. Это можно исправить, прописав несколько команд.
Агент
PHP парсер юзер агента с поддержкой Laravel, работающий на базе библиотеки Mobile Detect.
PhpStorm 2020.3: PHP 8, атрибуты, PHPStan и Psalm, Xdebug 3, Tailwind CSS и совместная разработка
PHP 8
PHP 8.0 выпущен. Большое спасибо всем контрибьюторам и менеджерам релиза!
PhpStorm 2020.3 поддерживает все последние изменения языка. Давайте рассмотрим, что доступно и как это использовать в IDE.
Версия языка в статусбаре
Теперь в статусной строке всегда отображается текущая версия PHP проекта. Оттуда же можно переключить версию.
Если переключатель не активен, это означает, что ограничение на версию PHP задано в composer.json.
Именованные аргументы
В PHP 8 аргументы функций и методов могут передаваться путем указания имени параметра. Вызовы теперь автоматически задокументированы, а необязательные параметры стали необязательными в полном смысле слова.
С помощью квик-фикса Add name identifiers можно добавить имена к аргументам:
Опечатки или ошибочные имена аргументов подсвечиваются:
Если передаваемое значение совпадает со значением параметра по умолчанию, то его можно смело удалить:
Вместо массива options для передачи набора параметров можно использовать именованные аргументы, просто передавая только необходимые. Аргументы, передаваемые таким образом, в отличие от элементов массива, являются типобезопасными.
Атрибуты
Атрибуты — это новый, структурированный способ указания метаданных в PHP вместо комментариев PHPDoc.
А вот PhpStorm провалидирует все в редакторе, не запуская Reflection API. При этом проверяются следующие правила:
Вот атрибуты в действии с Symfony:
Штормовские атрибуты PHP 8
Их сразу же можно использовать в своей кодовой базе, ничего не подключая.
#[Deprecated]
Используйте этот атрибут как PHPDoc-тег @deprecated, чтобы пометить методы, классы или константы классов, которые будут удалены в будущем.
Преимущество тут в том, что можно указать замену для устаревшего кода и пользователю будет проще обновиться.
#[ArrayShape]
Этот атрибут полезен для работы с простыми структурами данных или объектоподобными массивами, когда по какой-то причине нельзя объявить класс.
Синтаксис вот такой:
Массив, который определяет «форму», можно вынести в константу и переиспользовать:
К счастью, синтаксис однострочных атрибутов обратно совместим. То есть, если записать #[ArrayShape] в одну строку в проекте на PHP 7, то интерпретатор PHP воспримет эту строку как комментарий.
#[Immutable]
Неизменяемые объекты не могут быть изменены после инициализации или создания. Их использование делает состояние программы более предсказуемым и облегчает отладку.
Атрибутом #[Immutable] можно пометить весь класс или конкретные свойства, чтобы показать, что они не могут быть изменены.
PhpStorm будет проверять использование таких объектов и свойств и подсвечивать попытки изменения.
Этим атрибутом помечаются чистые функции, то есть те, которые не производят никаких побочных эффектов. Такие функции можно безопасно удалить, если результат их выполнения впоследствии не используется.
Если функция помечена как чистая, но в ее теле есть попытка изменить что-то за пределами из внешнего скоупа, то PhpStorm подсветит небезопасный код.
Все стандартные чистые функции PHP уже помечены этим атрибутом в PhpStorm.
#[ExpectedValues]
С помощью этого атрибута можно указать, какие значения функция принимает в качестве параметров, а какие может возвращать.
Например, рассмотрим функцию count:
Вот как атрибут #[ExpectedValues] улучшит ситуацию:
То есть появилось автодополнение, а если передано что-то другое, то подсвечивается ошибка.
Еще один пример #[ExpectedValues]
Возьмем хелпер response() из Laravel. В качестве второго параметра он принимает статус код HTTP.
Давайте исправим это, добавив атрибут #[ExpectedValues(valuesFromClass: Response::class)]
#[NoReturn]
#[Language]
Этот атрибут можно добавить к строковым параметрам, в которых ожидается текст на каком-либо языке, например RegExp, SQL, DQL и так далее.
Для аргументов появится подсветка и дополнительные возможности.
Вернемся к новым возможностям PHP 8.
Объявление свойств в конструкторе
Обычные свойства можно преобразовать в promoted или обратно с помощью квик-фикса Convert to promoted property.
Если свойство объявлено новым способом, но в теле конструктора осталась инициализация, то PhpStorm предложит ее удалить.
Выражение match
Может быть трудно увидеть неправильное использование нового выражения, поэтому PhpStorm подсветит все ошибки.
Будут обнаружены дублирующиеся значения в условиях:
Выражение match с одной веткой и веткой по умолчанию может быть безопасно заменено на тернарное выражение.
А если осталась только ветка по умолчанию, то соответствие match вообще не понадобится.
Наконец, если в разных ветвях одинаковые тела, они могут быть объединены.
Оператор nullsafe
PhpStorm проверит правильность использования оператора:
Висячая запятая
Non-capturing catches
В PHP 8 можно ловить исключение в catch-блоке без переменной.
Выражение throw
Можно использовать сокращение thr и нажать tab — это live template.
Константа ::class на объектах
Собственно, по нажатию Alt+Enter такую замену и можно сделать. Неправильное использование константы ::class PhpStorm подсветит.
Новые функции для строк: str_contains(), str_starts_with(), str_ends_with()
Есть также новые str_starts_with() и str_ends_with() для определения того, начинается или заканчивается ли строка определенной подстрокой. PhpStorm подсвечивает, где вызовы substr() можно заменить новыми альтернативами:
Reclassified engine warnings
В PHP 8 для многих ошибок был пересмотрен тип бросаемого предупреждения. А именно, вместо Notice во многих случаях будет Exception или Type Error.
В PhpStorm в связи с этим некоторые инспекции имеют два разных уровня severity: для PHP 8 и для более старых версий.
Это все из наиболее заметного по PHP 8. Есть еще целая куча изменений помельче, которые будут видны при обновлении на PHP 8.
Поддержка Psalm и PHPStan
Оба статических анализатора можно использовать в PhpStorm 2020.3 для подсветки проблем непосредственно в редакторе.
Оттуда можно перейти к настройкам инспекции и включить подсветку в редакторе. Это делается выбором соответствующей инспекции в списке PHP | Quality tools в Settings/Preferences | Editor | Inspections.
Лучше включить только один из инструментов, а не оба одновременно.
Тут же можно указать путь к конфигурационному файлу и настроить аргументы командной строки.
Когда все настроено, откройте любой файл, и вы увидите подсветку от статических анализаторов. Может быть небольшая задержка перед тем, как появится подсветка.
Аннотации
Поддержка типов
Добавили поддержку некоторых типов Psalm и на основе информации из тегов улучшили наш вывод типов. Это сделало более точными проверки, генерацию кода и автодополнение.
Псевдотипы
Поддерживаются псалмовские псевдотипы, такие как scalar, numeric и т. п.
Константы в типах
Поддерживаются объединения констант и указание через * в тегах param и var.
Тайпхинты для массивов
Описания массивов array тоже поддерживаются, в том числе вложенные.
Дженерики и @tempate
Поддержка дженериков — фича для продвинутых пользователей, у которой нет полной корректной спецификации и много граничных случаев. Тем не менее мы решили реализовать базовую поддержку для @template на основе синтаксиса Псалма, чтобы посмотреть, как это будет использоваться.
Пока поддерживается только самый примитивный случай, когда функция возвращает один из своих параметров.
Эта поддержка дженериков является очень базовой, ее можно считать экспериментальной. Хотим понять, как это будет использоваться и что нужно реализовать в первую очередь. Будем рады обратной связи, особенно в виде реальных примеров использования в наш трекер.
Xdebug 3
Обновился популярный отладчик для PHP, теперь он значительно быстрее в работе и проще в настройке. Более подробно об Xdebug 3 читайте в документе Upgrade guide.
Чтобы сконфигурировать Xdebug 3, теперь достаточно одной опции xdebug.mode (например так XDEBUG_MODE=debug ).
Улучшения отладчика
Возможности по отладке в PhpStorm расширились двумя новыми фишками.
Интерактивные хинты
Теперь в отладочном режиме вывод переменных можно развернуть, чтобы увидеть все поля. Тут же можно и изменить значения.
Inline Watches
В предыдущих версиях можно было добавить переменную или выражение в список watch и наблюдать, как меняется значение по шагам.
В PhpStorm 2020.3 можно добавлять вотчи непосредственно в контексте, и они будут отображаться рядом с кодом.
Нажмите Add as Inline Watch в попапе на хинте.
Или нажмите Add Inline Watch в контекстном меню редактора.
Или выделите переменную и в контекстном меню выберите Add Inline Watch.
Подсветка и переименование переменных в Twig
Выберите переменную или поместите на нее курсор, и все ее использования в шаблоне будут подсвечены. А чтобы переименовать все вхождения, нажмите Shift + F6.
Совместная разработка – Code With Me
В PhpStorm 2020.3 встроен плагин Code With Me — новый инструмент JetBrains для совместной разработки и парного программирования. С помощью него можно расшарить открытый проект с другими пользователями и работать над ним вместе в режиме реального времени. Подробнее про Code With Me в этих постах.
HTTP-клиент
Интеграция Guzzle с HTTP-клиентом в PhpStorm
Guzzle — один самых популярных HTTP клиентов для PHP. Представьте, что где-то в коде есть HTTP-запрос и хочется его потестировать, не запуская сам код. Раньше пришлось бы копировать все параметры вручную.
Теперь из редактора запрос можно запустить и поиграться с ним, а затем сохранить его как http-файл в проекте.
Копировать HTTP-запрос в cURL
Чтобы экспортировать HTTP-запрос в cURL-строку, нажмите Alt+Enter на запросе в редакторе и выберите Convert to cURL and copy to clipboard. Теперь его можно вставить в терминал, документацию или любой инструмент тестирования API.
Редактор
Улучшения для Markdown
Для описания диаграмм и графиков можно использовать синтаксис Mermaid.js в markdown-файлах. PhpStorm теперь умеет рендерить превью для них прямо в редакторе. Включается в Preferences/Settings | Languages & Frameworks | Markdown.
Настраивается в Preferences/Settings | Editor | Code Style | Markdown.
И наконец, если нажать кнопку Auto-Scroll Preview в правом верхнем углу редактора, то прокрутка превью и текста будет синхронизирована.
Улучшена проверка орфографии и грамматики
Сплит редактора перетаскиванием
Чтобы открыть несколько файлов бок о бок, просто перетащите вкладку в нужный угол экрана.
Есть еще один способ открыть файл в сплит-режиме — Shift+Enter.
Комбинацию можно нажать на выбранном файле в Project view или в результатах поиска по файлам.
Вкладка предпросмотра
Если нужно быстро просмотреть файлы, то теперь не обязательно открывать каждый в отдельной вкладке. Можно использовать новую вкладку Preview tab.
Чтобы включить ее, нажмите на шестеренку в Project view и выберите Enable Preview Tab и Open Files with Single Click.
Еще можно просматривать файлы нажатием пробела в Project view, не открывая их.
Улучшения для Search Everywhere
Результаты сгруппированы по релевантности:
Можно делать простые математические операции и не открывать гугл калькулятор:
Можно искать по истории Git:
Автоматическое переключение на светлую или темную тему
В Preferences/Settings | Appearance & Behavior | Appearance | Theme выберите Sync with OS.
Новый набор горячих клавиш для macOS
Альтернативная раскладка горячих клавиш для macOS минимизирует использование функциональных клавиш, чтобы не надо было растягивать руку на всю клавиатуру при совершении основных действий. Например, вместо Fn+Shift+F6 для Rename рефакторинга используется ⌥+⌘+R.
Слова вместо иконок для горячих клавиш macOS
Можно сделать так, чтобы вместо иконок типа ⌥ ⌘ отображались слова Alt, Cmd и т. п.
Включается в секции Registry опцией ide.macos.disable.native.shortcut.symbols. Чтобы получить доступ к реестру, используйте Find Action Cmd+Shift+A и напишите там Registry.
Установить PhpStorm как приложение по умолчанию для разных файлов
В Preferences | Settings / Editor / File Types нажать Associate file types with PhpStorm…. В диалоговом окне выберите расширения для файлов, и они будут открываться в PhpStorm.
На macOS требуется перезагрузка.
Шаблоны могут генерировать несколько файлов
Можно одновременно сгенерировать сразу несколько файлов, например скелет для модуля или комбо контроллер-вью.
В Preferences / Settings | Editor | File and Code Templates нажать на , чтобы создать новый шаблон, а затем нажать на иконку Create Child Template File
.
А вот пример того, как сгенерировать контроллер и шаблон в Symfony:
Поддержка Git stage
Включить можно чекбоксом Enable staging area в Preferences/Settings | Version Control | Git.
В окне инструментов Commit (Cmd+0 / Alt+0) появятся две группы файлов: staged и unstaged.
Чтобы добавить файл в staged, нажмите на + напротив него.
Или можно выбрать конкретные строки и добавить их иконкой в редакторе. В этом случае можно закоммитить часть изменений из файла, а над остальными продолжить работу.
Инструменты БД
PhpStorm «из коробки» включает в себя возможности DataGrip, которые охвачены в обзоре релиза DataGrip 2020.3 от наших коллег.
SQL для MongoDB
Теперь можно использовать SQL-запросы к MongoDB. PhpStorm 2020.3 поддерживает SELECT- запросы с JOIN , WHERE , GROUP BY , HAVING , ORDER BY , LIMIT , OFFSET и всеми функциями MongoDB кроме map, reduce, filter и let. Подробнее в блог-посте.
Tailwind CSS
PhpStorm дополняет классы Tailwind в HTML-файлах и после директивы @apply. А также предоставит автодополнение псевдо-классов.
Если навести указатель на класс в HTML и CSS файлах, то отобразится предпросмотр полученного CSS. Предпросмотр также доступен при автодополнении кода, во всплывающем окне документации F1 / Ctrl+Q.
PhpStorm поддерживает настройки из tailwind.config.js. Например, если определить тему с новыми цветами, то во всплывающем окне автодополнения будут созданные классы с именем кастомного цвета.
А вот видеоролик (на английском) с демонстрацией главных фич релиза: