Вісім причин використовувати phpdoc

Ні, це не зовсім синтаксис PHP. А точніше, до самого PHP він ніякого відношення не має і сам PHP інтерпретатор його ніколи не парсит. Це PHPDoc-блок, що зародився ще як JavaDoc і перейшов в PHPDocumentor

Поки ми не Кодима так, як запалюють ці чуваки:

але спробуємо розібратися.

Всі ці речі, судячи з назви, як-то пов'язані з документацією. З неї і почнемо.

документація коду

Якщо подивитися в API Reference і в код класу то побачимо одне і те ж:

Вісім причин використовувати phpdoc

Тепер зрозуміло, як цей сайт так швидко змінюється при кожному оновленні початкових кодів. Виявляється, що він складений не вручну, а автоматично згенерований за кодом фреймворка.

Так що можемо вже сформулювати перший бонус, який нам дають PHPDoc-блоки:

Застосування перша: Можливість однією командою в консолі згенерувати документацію з описом всіх класів, полів і методів свого проекту.

Але крім цього ніж він корисний в реальному житті? Розглянемо ще кілька застосувань.

Віртуальні поля

У моделі він стане в нагоді для тієї ж автогенерации по класу цієї моделі, але для чого його використовують в предстваленіях, які в документації не виводяться?

Наприклад, був клас без полів:

і незрозуміло що там, так як Yii2 бере атрибути з таблиці в базі даних. Автопідстановка бачить тільки поля і методи з базового класу ActiveRecord:

Вісім причин використовувати phpdoc

А наші поля підкреслює, при цьому лаючись, що їх в об'єкті немає:

Можна задурити і написати плагін, який би Парс поля з бази для кожної моделі. Але це явно не легкий шлях.

Вісім причин використовувати phpdoc

Тепер він в курсі наших справ і більше не лається.

Або якщо в моделі є зв'язки:

У коді ми можемо використовувати їх просто як поля category. user і tags:

Але цих полів в класі немає. Все працює через віртуальні методи і геттери. Тому нам нічого не залишається, як вказати ці псевдополя і їх типи явно:

Так що PHPDoc-блок перед класом може містити повне перерахування того, чого в класі немає.

Застосування друге: Вказівка ​​псевдополей класу.

У прикладах ми розглянули поки тільки поля. До псевдометодам підійдемо пізніше.

Типи існуючих полів

Крім блоку перед класом можна використовувати і інші місця.

Припустимо, що у нас є приватне поле _user у класу PasswordChangeForm:

Вісім причин використовувати phpdoc

А якщо ми підкажемо, що там у нас знаходиться модель класу User:

то все запрацює як нам цього і хотілося.

Тут ми анотації @var передаємо тільки тип. Але взагалі їй можна передавати ім'я змінної, її тип або обидва аргументи відразу.

Застосування третя: Підказка типів для наявних полів в класі.

Тип повертається результату

Аналогічно, якщо ми анотацією @return вкажемо тип повертається методом об'єкта:

то при використанні цього методу наша система розробки зрозуміє, що всередині змінної $ user після виклику даного методу виявиться модель класу User:

і більше не буде лаятися на раніше невідомі їй методи load і save.

А що якщо який-небудь метод повертає нам або User. або null. Тоді можна перерахувати варіанти через вертикальну риску:

І IDE буде враховувати обидва випадки.

Застосування четверта: Підказка типів аргументів і типу що повертається результату (при наявності) у процедур, функцій, методів.

Змінні з нізвідки

Або ще варіант. Є певне уявлення, в яке з контролера передається змінна $ model. До того ж, це уявлення рендерится в об'єкті класу \ yii \ web \ View. який і буде доступний через $ this:

Але IDE не в курсі наших планів, тому відразу підсвічує змінні $ this і $ model що не визначені в цьому файлі. Для виправлення ситуації ми можемо додати скільки завгодно Doc-блоків з анотацією @var прямо всередину коду уявлення:

