PHPixie_logo

PHPixie является хорошо продуманная структура PHP кодируется вокруг архитектуры MVC, и идея расширения функциональности с помощью модулей вместо зубрежки все это внутри ядра фреймворка.
Это очень легкий, когда дело доходит до размера файла, обеспечивает быстрое время компиляции, приходит документально и при поддержке композитора.
Ядро систематизации содержит все необходимые утилиты современного веб-приложения, от регуляторов и двигатель маршрутизации, для классов управления и сопряжение базы данных.
Отдельные модули существуют для поддержки Haml, кэширование данных, миграции базы данных, обработка изображений, проверки данных, разбиение на страницы данных и аутентификации пользователя.
Всего в рамках, кажется, в ведении человека с глубоким знанием PHP, а также, кажется, поддерживается и регулярно обновляется.

Как и например Symfony, PHPixie состоит из двух частей: библиотеки компонентов и базового проекта, правда в случае PHPixie базовый проект более тонкий и состоит всего из нескольких файлов. Он здесь исполняет роль примера и поэтому изменение его под себя не только приветствуется но в некоторых случаях даже необходимо. Именно для этого важно понимать что и как происходит в системе.

Конечно тем кто уже знаком с MVC  наверняка эта схема уже покажется знакомой, но для новичков может быть очень полезна. Итак начнем c index.php куда и попадают все запросы, здесь самые важные строчки это:

И сразу же мы попадаем на самую важную часть, класс App\Pixie который является сердцем фреймворка, его DI контейнером. Через него можно получить доступ ко всем другим компонентам. App\Pixie наследует от PHPixie\Pixie из библиотеки PHPixie-Core. Базовый проект оглашает этот класс вместо использования PHPixie\Pixie напрямую для предоставления разработчику возможности внести в него свои изменения ( например подключить модуль).

Сразу стоит отметить что добавлять новые сущности в этот контейнер на ходу, как например в Silex, нельзя, все надо описывать явно в классе. Хотя это и может показаться не таким удобным на первый взгляд, но зато позволяет добиться лучшей читабельности кода, полностью продокументировать все сущности (так как все они становятся атрибутами класса) а также получить подсказки по этим сущностям в IDE. Поскольку PHPixie\Pixie содержит также все фактори методы, то это позволят нам с легкостью заменить любой класс фреймворка на свой путем перегрузки соответствующего метода.

Метод bootstrap() инициализирует $pixie, считывает конфигурацию, подключает обработку исключений итд. Как раз в handle_http_request() проходит обработка запроса. Этот процесс состоит из трех этапов:

  • Создание объекта $request класса PHPixie\Request
  • Этот объект передается в соответствующий контроллер и выполняется соответствующий action
  • В процессе исполнения екшена контроллер изменяет объект $response ( PHPixie\Response )
  • Данные из $response (хедеры и контент) отсылаются пользователю

Все три самых важных объекта $request, $response и $pixie доступны как атрибуты класса PHPixie\Controller. Теперь отвлечемся немного на еще несколько парадигм написания кода на PHPixie:

Не использовать оператор «new» нигде кроме фактори методов. Каждый новый класс должен иметь фактори метод (например в App\Pixie) для создания его екземпляров. Такой подход позволяет легко заменить один класс другим, что особенно важно при написании юнит тестов. Так тестируя например контроллер вы теперь сможете передать в него замоканный App\Pixie который вместо реальных классов передаст их моки.

Не использовать статические проперти и методы. Использование статики сильно усложняет написание тестов. Используя PHPixie можно легко обойтись без них, достаточно добавить экземпляр как атрибут App\Pixie и вы сможете получить к нему доступ практически из любого места. Таким образом мы фактически получим синглтон. Кстати сделать это можно еще путем добавления его в $instance_classes.

Как работают модули

Каждый модуль для PHPixie это дополнительная библиотека классов которая предоставляет свой DI контейнер очень похожий на главный PHPixe\Pixie, то есть он состоит из методов фабрик для создания экземпляров классов который входят в модуль. Потом мы просто добавляем его в массив модулей в главный контейнер:

