Ответ
Да, применял паттерн Model-View-Presenter (MVP) в веб-приложениях на PHP, особенно в тех случаях, где требовалось четкое разделение логики отображения и бизнес-логики для улучшения тестируемости.
Ключевое отличие от MVC: В классическом MVC View часто "знает" о Model и может напрямую запрашивать данные. В MVP View пассивна — она только отображает то, что ей передает Presenter, и делегирует ему все события пользователя.
Пример реализации простого модуля аутентификации:
// Model (Домен + Логика данных)
class AuthModel {
private UserRepository $userRepository;
public function authenticate(string $email, string $password): ?User {
$user = $this->userRepository->findByEmail($email);
if ($user && password_verify($password, $user->getPasswordHash())) {
return $user;
}
return null;
}
}
// View (Интерфейс, реализуется шаблоном)
interface AuthView {
public function showLoginForm(array $data = []): void;
public function showError(string $message): void;
public function redirectToDashboard(User $user): void;
}
// Presenter (Посредник, содержит логику отображения)
class AuthPresenter {
private AuthModel $model;
private AuthView $view;
public function __construct(AuthModel $model, AuthView $view) {
$this->model = $model;
$this->view = $view;
}
public function showLogin(): void {
$this->view->showLoginForm();
}
public function handleLogin(Request $request): void {
$email = $request->get('email');
$password = $request->get('password');
if (empty($email) || empty($password)) {
$this->view->showError('Все поля обязательны');
return;
}
$user = $this->model->authenticate($email, $password);
if ($user) {
$this->view->redirectToDashboard($user);
} else {
$this->view->showError('Неверные учетные данные');
}
}
}
// Реализация View (например, в шаблоне Twig или Blade)
class TwigAuthView implements AuthView {
private Environment $twig;
private Response $response;
public function showLoginForm(array $data = []): void {
$this->response->setContent($this->twig->render('login.html.twig', $data));
}
// ... остальные методы
}
Где это было полезно:
- В сложных административных панелях, где много интерактивных форм и валидации. Presenter обрабатывал всю логику UI, что делало его идеальным для модульного тестирования.
- При интеграции PHP-бэкенда с различными фронтендами (например, REST API для мобильного приложения и HTML для веба). Можно было создать два разных View-адаптера для одного Presenter'а.
Основной плюс: Presenter, содержащий всю логику отображения и обработки ввода, становится очень удобным для unit-тестирования без необходимости рендеринга HTML.
Ответ 18+ 🔞
А, MVP, говоришь? Ну да, применял, конечно. Это ж классика, ёпта. Особенно когда проект начинает разрастаться, как опухоль, и в твоём контроллере уже не бизнес-логика, а пиздопроебина полная — вот тут и вспоминаешь про чёткое разделение обязанностей.
Смотри, в чём главный прикол, чтобы не охуеть сразу. В том же MVC вьюха частенько лезет в модель сама, как голодный в холодильник ночью. А в MVP — нет, блядь. Вьюха тут — пассивная мартышлюшка. Она просто показывает то, что ей Presenter суёт, и скулит ему: «Чувак, на меня тут кликнули, сделай чё-нить!» Всё. Больше она нихуя не умеет.
Вот смотри на примере простой авторизации, чтоб понятно было. Код не трогаю, он правильный.
// Model (Тут твоя бизнес-логика, данные, работа с БД)
class AuthModel {
private UserRepository $userRepository;
public function authenticate(string $email, string $password): ?User {
$user = $this->userRepository->findByEmail($email);
if ($user && password_verify($password, $user->getPasswordHash())) {
return $user;
}
return null;
}
}
// View (Это просто интерфейс, контракт. Говорит: "Я умею показывать форму, ошибку и редиректить")
interface AuthView {
public function showLoginForm(array $data = []): void;
public function showError(string $message): void;
public function redirectToDashboard(User $user): void;
}
// Presenter (А вот это — мозги операции! Сюда стекаются все события и тут вся логика отображения)
class AuthPresenter {
private AuthModel $model;
private AuthView $view;
public function __construct(AuthModel $model, AuthView $view) {
$this->model = $model;
$this->view = $view;
}
public function showLogin(): void {
$this->view->showLoginForm();
}
public function handleLogin(Request $request): void {
$email = $request->get('email');
$password = $request->get('password');
// Валидация — это уже логика презентера, а не модели
if (empty($email) || empty($password)) {
$this->view->showError('Все поля обязательны');
return; // И нахуй отсюда
}
// Модель делает только своё дело — аутентифицирует
$user = $this->model->authenticate($email, $password);
if ($user) {
$this->view->redirectToDashboard($user);
} else {
$this->view->showError('Неверные учетные данные');
}
}
}
// А это уже реализация вьюхи, например, на Twig
class TwigAuthView implements AuthView {
private Environment $twig;
private Response $response;
public function showLoginForm(array $data = []): void {
$this->response->setContent($this->twig->render('login.html.twig', $data));
}
// ... остальное
}
Где эта штука реально выручала? Ну, например, в этих ебуч