При цьому для @var можна вказати спочатку тип, потім ім'я змінної:

В результаті автопідстановка, пошук і автозамена полів і методів об'єктів запрацюють для цих змінних автоматично.

Застосування п'ята: Позначення змінних, яким-небудь чином переданих ззовні.

підміна типу

Не завжди ми в контролерах та інших компонентах використовуємо метод findModel. Часто можна безпосередньо в коді виконати який-небудь запит:

В результаті IDE по ланцюжку спадкування підгляне анотації методу ActiveRecord :: find:

і, так як вказана анотація @inheritdoc. піде ще вище в анотації цього ж методу в інтерфейсі:

і склеїть все воєдино.

В результаті IDE по рядку:

зрозуміє, що з методу find повинен повернутися екземпляр класу \ yii \ db \ ActiveQuery і методи where і one будуть викликатися вже у нього:

Для правильної роботи нам потрібно явно вказати тип змінної за допомогою Doc-блоку перед привласненням:

або безпосередньо перед використанням об'єкта:

Це зручно робити в циклах з різних вибірках:

Застосування шоста: Підміна типу вже існуючих змінних.

І повернемося до методів.

підключення домішок

Спочатку ми розглянули віртуальні змінні. Тепер припустимо, що до своєї моделі ми підключаємо будь-яка поведінка на кшталт:

Його досить додати в метод behaviors моделі:

і в уявленнях виводити оригінал або превью:

А ми пам'ятаємо, що IDE лається на все, чого немає в класі. Але за допомогою анотації @mixin. яку підтримує IDE PhpStorm і, можливо, деякі інші, можна «підмішати» клас поведінки:

і все методи getImageFileUrl і інші будуть доступні в автопідстановки вже нашої моделі.

Але є один нюанс. Крім потрібних методів в класі поведінки є і багато непотрібних. Наприклад, допоміжні resolveProfilePath або createThumbs. які ми використовувати не будемо.

У такому випадку замість прімешаванія всього класу поведінки за допомогою @mixin ми можемо просто додати визначення тільки пари потрібних нам віртуальних методів:

Аналогічно можна додавати сигнатури будь-яких своїх методів, які працюють через свій магічний метод __call.

Застосування сьома: Визначення псевдометодов класу.

Програмування з анотаціями

Крім простої роботи з PHPDocumentor деякі системи пішли далі і придумали для своїх цілей власні види анотацій. І якийсь програмний код через рефлексію парсит ці дані. Взяти хоч перший-ліпший приклад з сайту StackOverflow:

Аналогічно можна отримати $ r-> getMethods () і парсити вже їх.

У підсумку цей підхід знайшов нове застосування. Наприклад, в Symfony Framework за допомогою власних анотацій (крім конфігурації в YAML або XML-файлах) можна конфігурувати ті ж сутності прямо в коді:

або ту ж маршрутизацію контролерів:

І фреймворк легко парсит ці дані і кешує в прості PHP-масиви, щоб не парсити їх кожен раз знову і знову.

Також в уроці з тестування ми розглядали анотації на кшталт @group і @dataProvider для тестів в пакеті PHPUnit.

Цей підхід вже мало пов'язаний з оригінальним PHPDoc, так як просто використовує його ідею. Але при цьому один одному ніхто не заважає і можна спокійно використовувати різні ключі разом:

Багатьом такий підхід з конфігурацією анотаціями в Symfony не подобається, так як він порушує принцип єдиної відповідальності, змішуючи програмний код і конфігурацію в одному файлі. Так що використовуйте на свій розсуд.

Восьма причина: Поява програмних систем з підтримкою специфічних анотацій.

Після цього не буде проблем з автопідстановки, помилками, розбіжностями типу, невизначеними змінними, з автоматичним перейменуванням полів або методів будь-якого класу і іншим автоматичним рефакторингом.

Дружите зі своєю IDE і вона полегшить ваше життя.

Ну і, начебто, свято скоро, так що не спалите ялинку: