Форум программистов, компьютерный форум, киберфорум
PHP: ООП
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
18 / 15 / 3
Регистрация: 04.05.2017
Сообщений: 136

Правильное оформление MVC

14.11.2024, 01:15. Показов 952. Ответов 16

Студворк — интернет-сервис помощи студентам
Добрый вечер, вопрос по оптимальной структуре проекта, в формате MVC с использованием API.
У нас есть постоянно поступающие данные по API на основе которых строится БД.
Есть три типа данных: Пользователь зарегистрировался, пользователь пополнил счет, пользователь совершил покупку и средства списаны
Причем фиксация пользователя происходит во время регистрации, ему создается id, а дальнейшие действия API передает через его id, что в принципе стандартно.
Интерфейс администратора же предполагает регулирование курса валют, возможность ручных воздействий на баланс и прочее(это controller)
Стоит вопрос построения структуры. Какая будет более правильной, в связи с учетом данных поступающих по API:
1. Controller - БД - Model - View
2. Controller - Model - БД - Model - View

То есть по сути вопрос проверки и обработки данных поступающих по API, куда его лучше направить на Model или Controller, как Вы делаете это обычно, интересно услышать мнение

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

Добавлено через 3 минуты
То есть мы принимаем данные на контроллер, проводим там все проверки и даем ответ если ошибки, если все ок, грузим сами в БД, либо это массивом отдаем в модель и просто ждем ответа

Добавлено через 3 минуты
Есть еще третий вариант более сложный, грузит в БД Controller, но проверки проводит Model, в итоге получится Controller - Model - Controller - БД - Model - View
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.11.2024, 01:15
Ответы с готовыми решениями:

MVC - правильное использование наследования
Всім добрий день. Я намагаюсь розібратись з MVC і написати свій "велосипад"(фреймворк) - чисто для досвіду і щоб зрозуміти як це все...

Правильное построение паттерна "MVC"
Здравствуйте, товарищи. Суть темы заключается в том, что нету конкретного понимания некоторых моментов при использовании паттерна MVC....

Правильное оформление CRUD операций
Всем привет. Долгое время писал на фреймворке Yii2 и на работе впринципе никогда не контролировали оформление CRUD операций в...

16
Модератор
 Аватар для long399
2882 / 1836 / 933
Регистрация: 16.10.2013
Сообщений: 5,240
Записей в блоге: 15
14.11.2024, 05:19
Лучший ответ Сообщение было отмечено Кверт как решение

Решение

Цитата Сообщение от Кверт Посмотреть сообщение
То есть по сути вопрос проверки и обработки данных поступающих по API, куда его лучше направить на Model или Controller
Валидацию данных удобно делать в модели. Пусть в модели будет некий метод validate(), который анализирует значения атрибутов и выносит вердикт о валидности. Данный метод вызывается из контроллера:

PHP
1
2
3
4
5
6
7
8
9
// псевдокод
 
// контроллер
$model->load($queryParams);
if ($model->validate() === true) {
    // пишем данные в БД
} else {
    // обрабатываем ситуацию, например, вернем какое-то пояснение пользователю
}
1
18 / 15 / 3
Регистрация: 04.05.2017
Сообщений: 136
14.11.2024, 05:43  [ТС]
То есть и загрузка в БД тогда тоже будет производится в модели, верно? При верной проверке?
Получается контроллер просто массив данных ей отдает, и больше ни за что не отвечает?

Добавлено через 3 минуты
В целом я повторил ответ, просто чтоб убедиться, спасибо большое

А хотя нет, получается все же в БД пишет контроллер, что то я не так понял, то есть проверка у модели а пишет контроллер, понял

Добавлено через 6 минут
Controller - Model - Controller - БД - Model - View получается, я этот вариант как раз и предполагал как самый не оптимальный, но понял сейчас, что он по идее лучше всего и будет работать