А что делать если я например хочу подменить класс PHPixie\ORM\Model на свой App\Model? Все просто, надо еще сделать свой App\ORM (extends PHPixie\ORM ) метод get() которого вместо модели PHPixie\ORM\Model будет возвращать ту что нужна нам. в этом еще больше проявляется одна из идей фреймворка — как можно больше использовать стандартные приемы ООП вместо каких-то магий. Например чтобы подменить класс самого фреймворка приходится применять subclass_prefix и делать єто на уровне конфигурации а не собственно программирования. Такой подход позволяет намного улучшыть понимание системы, так как по большей части в флове можно разобраться не зная ничего о фреймворке, просто посмотрев на сами классы.

А как же хуки, ивенты и прочее?

Их нет и я так понимаю не будет. Такие вещи полностью из другой парадигмы так как делают код нелинейным, особенно это относится к ивентам, где всегда не до конца понятно который из листенеров запустится первым и что случится если он сам вызовет какой-то ивент. А также от их использования очень часто страдает читабельность бектрейсов, так как они вызываются самим фреймворком где-то там где сам программист кода точно не писал. Если нужно что-то сделать в каком-то месте гораздо проще перегрузить метод который как-раз это и делает и дописать к нему ту логику что нужно.

nette-logo-oval

Работа с формами


Предусмотрена валидация как на стороне клиента (javascript), так и на стороне сервера. Присутствует встроенная защита от атак (XSS и CSRF). Несколько доступных режимов рендеринга формы. Интернационализация (i18n) позволяет создавать мультиязычные формы.

В целом, по функциональности и конструкциям похоже на формы Zend Framework, но как-то более легко и свежо. Вместо страшных зендовских декораторов – более понятные на первый взгляд wrappers.

 

Собственный шаблонизатор


Latte. С хитрыми макросами, встроенными в HTML-теги. На вид, гораздо более читаемо, чем нативный PHP.

Важно, что шаблонизатор эскейпит переменные по умолчанию при выводе на страницу, что не позволяет забыть об этом. Упоминается некоторая умная технология Context-Aware Escaping, позволяющая автоматически корректно эскейпить различные переменные. Собственно, громких названий в этом фреймфорке хватает. Но, может, это не так и страшно.

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

В целом, шаблонизатор более простой и понятный, по сравнению с Smarty.

 

Конфиги


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

 

Кроме того


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

 

 

MNcVh0Z

Начало

Вторая версия отличается от первой кардинально. Список в краткой форме:

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

— Базовый CComponent разделили на Object и Component. Первый осуществляет работу геттеров и сеттеров, второй расширяя первый, добавляя события и поведения.

— Видоизменилось подключение событий и поведений. Подписываемся на событие

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

— Добавили новый класс View, теперь у нас настоящий MVC фреймворк. Представление

* View можно для каждого контроллера устанавливать, или использовать базовый для приложения.

— render() контроллера больше ничего не выводит. Оно возвращает данные

— В контроллере появились два события, на котрые можно подписываться: beforeAction, afterAction

— Убраны фильтры контроллера CFilter, теперь все делается через поведения

— В контроллере появился отличный помощник — метод populate

— Добавлены еще несколько статических классов-хелперов: ArrayHelper, StringHelper, SecurityHelper. Все хелперы теперь можно перекрыть через LSB. Ура, воскликнул я, т.к лично мне не раз нужно было перекрытьHtml.

— Виджет ActiveForm тоже переписан, и скорее всего заменит форм-билдер CForm. Каждое поле формы теперь может быть представлено как объект ActiveField, который создает ActiveForm

* Внимание: в Html::tag($tag, $content, $options) — изменили порядок параметров!

ActiveRecord

«По большей части, ActiveRecord осталась нетронутой»

— написано в предыдущей статье. Верно подмечено — не трогали.
Просто взяли и написали совсем другой ActiveRecord.

— Забываем про model()

— Убран CDbCriteria. Но не пугайтесь, работа с базой стала от этого легче. Появился ActiveQuery, который представляет себя гибрид CActiveFinder и CDbCriteria.

