Структура, конечно зависит от, собственно, того, что за приложение создается.
Мы занимаемся в основном системами ERP. в которых работники работают за своими рабочими местами.
Каждое рабочее место оптимизировано для того, чтобы в нем было удобно делать именно ту работу, для которой оно предназначено, ничего лишнего там быть не должно.
Таких рабочих мест даже в большой системе не очень много - максимум пара десятков.
Эти рабочие места и что с ними связано, у нас организуются как модули.
Также: в системе бывают "группы сущностей" - это набор таблиц, объединенных некой общностью.
Например, client, client_type, client_status, client_comment, client_phone, client_email - это все группа сущностей client.
AR модели с этими группами сущностей лежат каждая в своей папочке в корневой папке model. В основном в этих моделях указаны те вещи, которые будут нужны при использовании сущности в любом модуле.
Например, некоторые общие правила валидации, аннотации phpdoc, реляции и тому подобное. при использовании в каком-либо модуле, в этом модуле размещается модель, наследуемая от соответствующей вышеописанной.
Сами вышеописанные модели наследуются, в свою очередь, от Базовых моделей и, иногда, включают в себя трейты с нужным функционалом.
Базовые модели, в свою очередь, включают в себя некоторую очень общую функциональность - например, код: связанный с реализацией доступа с применением политик защиты строк.
Модули используют в своей работе свои собственные контроллеры, однако, если при работе появляются ситуации, когда одна операция с сущностью происходит в нескольких модулях (или по наитию архитектора), экшен переезжает в Контроллер группы сущностей, расположенный в корневой(для приложения) папке.
Работы с некоторыми сущностями "для внутреннего пользования" происходит через Сервисы(Провайдеры), оформленные как компоненты приложения.
Все вышесказанное, наряду с нестандартной структурой БД, позволяет создавать легко поддерживаемый быстрый код, мы практически не сталкиваемся с ситуацией, когда необходимо что-то серьезно переделывать для добавления неожиданного функционала, Мы не переделываем: а ДОДЕЛЫВАЕМ.
Да, еще одна особенность - мы почти не используем view - в каждом модуле один view - вида <div id="<module-name>-react-root"></div>
Весь фронтенд - исключительно на react (ну или редко vue)
Жуть )