Добавлено через 1 минуту
То есть чем меньше модель мы используем в простых так скажем процессах, типа загрузки данных то лучше, в целом логика понятна
0
Модератор
 Аватар для long399
2882 / 1836 / 933
Регистрация: 16.10.2013
Сообщений: 5,240
Записей в блоге: 15
14.11.2024, 05:53
Кверт, правилом хорошего тона является делать тонкие контроллеры. В них не должно быть бизнес-логики какой-то заложено. Только прием данных, передача этих данных в модель, которая уже работает с бизнес-логикой.
Контроллер же отвечает за навигацию в основном.

Цитата Сообщение от Кверт Посмотреть сообщение
Получается контроллер просто массив данных ей отдает, и больше ни за что не отвечает?
Вроде того. Он получил данные и отдает их модели - пускай она с ними разбирается.
Модель эти данные проверяет и она же в БД пишет. Скажем, метод save() будет, который заносит инф-ию в БД.
PHP
1
2
3
4
5
6
7
// контроллер
$model->load($queryParams);
if ($model->validate() === true) {
    $model->save(); // сохраняем в БД валидные данные
} else {
    // обрабатываем ситуацию, например, вернем какое-то пояснение пользователю
}
Т.е. повторю: толстые модели, тонкие контроллеры.
0
18 / 15 / 3
Регистрация: 04.05.2017
Сообщений: 136
14.11.2024, 05:58  [ТС]
PHP
1
2
3
4
5
6
7
8
9
// псевдокод
 
// контроллер
$model->load($queryParams);
if ($model->validate() === true) {
    // пишем данные в БД
} else {
    // обрабатываем ситуацию, например, вернем какое-то пояснение пользователю
}
так вот тут не понял, получается же контроллер пишет в БД по комментарию, я тоже сначала не так понял
0
Модератор
 Аватар для long399
2882 / 1836 / 933
Регистрация: 16.10.2013
Сообщений: 5,240
Записей в блоге: 15
14.11.2024, 06:00
Контроллер инициирует действия с бизнес логикой. Но сами действия выполняются в модели.
0
18 / 15 / 3
Регистрация: 04.05.2017
Сообщений: 136
14.11.2024, 06:01  [ТС]
или под этим комментарием понимается $model->save то есть внутри контролера метод модели вызываем
1
Модератор
 Аватар для long399
2882 / 1836 / 933
Регистрация: 16.10.2013
Сообщений: 5,240
Записей в блоге: 15
14.11.2024, 06:02
Цитата Сообщение от Кверт Посмотреть сообщение
или под этим комментарием понимается $model->save то есть внутри контролера метод модели вызываем
именно так
1
18 / 15 / 3
Регистрация: 04.05.2017
Сообщений: 136
14.11.2024, 06:30  [ТС]
все понял, спасибо большое, я как раз и предполагал тонкую структуру контроллера, а перенос в модель понял как нагрузку на процессы чтоб снизить, поэтому и сомневался как лучше

Добавлено через 25 минут
long399, я Вам личное сообщение отправил еще, не пойму отправилось нет что то лагает, если нет, напишите, мне пожалуйста
0
14.11.2024, 12:02
 Комментарий модератора 
Кверт,
4.6 Обсуждение вопросов - только в теме на форуме. Приглашения к обсуждению еще где-либо (в том числе и с помощью системы личных сообщений) запрещены, за исключением коммерческих разделов.
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
14.11.2024, 17:56
Цитата Сообщение от Кверт Посмотреть сообщение
или под этим комментарием понимается $model->save то есть внутри контролера метод модели вызываем
Если простой CRUD, то можно и так.
Для более сложных вещей выделяют операционный слой.
Операция либо выполняется полностью, либо кидает исключение.
Тогда и валидацию нужно делать не через модель, а отдельный класс.

Это может выглядеть так

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$form = new SignupRequestForm();
 