— Все общие методы теперь статические: getDb, tableName, find*, saveAll*, primaryKey. Выигрыш очевиден.

— Связи, куда же без них. Теперь связи определяются добавлением геттеров

— Для удобства работы со связями добавили link() и unlink(), который автоматически расставят ключи
— Именованные группы условий есть, но в другом виде. У нас же нет больше CDbCriteria, а значит и массивов условий тоже больше нет. Теперь это методы, причем статические, добавляющие условия в Query
  • Отсутствие обратной совместимости с Yii 1.1;
  • Пересмотрена архитектура классов, некоторые их реализации;
  • Отсутствие, как следствие новой архитектуры, некоторых сущностей, например: CDbCriteria, CClientScriptCUserIdentity и другие;
  • Поддержка шаблонизаторов Smarty и Twig.
Namespace
Псевдонимы путей
Компонент и объект
  • \yii\base\Object – легковесный класс, реализующий определение атрибутов класса через методы получение (set) и установки (get);
  • \yii\base\Component – является расширением вышеуказанного, который поддерживает дополнительно события (event) и поведения (behavior).
Консольные приложения

Yii 2.0 активно развивается

 

Что такое Symfony 2

symfony_logo-750x410

Высокопроизводительная среда (фреймворк) для разработки надёжных приложений на PHP5.

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

Множество других современных фреймворков или систем управления сайтом (CMS) используют ядро Symfony, что говорит о заслуженном признании профессиональным сообществом.

Для чего Symfony 2 нужен разработчикам

  • Ускоряет разработку.
  • Оберегает от ошибок.
  • Стандартизирует разработку.
  • Облегчает доработку и поддержку.

Для чего Symfony 2 нужен заказчику

  • Гарантия профессионализма и высокого уровня разработки.
  • Независимость от одной компании.,

Версии

Цвет Описание
Красный Старая версия; не поддерживается
Зелёный Текущая версия
Голубой Планируемая версия
Версия Дата релиза Поддержка Версия PHP Версия ORM Окончание поддержки Заметки
1.0 Январь 2007 3 года >= 5.0 Январь 2010
1.1 Июнь 2008 1 год >= 5.1 Июнь 2009 Патчи безопасности выпускались до июня 2010
1.2 Декабрь 2008 1 год >= 5.2 Ноябрь 2009
1.3 Ноябрь 2009 1 год >= 5.2.4 Propel: 1.4Doctrine: 1.2 Ноябрь 2010
1.4 Ноябрь 2009 3 года >= 5.2.4 Propel: 1.4Doctrine: 1.2 Ноябрь 2012 Версия 1.4 идентична версии 1.3, но в ней не поддерживаются возможности, объявленные нежелательными к использованию в версии 1.3[6]
2.0[7] Июль 2011 >= 5.3.2 Doctrine: 2.1 Март 2013
2.1[8] Сентябрь 2012 8 месяцев >= 5.3.3 Doctrine: 2.2 Июнь 2013
2.2[9] Март 2013 8 месяцев >= 5.3.3 Doctrine: 2.2 Ноябрь 2013
2.3[10] Июнь 2013 3 года >= 5.3.3 Doctrine: 2.2.3 Май 2016 Первая версия в ветке 2.x с долгосрочной поддержкой
2.4[11] Ноябрь 2013 10 месяцев[12] >= 5.3.3 Doctrine: 2.2.3 Сентябрь 2014
2.5[13] Июнь 2014 8 месяцев >= 5.3.3 Doctrine: 2.2.3 Январь 2015
2.6[14] Ноябрь 2014 8 месяцев >= 5.3.3 Doctrine: 2.2.3 Июль 2015
2.7 Май 2015 3 года >=5.3.9 Doctrine: 2.2.4 Май 2018 Версия с долгосрочной поддержкой
2.8 Ноябрь 2015 3 года >=5.3.9 Doctrine: 2.2.4 Ноябрь 2018 Версия 2.8 вышла одновременно с версией 3.0 и является долгосрочной, но поддерживает возможности версии как 3.0 так 2.7. Версия 2.8 считается переходным на 3.0, она помогает перевести свой проект с 2.7 на 3.0. Версия 2.8 предупреждает о функциях которые не поддерживаются в 3.0 и помечает их как устаревшие, но дает возможность их все еще использовать.
3.0[15] Ноябрь 2015 8 месяцев >=5.5.9 Doctrine: 2.2.4 Июль 2016 Версия с поддержкой PHP 7.0
3.3 [15] Май 2017 3 года Версия с долгосрочной поддержкой

1. Установка и настройка

Скачать дистрибутив можно с официального сайта. Думаю лучше скачать версию-standart которая идёт со всеми дополнительными компонентами. Далее я предпологаю что архив был распакован в корневую папку вашего веб-сервера.
Проверить что все корректно работает можно по этой ссылке: http://localhost/Symfony/web/config.php.
Если все нормально, то можно начинать, но для начала нужно закомментировать одну строку в файле Symfony/web/app_dev.php

$kernel->loadClassCache();

Очень странное решение, по умолчанию включать кеш в режиме разработки.

2. Создание нового приложения

Приложения в Symfony 2 имеют модульную структуру, модули называются бандлами (bundle). Наше demo-приложение будет находиться в своём отдельно бандле. В Symfony существует очень много консольных команд, которые помогут вам в работе. Есть соответсвующая команда для генерации структуры нового бандла:

php app/console generate:bundle --namespace=Demos/BlogBundle

Эту команду нужно выполнить из консоли, находясь в папке Symfony/. Если вы работаете в линуксе, то можете присвоить файлу console права на выполнения и не писать перед ним php. Генератор задаст несколько простых вопросов на каждый из которых у него есть ответ по умолчанию. Так как мы создаём своё первое приложение, то согласимся на все варинты. Итак, нажав несколько раз клавишу enter мы получим скелет нашего бандла в папке Symfony/src/Demos/BlogBundle.

3. Контроллер и основы роутинга

Как и большинство современных фреймворков, Symfony придерживается паттерна MVC. Мы начнём своё знакомство с реализацией этого паттерна в Symfony с последней буквы, т.е. контроллера.
Наш маленький бандл уже имеет один контроллер, он называется DefaultController и находися в папке src/Demos/BlogBundle/Controller. Если вы заглянете внутрь него, то увидите что у него реализован экшен indexAction. Сейчас мы увидим что он делает. Откройте в своём браузере адресhttp://localhost/Symfony/web/app_dev.php/hello/username.
Вы можете удивиться почему именно такой адрес у этой страницы, но если внимательно посмотрите на PHPDoc (это такие специальные комментарии, которые начинаются с символов /**) перед функцией indexAction, то наверняка всё поймёте. Аннотация Route указывает по какому адресу доступен данный экшен и какой параметр он имеет.
Вообще, можно добиться того же и без аннотаций, но они применяются в Symfony повсеместно, так что лучше сразу к ним привыкать. С одной стороны они более лаконичны, а с другой для них не очень хорошо поддерживается автокомплит в моей любимой IDE.
За настройку того как будут выглядеть урлы вашего приложения отвечает специальный компонент Routing, он очень гибко позволяет всё настроить. Более подробно можно почитать в соответсвующем разделе документации. Мы же кратко рассмотрим почему наше приложение открывается именно по этому адресу и почему от нас не потребовалось для этого ничего настраивать.
Если вы не очень внимательно читали что у вас спрашивал генератор бандла, то вполне могли пропустить его вопрос о том обновить ли настройки роутинга в соответствии с новым бандлом. Если пропустили, то можете открыть файл Symfony\app\config\routing.yml. Там вы увидите такую запись:

DemosBlogBundle:
resource: "@DemosBlogBundle/Controller/"
type: annotation
prefix: /

Первая строка — это название секции с конфигурацией, оно соответсвует имени нашего бандла. Вторая строка — указывает откуда импортировать настройки. В данном случае будут читать все файлы из папки с контроллерами, а следующая строка говорит что все необходимые настройки описаны в аннотациях экшенов. Ну а аннотации мы уже видели. И, наконец, последняя строка указывает какой префикс будет добавлен ко всем урлам из нашего бандла. По умолчанию все урлы доступны напрямую от имени входного скрипта. Давайте поменяем / на /blog чтобы было более логично.
Теперь все что мы будем делать будет доступно по адресу http://localhost/Symfony/web/app_dev.php/blog.

4. Работа с Doctrine: создание модели

Теперь перейдем к следующему шагу — работе с базой данных. Я буду использовать Doctrine, хотя никто не обязывает этого делать, вместо доктрины можете использовать любой удобный вам способ работы с бд. Однако, доктрина хорошо интегрирована с symfony и работать с ней одно удовольствие.
Для начала настроим подключеник к бд. Откройте файл app/config/parameters.ini и опишите свои настройки. Кстати, интересно, почему все настройки по дефолту в yml, а этот в ini-файле. Если в настройках вы указали не сущесвующую базу данных, то выполните следующую команду:
php app/console doctrine:database:create
и доктрина сама создаст её.
Доктрина является полноценной ORM, но построна она по другому принципу нежели ActiveRecord, с которым у многих сейчас однозначно ассоциируется это понятие. Доктрина реализует шаблон Data Mapper который очень подрбно описан здесь.
Для начала нам нужно описать сущность с которой мы будем работать. Это будет класс Post с нужными нам свойствами. Создайте папку src/Demos/BlogBundle/Entity. В ней создайте файл Post.php и заполните его следующеим кодом:

<?php
namespace Demos\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\Table(name=”post”)
*/
class Post {

/**
* @ORM\Id
* @ORM\Column(type=”integer”)
* @ORM\GeneratedValue(strategy=”AUTO”)
*/
protected $id;

/**
* @ORM\Column(type=”string”, length=255)
*/
protected $title;

/**
* @ORM\Column(type=”text”)
*/
protected $body;

/**
* @ORM\Column(type=”datetime”)
*/
protected $created_date;

/**
* @ORM\Column(type=”datetime”)
*/
protected $updated_date;
}

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

php app/console doctrine:generate:entities Demos/BlogBundle/Entity/Post

Теперь посмотрите в файл Post.php, в нём должны были появиться соответсвующие методы. У нас есть есть описание модели, по ней нужно создать соотвествующую таблицу в базе данных. Для этого выполните:

php app/console doctrine:schema:update --force

Если все прошло без ошибок, то в вашей бд должна было появиться таблица post. Перейдём к непосредсвенной работе с объектами. В классе DefaultController создайте новый экшен с таким кодом:

/**
* @Route("/create")
*/
public function createAction() {
$post = new Post();
$post->setTitle('Demo Blog');
$post->setBody('Hello Symfony 2');
$post->setCreatedDate(new \DateTime("now"));
$post->setUpdatedDate(new \DateTime('now'));

$em = $this->getDoctrine()->getEntityManager();
$em->persist($post);
$em->flush();

return new Response(‘Created product id ‘ . $post->getId());
}

А в начало файла нужно добавить импорт нужных пространств имён:

use Demos\BlogBundle\Entity\Post;
use Symfony\Component\HttpFoundation\Response;

Теперь если вы откроете адрес http://localhost/Symfony/web/app_dev.php/blog/create, то в ответ должны получить id созданной записи.
Теперь создадим экшен для вывода сущесвующих записей. Для этого нам понадобится экшен с параметром, который будет принимать id записи.

<?php
/**
* @Route("/show/{id}")
*/
public function showAction($id)
{
$post = $this->getDoctrine()->getRepository('DemosBlogBundle:Post')->find($id);

if (!$post) {
throw $this->createNotFoundException(‘Страница не найдена!’);
}

$html = <<<HTML
<h1>{$post->getTitle()}</h1>

<p>{$post->getBody()}</p>

<hr/>
<small>Запись создана {$post->getCreatedDate()->format(“Y-m-d H:i:s”)}</small>
HTML;

return new Response($html);
}
?>

Теперь можете просмотреть запись пройдя по ссылке http://localhost/Symfony/web/app_dev.php/blog/show/1. На этом с доктриной закончим, подробности в документации.

5. Twig: первые шаблоны

Пора перейти к заключительной части нашего знакомства с Symfony. На прошлом шаге мы поступили не очень хорошо смешав логику работы с выводом записи в showAction. Избавиться от этого недостатка нам поможет View (по русски «вид» звучит как-то не очень хорошо, поэтому я буду называть это вьюхой ;).
В качестве шаблонизатора Symfony использует Twig — пожалуй лучший PHP-шаблонизатор с которым я работал. Как и любой другой компонент симфони можете заменить его на то, что вам больше нравится.
Как вы помните у экшена indexAction есть специальная аннотация Template(), которая говорит что у него есть шаблон.

return array('name' => $name);

Массив который возвращается из экшена передаётся во вьюху, ключи массива буду именами переменных которые будут там доступны.
Давайте изменим экшен show. Нужно добавить соответсвующую аннотацию и вместо того чтобы возвращать объект Response вернуть массив в котором будет просматриваемая запись. Вот что получилось:

/**
* @Route("/show/{id}")
* @Template()
*/
public function showAction($id)
{
$post = $this->getDoctrine()->getRepository('DemosBlogBundle:Post')->find($id);

if (!$post) {
throw $this->createNotFoundException(‘Страница не найдена!’);
}

return array(‘post’ => $post);
}

Согласитесь, так гораздо лучше. Теперь в папке src/Demos/BlogBundle/Resources/views/Default создайте файл show.html.twig в который перенесите html код который был у нас экшене. Синтаксис твига отличается от php поэтому придется кое-что изменить. Конечный вариант смотрите в исходниках. Узнать больше о синтаксисе твига можно в его документации.

LARAVELLaravel — бесплатный веб-фреймворк с открытым кодом, предназначенный для разработки с использованием архитектурной модели MVC (англ. Model View Controller — модель-представление-контроллер). Laravel выпущен под лицензией MIT. Исходный код проекта размещается на GitHub

В результате опроса sitepoint.com в декабре 2013 года о самых популярных PHP-фреймворках Laravel занял место самого многообещающего проекта на 2014 год

В 2015 году в результате опроса sitepoint.com по использованию PHP-фреймворков среди программистов занял первое место в номинациях:

  • Фреймворк корпоративного уровня
  • Фреймворк для личных проектов

Laravel — это чистая и стильная основа для разработки. Он избавит вас от спагетти кода. Поможет вам создавать прекрасные веб-приложения используя простой и выразительный синтаксис. Разработка должна доставлять удовольствие. Наслаждайтесь глотком свежего воздуха.

Еще один PHP фреймворк, подумаете вы. Возможно, но он стоит того, чтобы на него посмотреть.
Фреймворк довольно молодой, 2011 год. Использует PHP 5.3. У него уже хорошее сообщество, много форков. Уже дорос до версии 3.0.

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

Что умеет

Bundles ( Модули ) — имеется репозиторий с обширным количеством бандлов.

The Eloquent ORM — ActiveRecordORM, умеет строить связи ( many to many, one to many, one to one )

Migrations — думаю, правило хорошего тона.

Redis — да, noSQL из коробки.

Environments — в зависимости от домена, может подгружать те или иные конфигурационные файлы.
Скажем, пропишем в файле paths.php

Теперь, если мы зайдем с домена начинающегося на localhost или заканчивающегося на .dev. Фреймворк будет подгружать файлы конфигов с папк application/config/local/* вместо application/config/*

IoC Container — методы для создания и, опционально, инстанцирования и хранения ссылок синглтонов. Это также значит, что вы будете меньше нуждаться в подгрузке внешних библиотек.

Class Auto Loading — так же, можно переопределить в конфиге любой системный класс.

Работа из под CLI — устанавливайте\создавайте миграции, бандлы, запускайте нужные роуты (крон скажем).

Имеется asset менеджер. Весь код вынесен за пределы публичной директории.

Возможностей из коробки довольно много, кому интересно, тот заглянет глубже.