Skip to content

ivankarmanow/phpca

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Шаблон чистой архитектуры на PHP

Данный шаблон представляет собой пример реализации чистой архитектуры на PHP

Установка и запуск

Для запуска просто склонируйте репозиторий

git clone [email protected]:ivankarmanow/phpca.git

Либо скачайте репозиторий в виде ZIP-архива и распакуйте в любую папку.

Далее необходимо настроить базу данных и создать все необходимые таблицы. Данные для подключения к базе данных MySQL через PDO настраиваются в файле config.ini:

db_dsn = "mysql:dbname=test_database;host=localhost"
db_user = root
db_password = ""

Чтобы создать все необходимые таблицы, необходимо выполнить скрипт setup.php

php setup.php

Далее запускайте проект через любой веб-сервер

Структура

Одна из основных составляющих ЧА (Чистой Архитектуры) является упорядоченность и структурированность проекта. Карта файлов проекта выглядит так:

│   .htaccess
│   config.ini
│   extending.md
│   index.php
│   README.md
│   setup.php
│   todo.md
│
└───src
    └───app
        │   di.php
        │
        ├───adapters
        │       IniConfig.php
        │       MySqlGateway.php
        │
        ├───controllers
        │       IndexController.php
        │       StubController.php
        │       UserController.php
        │
        ├───core
        │   │   DIContainer.php
        │   │
        │   ├───config
        │   │       Config.php
        │   │       DbConfig.php
        │   │
        │   ├───exceptions
        │   │       ControllerMissing.php
        │   │       DependencyNotFound.php
        │   │       DispatcherHasNotParents.php
        │   │       EmailExists.php
        │   │       FactoryAlreadyExists.php
        │   │       IncludeParentRouter.php
        │   │       MethodNotAllowed.php
        │   │       NotFound.php
        │   │       RouterYetIncluded.php
        │   │       ValueError.php
        │   │
        │   ├───models
        │   │       Cart.php
        │   │       CartElement.php
        │   │       Category.php
        │   │       Item.php
        │   │       User.php
        │   │
        │   ├───protocols
        │   │       Authentication.php
        │   │       Authorization.php
        │   │       Controller.php
        │   │       DbGateway.php
        │   │       Model.php
        │   │       Repo.php
        │   │       View.php
        │   │
        │   └───routing
        │           Dispatcher.php
        │           methods.php
        │           Request.php
        │           Router.php
        │
        ├───repos
        │       StubRepo.php
        │       UserRepo.php
        │
        └───views
            │   HTMLView.php
            │   RESTView.php
            │
            └───templates
                ├───base
                │       footer.html
                │       header.html
                │
                └───user
                        add.html
                        delete.html
                        get.php
                        list.php
                        update.html

Теперь подробнее про каждый каталог и файл:

  • .htaccess - настройка поведения веб-сервера. В данном случае используется для перенаправления всех запросов на файл index.php, который производит маршрутизацию.
  • config.ini - настройки конфигурации приложения. Используется модулем IniConfig.
  • index.php - основной файл, точка входа. На него перенаправляются все входящие запросы, которые далее передаются в контроллеры. Файл содержит инициализацию и конфигурацию роутеров.
  • setup.php - скрипт для стартового создание таблиц для моделей БД.
  • src/app/ - базовая директория проекта, содержит весь код. Далее рассмотрим её подробнее.

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

  • config/ - базовый конфиг приложения и конфиги всех компонентов как отдельные классы
  • config/Config.php - модель конфига приложения. Обратите внимание, что не указан способ загрузки данных, это возлагается на реализацию.
  • exceptions/ - исключения, используемые приложением. Название каждого класса (файла) говорит само за себя.
  • models/ - модели данных, упрощающие взаимодействие между различными компонентами приложения, к примеру упрощает доступ к данным из базы данных.
  • DIContainer.php - контейнер зависимостей. В проекте используется концепция Dependency Injection (внедрение зависимостей). Благодаря ей класс не знает, как получить ту или иную зависимость (к примеру объект подключения к базе данных или конфиг), а лишь предоставляет список нужных ему компонентов. Остальное происходит автоматически, все необходимые компоненты загружаются из контейнера.

Note

Контейнер хранит не сами объекты, а фабрики для их создания, но сохраняет готовые объекты в кэш для ускорения повторного использования

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

  • Controller.php - базовый класс-контроллер. Не задаёт строго ничего кроме работы с представлениями, так как это общее для всех контроллеров.
  • DbGateway.php - интерфейс абстракции базы данных от кода. Данный интерфейс предоставляет базовые функции работы с моделями, которые можно использовать в более высокоуровневых компонентах без учёта особеноостей работы с БД.

Note

Реализацией интерфейса может быть что угодно:

  • SQL СУБД (MySQL, PostgreSQL)
  • NoSQL СУБД (MongoDB, Redis)
  • Файлы (CSV, JSON, YAML)
  • Object storage, ex Amazon S3

Использование интерфейса даёт свободу выбора системы хранения данных. Если вы решите поменять базу данных проекта, вам не придётся переписывать весь код, достаточно будет изменить лишь класс, предоставляющий интерфейс DbGateway.

  • Model.php - базовый класс для моделей данных. Устанавливает только два статических поля: $tablename и $create_table. Первое хранит название таблицы в БД, которую представляет модель, а второе - код создания таблицы в БД для файла setup.php.
  • Repo.php - самый простой интерфейс. Не делает ничего и служит чисто для метаданных, чтобы указать, что класс является репозиторием. Возможно в будущем обретёт свою функциональность.
  • View.php - базовый интерфейс представления. Определяет метод render, производящий "отрисовку" представления.

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

  • Request.php - простой класс абстракции HTTP-запроса. Даёт доступ к запрошенному пути, методу запроса и его параметрам. Объекты этого класса передаются в контроллеры, предоставляя доступ к данным, пришедшим с фронтенда.
  • Router.php - класс, реализующий роутинг запросов. Для маршрутизации нужно создать его экземпляр, передать в него требуемый контроллер и префикс пути. Затем с помощью функции register и её шорткатов для методов GET и POST: get, post. В функцию необходимо передать регистрируемый эндпоинт (путь) и метод контроллера, который будет обрабатывать данный запросы данного эндпоинта.

Important

Ещё есть интересная функция, сильно упрощающая вложенность эндпоинтов, include_router.

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

Таким образом, запрос рекурсивно обойдёт все роутеры, как по веткам дерева.

  • Dispatcher.php - по сути является просто-напросто корневым роутером, принимающим запрос и передающим его далее вглубь. Не может быть включен в другой роутер, а также желательно не регистрировать обработчики напрямую через него, хотя это и не запрещается. Через диспетчер можно регистрировать обработчики исключений.
  • methods.php - служебный файл, хранящий методы, обрабатывающиеся роутерами. По умолчанию все роутеры поддерживают только методы GET и POST.

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

  • MySqlGateway.php - реализация DbGateway, использующая MySQL через PDO. Вся работа с базой данных происходит в этом классе.
  • IniConfig.php - реализация протокола Config, использующая в качестве источника настроен конфигурации файл .ini. Вы легко можете создать другую реализацию для хранения настроек в другом формате, например JSON или в переменных окружения.

Репозитории представляют слой абстракции между DbGateway и контроллерами. Это нужно для того, чтобы DbGateway не заботился о валидации и преобразовании поступающих от пользователя данных в модели, а контроллерам не нужно было работать с моделями. Через данный слой вы можете, к примеру, добавить дополнительные проверки для методов.

  • StubRepo.php - служебный контроллер, который нигде напрямую не используется и не имеет никаких методов и полей.

Warning

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

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

Поэтому создана эта заглушка.

  • UserRepo.php - репозиторий для работы с пользователями. Содержит несколько функций, реализующих нужную функциональность на основе базовых методов DbGateway. Используется контроллером для доступа к БД.

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

  • StubController.php - используется для той же цели, что и StubRepo, однако также используется в качестве контроллера диспетчера, так как диспетчер не должен сам обрабатывать что-либо.
  • UserController.php - основной контроллер, реализующий все действия надо пользователями. На данный момент реализованы только методы add, list и get.
  • UserController.php - контроллер главной страницы - /.

Представления, более известные как View (вьюшки) - классы, отображающие интерфейс пользователя и передающие в него данные из контроллеров и моделей.

  • templates/ - каталог базовых HTML шаблонов страниц, которые используются всеми остальными представлениями.
  • HTMLView - представление на основе HTML-шаблонов. Подключает необходимый шаблон через переданный при инициализации массив названий шаблонов и путей к их файлам.
  • RESTView - представление для RESTful API на основе JSON-ответов.

Данный файл хочу выделить в отдельный раздел, так как он связывает всё воедино, загружая все зависимости.

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

Наш DIContainer написан таким образом, что может принимать два типа фабрик: классовые и функциональные.

  1. В первом случае фабрикой выступает оператор new, а зависимости загружаются исходя из типов параметров конструктора класса.

    К примеру, если у класса есть аргумент UserRepo $repo в конструкторе, то контейнер вместе с классом загрузит также и UserRepo, передав его в конструктор класса, но для этого в контейнере обязательно должна быть фабрика и для класса UserRepo.

  2. Фабрики в виде функций позволяют реализовать больше функционала. Если в качестве фабрики передана функция, то контейнер передаёт экземпляр себя в качестве аргумента. Через этот аргумент функция может получить доступ к любой зависимости, уже хранящейся в контейнере.

Important

Таким образом, функции являются более гибким вариантом фабрики и позволяют кастомизировать процесс создания экземпляра зависимомсти, к примеру передать в неё заранее подготовленные элементы.

Заключение

На основе данного шаблона вы можете строить свои приложения, дополняя функциональность контроллерами, представлениями и моделями.

Также вы можете добавить свои протоколы и другие компоненты, к примеру для реализации кэширования или интеграции с внешними API.

About

PHP Simple Clean Architecture implemention

Topics

Resources

Stars

Watchers

Forks