if (!empty($_POST)) {
    $form->load($_POST);
 
    if ($form->validate()) {
        try {
            $this->service->request($form);
            $_SESSION['success_message'] = 'Вам отправлено письмо';
            return $this->redirect(...);
        } catch (DomainException $e) {
            $_SESSION['error_message'] = $e->getMessage();
        }
    }   
}
 
return $this->render('request', compact('form'));
Если это API:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$form = new SignupRequestForm();
$form->load($_POST);
 
if (!$form->validate()) {
    return new JsonResponse([
        'errors' => $form->errors,
    ], 422);
}
 
try {
    $this->service->request($form);
    return new JsonResponse([
        'message' => 'Вам отправлено письмо'
    ], 200);
} catch (DomainException $e) {
    return new JsonResponse([
        'message' => $e->getMessage()
    ], 409);
}
В api отдача обработка ошибок будет происходить одинаковым образом, поэтому можно перехватывать различные исключения через посредники (middleware), и контроллер упростится

PHP
1
2
3
4
5
6
7
8
9
$form = new SignupRequestForm();
$form->load($_POST);
if (!$form->validate()) {
    throw new ValidateException($form->errors);
}
$this->service->request($form);
return $this->json([
    'message' => 'Вам отправили письмо'
]);
Либо так
PHP
1
2
3
4
5
6
7
$form = new SignupRequestForm();
$form->load($_POST);
$this->validator->validate($form);
$this->service->request($form);
return $this->json([
    'message' => 'Вам отправили письмо'
]);
Т.е. вынести выброс исключения в отдельную службу.
0
Эксперт PHP
3899 / 3237 / 1353
Регистрация: 01.08.2012
Сообщений: 10,904
14.11.2024, 17:58
Цитата Сообщение от Кверт Посмотреть сообщение
Стоит вопрос построения структуры.
А фрейморков, библиотек никаких нет? Всё должно быть самописное?

Цитата Сообщение от Кверт Посмотреть сообщение
Какая будет более правильной, в связи с учетом данных поступающих по API:
Лучше из контроллера вызывать экшн/сервис, который уже выполняет бизнес-логику, чтобы максимально изолировать контроллер.

PHP
1
2
3
4
5
6
7
8
9
10
11
class Controller
{
    public function createUser(Request $request, CreateUserAction $action): void
    {
        $action->execute(
            $request->get('login'),
            $request->get('password'),
            $request->get('email'),
        );
    }
}
Как там дальше происходит валидация, создание юзера и т.п. - контроллер уже не знает. Плюс в переиспользуемости - этот action можно вызвать из любого другого контроллера, команды или сервиса при необходимости.

На всякий напомню, что Model в MVC - это не модель Active Record, а слой бизнес-логики. Экшены/сервисы относятся к Model.

Кстати, в Laravel для валидации используются FormRequest - отдельные классы для валидации прилетевших данных. Можно сделать аналогично:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
class Controller
{
    public function createUser(CreateUserFormRequest $request, CreateUserAction $action): void
    {
        $request->validate(); // Выбросит валидационное исключение с набором пользовательских ошибок, если валидация не прошла 
 
        $action->execute(
            $request->get('login'),
            $request->get('password'),
            $request->get('email'),
        );
    }
}
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
14.11.2024, 18:12
Цитата Сообщение от Jodah Посмотреть сообщение
На всякий напомню, что Model в MVC - это не модель Active Record, а слой бизнес-логики.
Тогда и контроллер это тоже слой. И ему на самом деле известно что валидация происходит через посредника и рефлексию метода.
0
Эксперт PHP
3899 / 3237 / 1353
Регистрация: 01.08.2012
Сообщений: 10,904
14.11.2024, 18:23
Цитата Сообщение от sad67man Посмотреть сообщение
Тогда и контроллер это тоже слой.
Слой чего?

Цитата Сообщение от sad67man Посмотреть сообщение
известно что валидация происходит через посредника
Ему в любом случае что-то будет известно. Хотя, конечно, можно обложиться интерфейсами как велит DIP.

В идеале хотелось бы иметь 2 этапа валидации, на входе в контроллер и в экшен, но на практике (или на проектах, где я работал) на это обычно забивают и оставляют только FormRequest.
0
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
14.11.2024, 18:37
Цитата Сообщение от Jodah Посмотреть сообщение
Слой чего?
Ну MVC - это же слои? M - слой, C - слой, или я что-то не понимаю?)
Вообще есть столько разночтений, что я предпочитаю не пользоваться этой аббревиатурой)

Цитата Сообщение от Jodah Посмотреть сообщение
В идеале хотелось бы иметь 2 этапа валидации, на входе в контроллер и в экшен
Главное не впадать в догматизм.. Часто такое видел, когда для простейших вещей делают 10 слоев, чтоб формально соблюсти некие подходы. Все-таки архитектура должна быть говорящей, простые вещи должны быть просто устроены)

Добавлено через 1 минуту
Цитата Сообщение от Jodah Посмотреть сообщение
В идеале хотелось бы иметь 2 этапа валидации, на входе в контроллер и в экшен
Зачем 2 раза делать валидацию? Или я что-то не понимаю.
0
Эксперт PHP
3899 / 3237 / 1353
Регистрация: 01.08.2012
Сообщений: 10,904
14.11.2024, 19:19
Цитата Сообщение от sad67man Посмотреть сообщение
Ну MVC - это же слои? M - слой, C - слой, или я что-то не понимаю?)
Ну да, контроллер - это слой, который может включать в себя и пхп-шные контроллеры, и консольные команды, и обработчики сообщений из Кафки.

Смысл MVC в том, что каждый слой можно заменить на другую реализацию (php контроллер на консольную команду, html шаблон на xml шаблон), а бизнес-логика может тестироваться изолированно от всего остального. Когда у тебя есть только файлик calculator.php, который и конфиги с композерами подключает, и калькуляции выполняет, и выводит html, трудно протестировать функционал калькулятора в отрыве от всего остального.

Добавлено через 57 секунд
Цитата Сообщение от sad67man Посмотреть сообщение
Зачем 2 раза делать валидацию? Или я что-то не понимаю.
Потому что нет гарантии, что экшен всегда будет вызываться с валидными аргументами.
1
 Аватар для sad67man
2600 / 1504 / 689
Регистрация: 23.08.2015
Сообщений: 3,804
14.11.2024, 20:05
Jodah, Разные фреймворки устроены по разному. Такой способ автоматической валидации через Reuest я видел только в Laravel. Это больше похоже на сахар. И у него так же есть замудренная система передачи заполненных данных и ошибок формы через сессию, чтоб разделить форму и саму операцию на 2 разных экшена.

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

Возникает вопрос, а каковы обязанности контроллера? Где он заканчивается как слой? Относится ли к нему к примеру маршрутизация или проверка прав доступа?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.11.2024, 20:05
Помогаю со студенческими работами здесь

Правильное оформление
Как правильно оформить данный слайдер, учитывая что там должно быть 12 блоков, из которых 4 показывают?(без скрипта) чтобы никто не...

Правильное оформление друж-х ф-й
Добрый вечер! Компилятор ругается на то, что друж-я ф-ция использует private - поля класса. Попробовал положить определение в StdAfx.h, а...

Правильное оформление конфига
Здравствуйте, есть сервер с apache2, на нём примерно 20 поддоменов, оформленных следующим образом: <VirtualHost *:80> ...

Правильное оформление кода
Возникло несколько вопросов по оформлению 1. Важны ли комментарии к коду? 2. Предположим, есть у меня три класса. Выполняют разную...

Правильное оформление стилей в js
Как более правильно менять стили в js, Напрямую (1способ) или через поиск в документе (2способ) ? Как будет грамотней? ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru