Основи Кращі практики 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-додатку контролери зазвичай дуже тонкі і містять лише кілька десятків рядків коду. У той же час, моделі дуже товсті і містять велику частину коду, пов'язану з обробкою даних, оскільки структура даних і бізнес-логіка, які там містяться, зазвичай досить специфічні для конкретного додатка. Логіка контролера, навпаки, досить типова і може бути винесена до базових класів.