Ответ свой хочу поделить на две части: первая - пара слов насчет прочих framework-ов (в частности Limb/WACT), другая - насчет ENVOS. Я постараюсь не вдаваться в подробности, но высказать свое мнение насчет того, что такое "идеальный" framework.
Limb более года назад разделился на 2 ветки - первая из них - это прежняя CMS, которую все знают как не слишком удобный, быстрый, но этот инструмент нас устраивает, вторая - это фреймворк. С тех пор CMS изменилась очень незначительно (только внешний вид), но фреймворк - очень сильно. Причем изменения велись в основном под воздействием проектов, которые на его базе реализовывались. Постоянный рефактринг, модульное тестирование, иногда TDD, выделение пакетов. CMS - это не больше, чем пакет сейчас. Я просто хочу сказать, что сделать хороший фреймворк без практики и использования продукта в рабочих целях, просто нельзя. Большинство решений, которые мы делали up-front (продумывались, затем реализовывались), оказались или не нужными, или кардинально изменились под влиянием реальных проектов. Мелкие проекты типа "демки" - не в счет: они ничего не показывают.
Что касается WACT - согласен, что его трудно использовать, так как он редко релизится, нередко месяцами вообще висит в подвешенном состоянии, многое в этом плане зависит от project-lead-а, который то более по 4 месяца, по 2 месяца на кояке плавает и т.д. Но у WACT нужно учиться. Как писать классный код, писать хорошие тесты, черпать идеи. Многие концепции WACT понять неопытному разработчику непросто, это да. По приглядеться стоит. Limb, например, сейчас спокойно использует 60% кода WACT (валидаторы, шаблонизатор, итераторы, свойства, callback-и, DBAL, утилиты) без каких-либо проблем.
Что касается остальных фреймворков, которые я недавно смотрел - это symfony (клон Mojavi 4.0) и Cake. Symfony весьма понравился, аккуратно, продолжение хорошо зарекомендовавшей себя идеи. Хорошая библиотека кода, которую скорее всего удобно использовать для типичных задач. Вопрос, как обычно, в изучении этой библиотеки. Cake пока еще слишком молод. Но посмотреть его реализацию ActiveRecord, наверное, стоит.
Для меня интересно, как в том или ином MVC-фреймворке решены вопросы взаимодействия всех компонентов. Как реализован контроллер, что знает View о модели, как обрабатываются ошибки с форм, как они передаются в шаблоны, можно ли менять View по ходу работы действия. Также важно можно ли сменить механизм построения URL-ов, сколько процентов работы выносится в файлы конфигурации, какая модель встраивания пакетов, насколько легко обеспечить повторное использование кода, шаблонов, запросов, насколько легко тестировать мои новые классы, например, действия и т.д. Конечно, для меня признаком качества системы является наличие модульных тестов. По-моему это первый признак того, что система легко расширяема, сделана исходя из реальных требований, что над ней работают опытные разработчики.
Теперь попробую покритиковать Envos
Насчет с модели. Признаюсь, что мне показалось странным, что интерфейс Model содержит метод getView(). В моем понимании MCV Model2 модель ничего не знает о существовании отображения. По идее контроллер передает необходимые данные во View. Часто непосредственную передачу данных в щаблоны осуществляют специальные View-helper-ы (я могу ошибаться в данном термине, так как иногда под view-helper-ами понимают классы, которые используются в непосредственно в шаблонах для вытягивания данных).
Такой класс, как BaseDBModel, наверное было бы правильнее назвать как Query, а еще лучше SelectQuery. Из схожего класса у нас выделились подсистемы Query, Criteria и QueryModifier, небольшие классы с очень четкими интерфейсами. Кстати, в onPHP тоже есть такие классы.
Я не понял, почему Auth класс наследуется от BaseDBModel, а не делегирует ему. Ведь очевидно, что при помощи Auth классы просто некорректно выполнять операции, характерные BaseDBModel.
Вообще называть какой-либо класс Model, просто некорректно. Обычно модель - это множество классов, которые играют порой очень различные роли в рамках одной системы. DBAL - это тоже часть модели, доменные классы, Finder-ы, ORM и т.д. Грести всех под одну гребенку - нельзя.
Теперь насчет цепочки фильтров. Насколько я понимаю, цепочка фильтров, это форма паттерна Chain-of-Responsibility, и теоретически должна быть возможность эту цепочку прервать. У тебя этой возможности нет. FilterManager спрашивает App насчет текущего модуля, действия и далее запускает фильтры. А не бывает ситуации, когда еще для того, чтобы работал сам App нужно выполнить некоторые действия, которые также подходят к цепочке. Лично я бы сделал так: FilterManager просто запускает фильтры, а ту часть, которая находится в верхей части метода execFilters переместил бы еще в один фильтр, который бы создавал еще один экземпляр FilterManager и передавал бы ему нужные фильтры.
Насчет такого частого использования одиночек я уже как-то высказывался здесь на форуме. Одиночки резко снижают тестируемость системы и ее расширяемость. Как минимум нужно иметь возможность заменять любую одиночку другим объектом. Ведь когда ты используешь одиночку, то одижаешь не какую-либо функциональность, а ожидаешь, что одиночка просто поддерживает какой-либо интерфейс. Нужен фильтру название модуля, ему по-барабану, как определяется этот модуль. Используя статические методы, ты связываешь два класса намертво. А раз всем по-барабану как определяется иодуль, значит APP должен обеспечивать возможность замены определения модуля, а это можно сделать только заменив инстанс одиночки на другой. Вообще отношение к одиночкам у всех разное, но большинство тех, кто использует модульное тестирование признают, что их использование нецелесообразно и затрудняет развитие систем. В большинстве случаев от них можно отказаться, например, используя Registry или DI.
Не могу что-то определенного сказать насчет контроллера. Все логично - определили текущий модуль, действие, создали Action, запустили. По действию сформировали шаблон, получили с модели данные, отправили в шаблон. Вроди нормально, все это мы уже видели, например, в Mojavi 1.0. Странновато, правда, было видеть методы методов BaseController :: hasRights(), MainController :: getTemplate() - это вводит слишком много зависимостей в систему. Насчет остального см. мой список вопросов к любому фреймворку выше

Будут ответы?
Мои 2 копейки...