Сравнение PHP-фреймворков: CakePHP, CodeIgniter и Yii

PHP
Не так давно на Хабре проскакивал пост о появлении нового PHP-фреймворка под названием Yii.
После ознакомления, этот фреймворк показался мне интересным, перспективным и достойным внимания.
Недавно Daniel Carrera выложил в своем блоге интересную статью «Comparison of PHP frameworks» о сравнении CakePHP, CodeIgniter и Yii.
С целью популяризации Yii среди русскоговорящего (и плохо-по-английски-читающего) населения я решил сделать перевод.

Осторожно: букв действительно много.
Содержание

  • Простота
  • Документация
  • Производительность
  • Гибкость
  • Безопасность
  • Другие замечания
  • Итоги


Простота


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

CakePHP

Установка: У меня возникли проблемы с Apache, которые не были документированы. Мне пришлось редактировать три файла .htaccess, чтобы добавить команды «RewriteBase».

Использование: Helpers, Actions, Behaviours, Layouts, Components… Неужели я должен знать обо всем этом чтобы написать мою программу? Похоже, у Cake
наивысший порог вхождения и на текущий момент я не вижу у него никаких особых возможностей, которые бы не предоставляли остальные фреймворки.

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

CodeIgniter

Установка: Тривиальная. Всего лишь распаковать файлы и все готово к работе.

Использование: CodeIgniter кажется достаточно простым. Документация не дает повода усомниться в этом. Мое приложение «hello-world» было готово намного быстрее, чем при использовании Cake. В общем, порог вхождения у CI ниже.

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

Yii

Установка: Легкая. Необходимо запустить yiic, чтобы создать корневую веб-директорию. Имеется также PHP-версия (yiic.php), которая хороша, если у вас нет ssh-доступа. Yiic хорошо документирован.

Использование: Yii также кажется простым и понятным, разве что чуть меньше, чем CodeIgniter. Мой «hello-world» был создан почти так же быстро, как и в случае с CI.

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

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

Результат: CodeIgniter кажется наиболее простым, за ним очень близко следует Yii.
Я отложу окончательный вердикт до момента, пока не напишу прототипы приложений во второй части тестирования.

Документация


Пожалуйста, отнеситесь к сказанному критически. Документация обычно начинает выглядеть немного по-другому, когда вы в действительности пишете приложение. Если она неточна или неполна, вы не узнаете об этом до момента начала работы. До сих пор единственным приложением, написанным мной под тестируемые фреймворки, является «hello world».

CakePHP

Мое первое впечатление было положительным. Документация выглядит полной и легкочитаемой. Туториалы было достаточно тяжело обнаружить (они оказались в разделе «Example Applications»). Когда я написал свой «hello world», я столкнулся с проблемой (404 error) и это не было описано в документации. Мне пришлось подредактировать файлы .htacces, чтобы решить это. Я бы хотел видеть раздел «Устранение неполадок» в документации. Кроме того мне было очень тяжело выяснить, как избавиться от примочек (хедер, футер, стили), которые присутствуют в Cake по умолчанию.

CodeIgniter

Первое впечатление было снова позитивным. Замечу, что написание «hello world» заняло у меня намного меньше времени, чем в случае с Cake. Я думаю, причина в том, что CI проще, но также считаю, что на это повлияла и документация.

Yii

И снова мое первое впечатление оказалось положительным, я написал «hello world» очень быстро. После этого я избавился от дополнительных примочек, которые Yii подключает, чтобы сделать страничку симпатичной. Найти как это сделать было очень легко и быстро.

Результат: На данный момент тяжело судить.
Похоже, что у всех фреймворков хорошая документация. У меня было пару проблем с Cake, но я пока что не могу ничего заявить твердо.

Производительность


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

Основные сходства:
Оба теста пытаются оценить минимальные накладные расходы каждого фреймворка. Задача фреймворка — вывести «Hello World» и больше ничего.

Основные различия:
Я использовал конфигурацию каждого фреймворка по умолчанию. Команда Yii піталась оптимизировать каждый фреймворк, чтобы отобразить «Hello World» максимально быстро.
Тест от Yii выполняет только die(). Мой же использует MVC: контроллер устанавливает значение переменной в «Hello World», затем она передается представлению для вывода на основной HTML-странице.
Yii использовали выделенный сервер для тестов, а я — shared hosting, где собираюсь размещать мое реальное приложение.

Таким образом, тесты команды Yii более технически честны, но мои лучше отображают поведение в реальном мире.
Как всегда, все тесты следует воспринимать критически.
Результаты выражены в запросах в секунду (Requests Per Second, RPS), поэтому большие значения — лучше.
image

Детали тестирования:
Данная страница на сайте Yii описывает их тест. В моем тесте каждый фреймворк содержал следующий код в представлении:
image

Где переменная $message предоставляется контроллером, а ее значение — «Hello World». Количество запросов в секунду выяснялось при помощи утилиты ApacheBench с такими параметрами: «ab -t 30 -c 10 URL». Моя тестовая среда — это shared hosting со следующими параметрами:

* CentOS 4 Enterprise Linux.
* Apache 2
* PHP 5.2.6
* CPU: Quad-Core AMD Opteron(tm) Processor 2350
* Memory: 8GB

Выводы: Yii и CI оба выделились в плане скорости. Возможно Yii и имеет некоторое преимущество, но однозначно утверждать тяжело.

Гибкость


CakePHP

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

CodeIgniter и Yii

CodeIgniter и Yii оба выглядят достаточно гибкими. Посмотрев в документацию, проблематично будет сказать, что один точно более гибкий, чем другой.
Оба используют шаблон MVC, но не кажутся очень строгими в этом плане. CakePHP намного больше зависит от соглашений, чем Yii и CI.

Некоторые примеры сходств и различий:
* Каждый из фреймворков ожидает от вас следования соглашениям об именовании контроллеров.
* CakePHP требует создания модели, базы данных и таблицы, даже если они не используются в вашей программе.
* Cake сам вызывает представление автоматически, основываясь на имени контроллера. В CI и Yii вы вызываете представление явно, поэтому у Cake соглашения более преобладают над конфигурацией. В свою очередь, в CI и Yii вы можете вызывать несколько представлений.

Вот пример кода:
image

Как можно видеть, версии для CI и Yii не кажутся более сложными, чем для CakePHP, кроме того у них есть дополнительная возможность — вы можете загружать более одного файла представления. К примеру, вы можете загрузить специальный хедер, вставить виджет и т.п.

Результат: CodeIgniter и Yii оба выглядят более гибкими. На данным момент я не могу определить, какой из них более гибкий.

Безопасность


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

Контроль доступа

Предварительная информация тут — Аутентификация и Авторизация.

CakePHP

Я обнаружил, что система контроля доступа в CakePHP трудна для понимания. Для генерации файлов схем и списков контроля доступа (ACLs) используется генератор кода («cake bake») — этот процесс выглядит замысловато. Некоторые термины (ACOs, AROs, Requester) добили меня окончательно.

Я ожидал, что контроль доступа — это непросто, но в Cake это оказалось намного более сложным, чем я предполагал. Выглядит достаточно мощно, но тяжело в использовании. Я почувствовал, что не контролирую процесс и не понимаю, что же происходит. А безопасность — это именно то, над чем бы я хотел иметь контроль и что я бы хотел хорошо понимать.

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

CodeIgniter

Насколько я могу судить, CI не предоставляет средств по контролю доступа. Контроль доступа может быть достаточно сложной задачей (группы, роли и др.) и было бы неплохо, если бы фреймворк помогал в этом.

Yii

Я намного быстрее понял систему контроля доступа в Yii. Я бы не сказал, что она проста, но это потому, что контроль доступа сам по себе непрост. Я бы сказал, что в Yii система контроля доступа проста настолько, насколько это возможно — но не более того. После того как я прочитал документацию, мне показалось, что я понимаю процесс и что я способен изменить его под мои нужды.

Быстрый тест: я смог тут же найти, как усилить стойкость паролей.

Некоторые фишки Yii, которые мне нравятся

* Гибкость: у вас могут быть правила доступа, основанные на пользовательском IP-адресе или типе запроса (GET vs POST), или правила для анонимных и авторизированнх пользователей.

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

* Контроль доступа, основанный на ролях (Role Based Access Control): RBAC более гибкий и мощный способ, нежели традиционные ACL. С фреймворком Yii вы можете писать свое приложение, не обращая внимания на RBAC, и использовать его только в тех случаях, когда требуется решить специфическую задачу. Итак, система настолько гибкая, насколько должна быть, но ваши правила доступа сложны не более, чем того требуется.

Атаки по словарю (Dictionary attacks)

Атака по словарю состоит из попыток подбора пароля, используя список наиболее употребимых слов — словарь. В случае веб-приложений такая атака может быть очень эффективной. Недавняя атака на Twitter была атакой по словарю.

Есть множество методов прерывания атаки по словарю: блокировка аккаунта после Х неудачных попыток авторизации, временные задержки, CAPTCHAs. Каждый их них имеет свои преимущества и недостатки. Блокировка аккаунтов — это легко и эффективно, но дает возможность для атаки на отказ в обслуживании: кто-то может совершить множество попыток авторизации, но не для того, чтобы получить доступ, а чтобы вызвать блокировку других пользователей. Вот один их методов, которые мне нравятся: после 5 неудачных попыток вы должны решить капчу, чтобы получить дополнительные попытки. Это позволяет контролировать атаки по словарю, DoS и удобство для пользователя.

Ни один из фреймворков не имеет средств, относящихся к проблемам атак по словарю или отказа в обслуживании, но я этого и не ждал. Настоящий вопрос в том, сможете ли вы в данном фреймворке настроить способ авторизации именно так, как нужно вам? Это вопрос контроля и гибкости. В CI и Yii я уверен, что смогу это сделать. Однако я не так уж уверен в этом в случае CakePHP.

Межсайтовый скриптинг (Cross-site scripting attacks, XSS)

XSS опережает переполнение буффера в рейтинге наиболее распространенных проблем безопасности. Это работает так: Кто-то публикует комментарий в вашем блоге и это сообщение включает в себя вредоносный JavaScript-код. Когда вы просматриваете блог, код исполняется. Так как код берется из вашего домена, он считается браузером «безопасным». Этот код может читать ваши кукисы, или изменять содержимое страницы (например, «Сессия истекла. Пожалуйста введите ваш пароль.»).

CodeIgniter и Yii поставляются с HTML-фильтрами, которые могут удалять JavaScript-код из пользовательского ввода. К сожалению, CakePHP не имеет таких фильтров.

Внедрение SQL-кода (SQL injection attacks)

Внедрение SQL-кода является одной из наиболее частых атак и брешей в безопасности веб-приложений (комикс). Это происходит, когда текст, введенный пользователем, интерпретируется как исполняемый SQL-код. Например:
image

Предположим, пользователь ввел пароль foo' OR 1='1. Тогда запрос будет таким:

image

Так как 1='1' — всегда истина, запрос вернет список всех пользователей. Наиболее частое (и неверное) решение — экранирование строк при помощи функций типа addslashes() или mysql_real_escape_string():

image

Что же не так с этим решением?
* Оно подвержено ошибкам, так как вы должны не забыть это сделать для каждого параметра.
* Также оно зависит от того, что кто-то может найти все возможные символы, которые могут использованы для взлома. Хорошие ребята находят все дырки, плохим же достаточно найти одну. Это игра для лузеров.

Chris Shiflett показывает, как провести внедрение SQL-кода в обход addslashes, используя китайский символ. Откуда мы можем знать, что не найдется какой-нибудь тамильский символ, который позволит обойти mysql_real_escape_string?

Правильное решение: подготовленные выражения (prepared statements)

Верным решением будет решить проблему в целом путем составления SQL запроса отдельно от пользовательского ввода, тоесть использовать подготовленные выражения (другими словами, параметризированные запросы). Подготовленные выражения отделяют логику SQL-запроса от пользовательских данных (см. тут и тут).

Поддерживает ли фреймворк подготовленные выражения?

К сожалению, лишь один из трех фреймворков — Yii — предоставляет такую возможность. Я думаю, что отсутствие подготовленных выражений — это наиболее серъезная проблема CakePHP и CodeIgniter.

Подделка межсайтовых запросов (Cross-site request forgery attacks, CSRF)

Подделка межсайтовых запросов (CSRF) используется в некотором смысле дополнительно к атакам с помощью межсайтового скриптинга(XSS). XSS злоупотребляет доверием клиента серверу, CSRF — доверием сервера клиенту. Представьте, что Боб посещает вредоносный сайт, содержайщий следующий тэг image:
image

Если Боб в данный момент авторизирован на своей банковской странице, то сервер банка получит запрос от Боба о переводе $10,000 на счет Евы.

Что же можно сделать для защиты от CSRF? Кроме того, что можно уменьшить период жизни кукисов, основным решением служит использование секретного значения для аутентификации любых параметров GET и POST, которые могут изменять данные на сервере.

CakePHP и CodeIgniter, похоже, не имеют средств для борьбы с CSRF. Yii предлагает защиту от CSRF для POST-запросов путем использования секретных токенов (вы должны включить эту функцию). Чтобы польностью защититься от CSRF вы должны быть уверены, что GET-запросы не могут изменять данные на сервере.

Кража куки (Cookie hijacking attacks)

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

Как защититься от кражи куки? SSL защитит вас от снифферов, и вы должны принять меры для предотвращения XSS-атак. Вы можете сделать куки менее значимыми, отказавшись от длительного хранения в них значимой информации. Например, вместо хранения md5(passwd) используйте хеши, срок дествия которых истекает — HMAC(date,md5(passwd)).

Насколько я знаю, CakePHP и CI не обладают никакими защитными механизмами против краж куки. Yii имеет возможность проверки куки, которая использует HMAC для аутентификации содержащихся данных. Атакующий не сможет изменить данные истекшего куки (например, дату истечения), не будучи замеченным.

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

Победитель: Yii
Yii имеет значительное преимущество в плане безопасности, с лучшей системой контроля доступа и защитой от XSS, внедрения SQL-кода, подделки межсайтовых запросов и краж куки.
CakePHP и CodeIgniter немного разочаровывают в этом плане. Так как CI более гибкий, в нем будет легче добавить требуемые средства защиты самому.

Другие замечания


Есть некоторые вещи, о которых я считаю необходимым упомянуть, хотя они и не попадают под критерии данного теста.

Prototype
CakePHP использует библиотеку Prototype. Я имел дело с Prototype. В основном, она загрязнет глобальное пространство имен и может поломать уже работающий JavaScript-код. Таким образом, Prototype не ведет себя хорошо с вашим кодом или другими библиотеками.

Запланированные релизы
У Yii имеются запланированные релизы. Я бы хотел, чтобы так было у всех opensource-проектов.

Фильтрация ввода
У CodeIgniter есть отличный класс Input, который производит очистку данных. Он уничтожает массив GET и все глобальные переменные, кроме POST и COOKIE. Эта фишка не совсем вписывается в мои критерии, но способствует более хорошему коду, и поэтому достойна упоминания. О XSS-фильтрации я упоминал в предыдущем разделе.

Итоги


Мое мнение — CakePHP несомненно хуже, чем CI и Yii. Документация, в общем-то, хороша, но не лучше, чем у CI и Yii. Я не вижу ни одной области, в которой Cake выглядит отчетливо лучше CI или Yii. Он может быть лучше для простых приложений, которые делают все именно так, как того ожидает Cake. Но в общем, Cake более сложен, нежели CI or Yii, и похоже что оно того не стоит.

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

Обычно я не люблю сравнительные таблицы, так как они слишком упрощают вещи. Но я понимаю, что люди часто хотят видеть краткую итоговую таблицу, поэтому предоставлю примерный набросок:

image

[1] Воспринимайте критично. Тяжело судить о документации до того, как приступишь к написанию программы.
[2] CodeIgniter получает очко за фильтрацию XSS и общую гибкость.

Оригинал статьи и копирайты — Daniel Carrera, «Comparison of PHP frameworks — Part I»
Tags:phpframeworkcakephpcodeigniteryiiсравнение
Hubs: PHP
+85
46.1k 202
Comments 136

Popular right now

PHP-программист Yii
from 150,000 ₽Max.CreditСанкт-ПетербургRemote job
PHP-разработчик
to 100,000 ₽Авто-АльянсRemote job
PHP Middle разработчик / Backend Developer
from 60,000 to 150,000 ₽MediaLineМоскваRemote job
PHP Developer
from 120,000 to 200,000 ₽Perfect PanelСевастополь
PHP-разработчик
from 150,000 ₽Большая ТройкаМоскваRemote job