Основи Кращі практики MVC, Повний посібник з Yii 1

Незважаючи на те, що з концепцією MVC знайомий практично кожен веб-розробник, її застосування в реальних проектах часто викликає труднощі. Головна ідея MVC -повторне використання коду та поділ проблем. У цьому розділі будуть описані загальні принципи, які допоможуть дотримуватися MVC у вашому додатку.

Припустимо, що веб-додаток складається з декількох підпрограм, таких як:

  • front end: частина сайту, яку бачать звичайні користувачі;
  • back end: адміністративна частина сайту, що дозволяє керувати програмою. Доступ до неї зазвичай обмежений;
  • консоль: додаток, який складається з набору консольних команд, що запускаються у вікні терміналу вручну або за розкладом;
  • API: надає стороннім програмам інтерфейси для інтеграції з вашим додатком.

Підпрограми можуть бути реалізовані у вигляді модулів або як додаток, що містить код, загальний для кількох підпрограм.

Моделі представляють внутрішню структуру даних програми. Вони часто є спільними для кількох підпрограм. Наприклад, модель LoginForm може бути використана як в користувача, так і в адміністративній частині програми. Модель News може використовуватися консольними командами, API та front/back частинами програми. Тому моделі

повинні містити властивості, які мають конкретні дані;

повинні включати бізнес-логіку (наприклад, правила валідації), щоб переконатися в тому, що дані відповідають пред'явленим вимогам;

можуть містити код для роботи з даними. Наприклад, модель SearchForm, крім зберігання пошукових даних, може містити спосіб search, який цей пошук здійснює.

Іноді дотримання останнього правила робить модельдуже товстої, тобто містить багато коду в одному класі. Це може призвести до труднощів підтримки коду, якщо модель використовується для виконання різних завдань. Наприклад, модель News може містити метод getLatestNews , який використовується тільки частиною користувача і метод getDeletedNews , який використовується тільки адміністративною частиною. Для невеликих та середніх програм це допустимо. Для великих додатків з метою спрощення подальшої підтримки коду можна зробити наступне:

Створити модель NewsBase , що містить лише код, загальний для додатків (користувача та адміністративної частин).

У кожному підпрограмі створити модель News , що успадковується від NewsBase і визначити в ній специфічні для підпрограми методи.

Таким чином, якщо застосувати це до розглянутого вище прикладу, необхідно додати модель News з методом getLatestNews в частину користувача і ще одну модель News з методом getDeletedNews в адміністративну частину.

У загальному випадку моделі не повинні безпосередньо взаємодіяти з користувачем. Тобто:

не повинні використовувати $_GET , $_POST або інші подібні змінні, які безпосередньо отримуються з запиту користувача, оскільки моделі можуть використовуватися в інших підпрограмах (наприклад, у модульних тестах або API), в яких ці змінні недоступні. Усі змінні, які стосуються запиту користувача, мають оброблятися у контролері;

не повинні генерувати HTML або інший код подання, оскільки він може змінюватися в залежності від потреб користувача (тобто, частина користувача та адміністративна частина можуть показувати новини в абсолютно різному форматі). Такий код має генеруватися в уявленнях.

2. Подання ¶

Подання відповідають за відображення моделей у потрібному форматі користувача. У випадку подання

повинні, головним чином, містити розмітку, таку як HTML, і простий PHP код, що використовується для обходу, форматування та відображення даних;

не повинні безпосередньо звертатися до бази даних. Цим мають займатися моделі;

не повинні безпосередньо звертатися до $_GET , $_POST та інших змінних, які отримуються із запиту користувача. Це завдання має виконувати контролер. Подання повинні використовуватися лише для оформлення даних, отриманих від контролера та моделі;

можуть безпосередньо звертатися до властивостей та методів контролера чи моделей. Однак це має робитися лише з метою відображення даних.

Подання можна використовувати повторно кількома способами:

Загальний шаблон: можна винести розмітку, загальну для всіх сторінок. Наприклад, шапку та підвал.

Частини шаблону: використовуються всередині інших шаблонів і зазвичай не використовуються із загальним шаблоном. Наприклад, частину шаблону _form.php можна використовувати для відображення форми введення моделі, яка буде використовуватися як під час її створення, так і при редагуванні.

Віджети: використовуються в тому випадку, коли частина шаблону включає занадто багато логіки. При цьому логіка переноситься до класу віджету. Віджет, що генерує велику кількість розмітки, може використовувати шаблони уявлень.

Хелпери (помічники): у шаблонах часто потрібно виконувати невеликі завдання, такі як форматування даних або генерація HTML-тегів. Замість того, щоб вставляти код безпосередньо в шаблони, можна помістити його в клас-хелпер і використовувати цей клас у шаблонах. Приклад такого підходу можна знайти в класі CHtml, який допомагає часто генерувативикористовується HTML код. Для того, щоб уникнути явного підключення класів, хелпери можна розмістити в окремій директорії, яка вказана в import.

3. Контролер ¶

Контролери — зв'язуюча ланка, що з'єднує моделі, уявлення та інші компоненти робочого додатку. Контролер відповідає за обробку запитів користувача. Тому контролер

може звертатися до $_GET , $_POST та інших змінних PHP, одержуваних із запиту користувача;

може створювати екземпляри моделей та керувати ними. Наприклад, у типовій дії оновлення моделі контролер може спочатку створити екземпляр моделі, потім заповнити його даними з $_POST і, у разі успішного збереження моделі, перенаправити браузер користувача на сторінку створеної моделі. Слід зазначити, що саме збереження моделі має бути реалізовано у класі моделі, а чи не в контролері;

не повинен містити запити SQL. Їх краще тримати у моделях;

не повинен містити HTML та іншу розмітку. Її варто винести на уявлення.

У добре спроектованому MVC-додатку контролери зазвичай дуже тонкі і містять лише кілька десятків рядків коду. У той же час, моделі дуже товсті і містять велику частину коду, пов'язану з обробкою даних, оскільки структура даних і бізнес-логіка, які там містяться, зазвичай досить специфічні для конкретного додатка. Логіка контролера, навпаки, досить типова і може бути винесена до базових класів.