Создаем свой Фреймворк на компонентах symfony2. Часть 2

Перед тем, как мы погрузимся в рефакторинг кода, я бы хотел сделать небольшое отступление, и поговорить о том, зачем вам нужно использовать фреймворк, вместо того, что бы писать ваши приложения на старом добром plain PHP. Почему использовать фреймворк — хорошая идея, даже для небольших кусков кода, и почему создание фреймворка на основе компонентов Symfony2 — лучше, чем создание фреймворка с нуля.

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

Даже учитывая, что приложение написанное нами в прошлой статье было очень простым, оно содержит в себе несколько проблем.

Во-первых, если в запросе будет отсутствовать параметр name, вы получите PHP warning. Давайте исправим это:

Во-вторых, это приложение не безопасно. Можете в это поверить? Даже простейший фрагмент PHP  кода может быть уязвим для одной из самых распространенных проблем с безопасностью в интернете: XSS (Cross-Site Scripting).  Вот более безопасная версия:

Как вы заметили, защита вашего кода с помощью htmlspecialchars — это утомительно, и есть вероятность ошибиться. Отличная причина, что бы использовать шаблонизатор, например Twig, где экранирование включено по умолчанию.

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

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

Если бы наше приложение было немного больше, у нас бы возникли и другие проблемы. Если они вам интересны, можете почитать главу из документации symfony: Symfony2 versus Flat PHP

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

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

ООП с компонентом HttpFoundation

Программирование в web — строится на взаимодействии с HTTP. Поэтому основные принципы нашего фреймворка должны быть вокруг HTTP спецификации.

HTTP спецификация описывает как клиент (например браузер) взаимодействует с сервером (нашим приложением на сервере). Диалог между клиентом и сервером происходит в строго определенных сообщениях запросов и ответов: клиент шлет запрос серверу и, основываясь на этом запросе, сервер возвращает ответ.

В PHP запрос представлен глобальными переменными ($_GET, $_POST, $_FILE, $_COOKIE, $_SESSION…), а ответ генерируется функциями (echo, header, setcookie, …).

Первый шаг на встречу хорошему коду — использование Объектно-Ориентированного подхода. Главный принцип компонента Symfony2 HttpFoundation: замена обычных глобальных переменных и функций в PHP на объектно ориентированные обертки.

Для использования этого компонента, откройте файл composer.json и добавьте туда зависимость для проекта:

Запустите команду update для композера

И наконец, в конце файла autoload.php, добавьте код, необходимый для загрузки компонента:

Теперь давайте перепишем наше приложение, используя классы Request и Response:

Метод createFromGlobals() создает объект Request, в соответствии с данными в глобальных массивах PHP.

Метод send() отправляет объект Response обратно клиенту (Сначала выводятся HTTP заголовки, за ними контент).

Перед тем, как вызвать метод send(), мы должны добавить вызов метода prepare():

что бы убедиться, что наш ответ соответствует HTTP спецификации.

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

Благодаря простому API класса Request, все параметры запроса всегда у вас под рукой:

Вы также можете симулировать запрос:

Используя класс Response, легко задать ответ:

Ну и напоследок, данные классы, как и  любые другие  Классы в Symfony2, были проверенны на безопасность, независимой компанией. Они также являются Open-Source проектом, что означает, что огромное количество разработчиков со всего мира, читали код, и уже исправили потенциальные проблемы в безопасности. Когда вы в последний раз заказывали профессиональный аудит безопасности для своих домашних проектов?

Даже что-то настолько простое, как получение IP клиента, может быть не безопасно:

Это будет отлично работать, пока вы не добавите reverse proxy на production сервер. Теперь вам нужно изменить код так, что бы он работал и на вашей девелоперской машине (где у вас нет прокси) и на сервере:

Использование Request::getClientIp() обеспечит вам правильное поведение кода с первого дня разработки. Этот метод также учитывает случай, когда вы поменяете прокси.

И вот дополнительное преимущество: Метод, по умолчанию безопасен. Что я подразумеваю под безопасностью? Значению $_SERVER[‘HTTP_X_FORWARDED_FOR’] нельзя доверять, оно может быть подделано клиентом, в случае, когда нет прокси. Так что, если вы не используете на сервере прокси, вашу систему можно легко обмануть. Такого не случится с методом getClientIp(), если только вы не укажете явно, что доверяете этому заголовку, вызвав метод trustProxyData():

Итак, метод getClientIp() работает безопасно при любых обстоятельствах. Вы можете использовать его в любых проектах, вне зависимости от конфигурации, и он будет вести себя правильно и безопасно. Это одна из причин использовать фреймворк. Если же вы решили писать фреймворк самостоятельно, вам нужно самому думать обо всех этих вещах. Почему бы не использовать технологию, которая уже работает?

Если вы хотите узнать больше о компоненте HttpFoundation, можете посмотреть на API или почитать документацию.

Верите или нет, но у вас уже есть фреймворк. Можете остановиться сейчас. Использование компонента Symfony2 HttpFoundation уже позволяет писать лучший и более тестируемый код быстрее, так как много ежедневных проблем уже решены за вас.

Кстати говоря, проект Drupal, начиная с версии 8, использует компонент HttpFoundation. Если он подходит им, думаю подойдет и вам. Не изобретайте велосипеды.

Почти забыл сказать об одном дополнительном преимуществе: использование компонента HttpFoundation способствует лучшей совместимости между всеми фреймворками, и приложениями, которые их используют (Symfony2, Drupal 8, phpBB 4, Silex, Midgard CMS, Zikula, …)

К содержанию >>
Оригинал статьи на английском языке >>
Исходный код из статьи >>

Не забудьте поделиться статьей с друзьями

Подписывайтесь на меня в соц. сетях

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *