Звичайний logout html view. Уявлення log in і log out. Создадаем головну сторінку
Ви можеть бути навіть чули про шаблони проектування і навіть гортали ці прекрасні книги:
- Е. Гамма, Р. Хелм, Р. Джонсон, Дж. Вліссідесс «Прийоми об'єктно орієнтованого проектування. Патерни проектування »;
- М. Фаулер «Архітектура корпоративних програмних додатків».
Представлена \u200b\u200bстаття буде корисна в першу чергу новачкам. У всякому разі, я сподіваюся що за пару годин ви зможете отримати уявлення про реалізацію MVC патерну, який лежить в основі всіх сучасних веб-фреймворків, а також отримати «їжу» для подальших роздумів над тим - «як варто робити». В кінці статті наводиться добірка корисних посилань, які також допоможуть розібратися з чого складаються веб-фреймворки (крім MVC) і як вони працюють.
Пропалені PHP-програмісти навряд чи знайдуть в даній статті щось нове для себе, але їх зауваження і коментарі до основного тексту були б дуже до речі! Оскільки без теорії практика неможлива, а без практики теорія марна, то спочатку буде трохи теорії, а потім перейдемо до практики. Якщо ви вже знайомі з концепцією MVC, можете пропустити розділ з теорією і відразу перейти до практики.
1. Теорія
Шаблон MVC описує простий спосіб побудови структури додатка, метою якого є відділення бізнес-логіки від призначеного для користувача інтерфейсу. В результаті, додаток легше масштабується, тестується, супроводжується і звичайно ж реалізується.Розглянемо концептуальну схему шаблону MVC (на мій погляд - це найбільш вдала схема з тих, що я бачив):
В архітектурі MVC модель надає дані і правила бізнес-логіки, уявлення відповідає за користувальницький інтерфейс, а контролер забезпечує взаємодію між моделлю і представленням.
Типову послідовність роботи MVC-додатки можна описати таким чином:
- При заході користувача на веб-ресурс, скрипт ініціалізації створює екземпляр додатку і запускає його на виконання.
При цьому відображається вид, скажімо головної сторінки сайту. - Додаток отримує запит від користувача і визначає запитані контролер і дію. У разі головної сторінки, виконується дія за замовчуванням ( index).
- Додаток створює екземпляр контролера і запускає метод дії,
в якому, наприклад, міститися виклики моделі, що зчитують інформацію з бази даних. - Після цього, дія формує уявлення з даними, отриманими з моделі і виводить результат користувачеві.
Модель не повинна безпосередньо взаємодіяти з користувачем. Всі змінні, що відносяться до запиту користувача повинні оброблятися в контролері.
Модель не повинна генерувати HTML або інший код відображення, який може змінюватися в залежності від потреб користувача. Такий код повинен оброблятися в видах.
Одна і та ж модель, наприклад: модель аутентифікації користувачів може використовуватися як в призначеній для користувача, так і в адміністративній частині програми. В такому випадку можна винести загальний код в окремий клас і успадковуватися від нього, визначаючи в спадкоємців специфічні для подпріложеній методи.
вид - використовується для завдання зовнішнього відображення даних, отриманих з контролера і моделі.
Види Cодержат HTML-розмітку і невеликі вставки PHP-коду для обходу, форматування і відображення даних.
Чи не повинні безпосередньо звертатися до бази даних. Цим повинні займатися моделі.
Чи не повинні працювати з даними, отриманими із запиту користувача. Це завдання має виконувати контролер.
Може безпосередньо звертатися до властивостей і методів контролера або моделей, для отримання готових до висновку даних.
Види зазвичай поділяють на загальний шаблон, що містить розмітку, загальну для всіх сторінок (наприклад, шапку і підвал) і частини шаблону, які використовують для відображення даних, що виводяться з моделі або відображення форм введення даних.
контролер - сполучна ланка, що з'єднує моделі, види і інші компоненти в робоче додаток. Контролер відповідає за обробку запитів користувача. Контролер не повинен містити SQL-запитів. Їх краще тримати в моделях. Контролер не повинен містити HTML і інший розмітки. Її варто виносити в види.
У добре спроектованому MVC-додатку контролери зазвичай дуже тонкі і містять тільки кілька десятків рядків коду. Чого, не скажеш про Stupid Fat Controllers (SFC) в CMS Joomla. Логіка контролера досить типова і велика її частина виноситься в базові класи.
Моделі, навпаки, дуже товсті і містять велику частину коду, пов'язану з обробкою даних, тому що структура даних і бізнес-логіка, що міститься в них, зазвичай досить специфічна для конкретного додатка.
1.1. Front Controller і Page Controller
У більшості випадків, взаємодія користувача з web-додатком проходить за допомогою переходів по посиланнях. Подивіться зараз на адресний рядок браузера - за цим посиланням ви отримали цей текст. За іншими посиланнями, наприклад, що знаходяться праворуч на цій сторінці, ви отримаєте інший вміст. Таким чином, посилання представляє конкретну команду web-додатком.Сподіваюся, ви вже встигли помітити, що у різних сайтів можуть бути вчинені різні формати побудови адресного рядка. Кожен формат може відображати архітектуру web-додатки. Хоча це і не завжди так, але в більшості випадків це явний факт.
Розглянемо два варіанти адресного рядка, за якими показується якийсь текст і профіль користувача.
Перший варіант:
- www.example.com/article.php?id\u003d3
- www.example.com/user.php?id\u003d4
Другий варіант:
- www.example.com/index.php?article\u003d3
- www.example.com/index.php?user\u003d4
Підхід з безліччю точок взаємодії ви можете спостерігати на форумах з движком phpBB. Перегляд форуму відбувається через сценарій viewforum.php, Перегляд топіка через viewtopic.php і т.д. Другий підхід, з доступом через один фізичний файл сценарію, можна спостерігати в моїй улюбленій CMS MODX, де всі звернення проходять через index.php.
Ці два підходи абсолютно різні. Перший - характерний для шаблону контролер сторінок (Page Controller), а другий підхід реалізується патерном контролер запитів (Front Controller). Контролер сторінок добре застосовувати для сайтів з досить простою логікою. У свою чергу, контролер запитів об'єднує всі дії з обробки запитів в одному місці, що дає йому додаткові можливості, завдяки яким можна реалізувати більш складні завдання, ніж зазвичай вирішуються контролером сторінок. Я не буду вдаватися в подробиці реалізації контролера сторінок, а скажу лише, що в практичній частині буде розроблений саме контролер запитів (щось подібне до).
1.2. маршрутизація URL
Маршрутизація URL дозволяє настроїти програму на прийом запитів з URL, які не відповідають реальним файлів програми, а також використовувати ЧПУ, які семантично значимі для користувачів і переважні для пошукової оптимізації.Наприклад, для звичайної сторінки, що відображає форму зворотного зв'язку, URL міг би виглядати так:
http://www.example.com/contacts.php?action\u003dfeedback
Приблизний код обробки в такому випадку:
switch ($ _GET [ "action"]) (case "about": require_once ( "about.php"); // сторінка "Про Нас" break; case "contacts": require_once ( "contacts.php"); // сторінка "Контакти" break; case "feedback": require_once ( "feedback.php"); // сторінка "Зворотній зв'язок" break; default: require_once ( "page404.php"); // сторінка "404" break; )
Думаю, багато хто так раніше робили.
З використанням движка маршрутизації URL ви зможете для відображення тієї ж інформації налаштувати додаток на прийом таких запитів:
http://www.example.com/contacts/feedback
Тут contacts є контролер, а feedback - це метод контролера contacts, що відображає форму зворотного зв'язку і т.д. Ми ще повернемося до цього питання в практичній частині.
Також варто знати, що маршрутизатори багатьох веб-фреймворків дозволяють створювати довільні маршрути URL (вказати, що означає кожна частина URL) і правила їх обробки.
Тепер ми володіємо достатніми теоретичними знаннями, щоб перейти до практики.
2. Практика
Для початку створимо таку структуру файлів і папок:Забігаючи вперед, скажу, що в папці core будуть зберігатися базові класи Model, View і Controller.
Їхні нащадки будуть зберігатися в директоріях controllers, models і views. файл index.php це точка в ходу в додаток. файл bootstrap.php ініціює завантаження програми, підключаючи всі необхідні модулі та ін.
Будемо йти послідовно; відкриємо файл index.php і наповнимо його наступним кодом:
ini_set ( "display_errors", 1); require_once "application / bootstrap.php";
Тут питань виникнути не повинно.
Слідом, відразу ж перейдемо до фалу bootstrap.php:
require_once "core / model.php"; require_once "core / view.php"; require_once "core / controller.php"; require_once "core / route.php"; Route :: start (); // запускаємо маршрутизатор
Перші три рядки будуть підключати поки що неіснуючі файли ядра. Останні рядки підключають файл з класом маршрутизатора і запускають його на виконання викликом статичного методу start.
2.1. Реалізація маршрутизатора URL
Поки що відхилимося від реалізації паттерна MVC і займемося мрашрутізаціей. Перший ш аг, який нам потрібно зробити, записати наступний код в .htaccess:RewriteEngine On RewriteCond% (REQUEST_FILENAME)! -F RewriteCond% (REQUEST_FILENAME)! -D RewriteRule. * Index.php [L]
Цей код перенаправить обробку всіх сторінок на index.php, Що нам і потрібно. Пам'ятайте в першій частині ми говорили про Front Controller ?!
Маршрутизацію ми помістимо в окремий файл route.php в директорію core. У цьому файлі опишемо клас Route, який буде запускати методи контролерів, які в свою чергу будуть генерувати вигляд сторінок.
Вміст файлу route.php
class Route ( static function start () ( // контролер і дію за замовчуванням $ Controller_name \u003d "Main"; $ Action_name \u003d "index"; $ Routes \u003d explode ( "/", $ _SERVER [ "REQUEST_URI"]); // отримуємо ім'я контролера if (! empty ($ routes)) ($ controller_name \u003d $ routes;) // отримуємо ім'я екшену if (! empty ($ routes)) ($ action_name \u003d $ routes;) // додаємо префікси $ Model_name \u003d "Model_". $ Controller_name; $ Controller_name \u003d "Controller_". $ Controller_name; $ Action_name \u003d "action_". $ Action_name; // підчіплюємо файл з класом моделі (файлу моделі може і не бути) $ Model_file \u003d strtolower ($ model_name). ". Php"; $ Model_path \u003d "application / models /". $ Model_file; if (file_exists ($ model_path)) (include "application / models /". $ model_file;) // підчіплюємо файл з класом контролера $ Controller_file \u003d strtolower ($ controller_name). ". Php"; $ Controller_path \u003d "application / controllers /". $ Controller_file; if (file_exists ($ controller_path)) (include "application / controllers /". $ controller_file;) else ( / * Правильно було б кинути тут виняток, але для спрощення відразу зробимо редирект на сторінку 404 * / Route :: ErrorPage404 (); ) // створюємо контролер $ Controller \u003d new $ controller_name; $ Action \u003d $ action_name; if (method_exists ($ controller, $ action)) ( // викликаємо дію контролера $ Controller -\u003e $ action (); ) Else ( // тут також розумніше було б кинути виняток Route :: ErrorPage404 (); )) function ErrorPage404 () ( $ Host \u003d "http: //". $ _ SERVER [ "HTTP_HOST"]. "/"; header ( "HTTP / 1.1 404 Not Found"); header ( "Status: 404 Not Found"); header ( "Location:". $ host. "404"); ))
Зауважу, що в класі реалізована дуже спрощена логіка (незважаючи на об'ємний код) і можливо навіть має проблеми безпеки. Це було зроблено навмисно, тому що написання повноцінного класу маршрутизації заслуговує як мінімум окремої статті. Розглянемо основні моменти ...
В елементі глобального масиву $ _SERVER [ "REQUEST_URI"] міститься повна адреса за яким звернувся користувач.
Наприклад: example.ru/contacts/feedback
За допомогою функції explode проводиться поділ адреси на составлющіе. В результаті ми отримуємо ім'я контролера, для наведеного прикладу, це контролер contacts і ім'я дії, в нашому випадку - feedback.
Далі підключається файл моделі (модель може бути відсутнім) і файл контролера, якщо такі є і нарешті, створюється екземпляр контролера і викликається дію, знову ж таки, якщо воно було описано в класі контролера.
Таким чином, при переході, наприклад, за адресою:
example.com/portfolio
або
example.com/portfolio/index
роутер виконає такі завдання:
- підключить файл model_portfolio.php з папки models, що містить клас Model_Portfolio;
- підключить файл controller_portfolio.php з папки controllers, що містить клас Controller_Portfolio;
- створить екземпляр класу Controller_Portfolio і викличе дію за замовчуванням - action_index, описане в ньому.
example.com/ufo
то його перекине на сторінку «404»:
example.com/404
Те ж саме відбудеться якщо користувач звернеться до дії, яке не описано в контролері.
2.2. Повертаємося до реалізації MVC
Перейдемо в папку core і додамо до файлу route.php ще три файли: model.php, view.php і controller.phpНагадаю, що вони будуть містити базові класи, до написання яких ми зараз і приступимо.
вміст файлу model.php
class Model ( public function get_data () (
}
}
Клас моделі містить єдиний порожній метод вибірки даних, який буде перекриватися в класах нащадках. Коли ми будемо створювати класи нащадки все стане зрозуміліше.
вміст файлу view.php
class View (
// public $ template_view; // тут можна вказати загальний вигляд за замовчуванням.
function generate ( $ Content_view, $ template_view, $ data \u003d null)
{
/ * If (is_array ($ data)) (// перетворимо елементи масиву в змінні extract ($ data);) * / include "application / views /". $ template_view; ))
Не важко здогадатися, що метод generate призначений для формування образу. У нього передаються такі параметри:
- $ Content_file - види відображають контент сторінок;
- $ Template_file - загальний для всіх сторінок шаблон;
- $ Data - масив, що містить елементи контенту сторінки. Звичайно заповнюється в моделі.
для відображення контенту конкретної сторінки.
У нашому випадку загальний шаблон буде містити header, menu, sidebar і footer, а контент сторінок буде міститися в окремому вигляді. Знову ж це зроблено для спрощення.
вміст файлу controller.php
class Controller ( public $ model; public $ view; function __construct () ( $ This -\u003e view \u003d new View (); )))
метод action_index - це дія, що викликається за замовчуванням, його ми перекриємо при реалізації класів нащадків.
2.3. Реалізація класів нащадків Model і Controller, створення View "s
Тепер починається найцікавіше! Наш сайт-візитка буде складатися з следущих сторінок:- Головна
- послуги
- Портфоліо
- Контакти
- А також - сторінка «404»
На попередньому малюнку окремо виділений файл template_view.php - це шаблон, який містить загальну для всіх сторінок розмітку. У найпростішому випадку він міг би виглядати так:
<html lang \u003d "ru"\u003e
<head\u003e
<meta charset \u003d "utf- 8"\u003e <title\u003eГоловнаtitle\u003e
head\u003e
<body\u003e
$ Content_view; ?\u003e body\u003e
html\u003e
Для додання сайту презентабельного вигляду зверстаємо CSS шаблон і інтегріріруем його в наш сайт шляхом зміни структури HTML-розмітки і підключення CSS і JavaScript файлів:
<link rel \u003d "stylesheet" type \u003d "text / css" href \u003d "/ css / style.css" /\u003e
<script src \u003d "/ js / jquery-1.6.2.js" type \u003d "text / javascript"\u003escript\u003e
В кінці статті, в розділі «Результат», наводиться посилання на GitHub-репозиторій з проектом, в якому виконані дії по інтеграції простенького шаблону.
2.3.1. Создадаем головну сторінку
Почнемо з контролера controller_main.php, Ось його код:class Controller_Main extends Controller ( function action_index () ( $ This -\u003e view-\u003e generate ( "main_view.php", "template_view.php"); ))
У метод generate примірника класу View передаються імена файлів загального шаблону і виду c контентом сторінки.
Крім індексного дії в контролері звичайно ж можуть міститися і інші дії.
Файл із загальним видом ми розглянули раніше. Розглянемо файл контенту main_view.php:
<h1\u003eЛаскаво просимо!h1\u003e
<p\u003e
<img src \u003d "/ images / office-small.jpg" align \u003d "left"\u003e
<a href \u003d "/"\u003eОЛОЛОША TEAMa\u003e - команда першокласних фахівців в області розробки веб-сайтів з багаторічним досвідом колекціонування мексиканських масок, бронзові і кам'яні статуї з Індії та Цейлону, барельєфів і статуй, створених майстрами Екваторіальної Африки п'ять-шість століть тому ...p\u003e
Тут міститься проста розмітка без будь-яких PHP-викликів.
Для відображення головної сторінки можна скористатися одним з наступних адрес:
- методи бібліотек, що реалізують абстракіцю даних. Наприклад, методи бібліотеки PEAR MDB2;
- методи ORM;
- методи для роботи з NoSQL;
- та ін. Для простоти, тут ми не будемо використовувати SQL-запити або ORM-оператори. Замість цього ми семуліруем реальні дані і відразу повернемо масив результатів.
- Controller_Login в якому генерується вид з формою для введення логіна і пароля, після заповнення якої виробляється процедура аутентифікації і в разі успіху користувач перенаправляється в адмінку.
- Contorller_Admin з індексним дією, в якому перевіряється був чи користувач раніше авторизований на сайті як адміністратор (якщо був, то відображається вид адмінки) і дією logout для разлогініванія.
- spring-security-web 4.2.3.RELEASE: spring-security-web.
- spring-security-config 4.2.3.RELEASE: spring-security-config.
- spring-webmvc 4.3.9.RELEASE: Spring Web MVC.
- javax.servlet-api 3.1.0 Java Servlet API
- JDK 1.8
- Maven 3.3.9
- LOGIN_REDIRECT_URL: Повідомляє про те, на який URL-адресу перенаправляти користувача після входу в систему.
- LOGIN_URL : URL-адресу для перенаправлення користувача на вхід (наприклад, за допомогою декоратора login_required)
- LOGOUT_URL : URL-адресу для перенаправлення користувача на вихід
- , Щоб виділити поточний розділ в меню за допомогою CSS. Також відображається ім'я користувача і посилання для виходу в систему, якщо користувач пройшов аутентифікацію, або посилання для входу в систему.
Відкрийте в браузері http://127.0.0.1:8000/account/login/. Ви повинні побачити стрініцу входу. Введіть валідний логін і пароль. Ви побачите наступне:
Можна побачити, що розділ My dashboard виділений за допомогою CSS, так як він має class selected. Оскільки користувач пройшов аутентифікацію, ім'я користувача відображається в правій частині header-а. клацніть посилання Logout. Ви побачите наступну сторінку:
На цій сторінці можна побачити, що користувач вийшов із системи, і тому більше не відображається меню веб-сайту. Посилання в правій стороні хедера показує тепер Log-in.
Якщо ви бачите сторінку log out з сайту адміністрування Джанго, а не власну сторінку виходу з системи, перевірте настройки INSTALLED_APPS і переконайтеся, що django.contrib.admin знаходиться після account. Обидва шаблону знаходяться в тому ж відносному шляху, і завантажувач шаблону Джанго буде використовувати перший знайдений.
Django comes with a lot of built-in resources for the most common use cases of a Web application. The registration app is a very good example and a good thing about it is that the features can be used out-of-the-box.
With the Django registration app you can take advantages of the following features:
- Login
- Logout
- Sign up
- Password reset
In this tutorial we will focus in the Login and Logout features. For sign up and password reset, check the tutorials below:
Getting started
Before we start, make sure you have django.contrib.auth in your INSTALLED_APPS and the authentication middleware properly configured in the MIDDLEWARE_CLASSES settings.
Both come already configured when you start a new Django project using the command startproject. So if you did not remove the initial configurations you should be all set up.
In case you are starting a new project just to follow this tutorial, create a user using the command line just so we can test the login and logout pages.
$ Python manage.py createsuperuserIn the end of this article I will provide the source code of the example with the minimal configuration.
Configure the URL routes
First import the django.contrib.auth.views module and add a URL route for the login and logout views:
from django.conf.urls import url from django.contrib import admin from django.contrib.auth import views as auth_views urlpatterns \u003d [url (r "^ login / $", auth_views. login, name \u003d "login"), url ( r "^ logout / $", auth_views. logout, name \u003d "logout"), url (r "^ admin /", admin. site. urls),]Create a login template
By default, the django.contrib.auth.views.login view will try to render the registration / login.html template. So the basic configuration would be creating a folder named registration and place a login.html template inside.
Following a minimal login template:
(% Extends "base.html"%) (% block title%) Login (% endblock%) (% block content%)
Login
(% Endblock%)This simple example already validates username and password and authenticate correctly the user.
Customizing the login view
There are a few parameters you can pass to the login view to make it fit your project. For example, if you want to store your login template somewhere else than registration / login.html you can pass the template name as a parameter:
url (r "^ login / $", auth_views. login, ( "template_name": "core / login.html"), name \u003d "login"),You can also pass a custom authentication form using the parameter authentication_form, incase you have implemented a custom user model.
Now, a very important configuration is done in the settings.py file, which is the URL Django will redirect the user after a successful authentication.
Inside the settings.py file add:
LOGIN_REDIRECT_URL \u003d "home"The value can be a hardcoded URL or a URL name. The default value for LOGIN_REDIRECT_URL is / accounts / profile /.
It is also important to note that Django will try to redirect the user to the next GET param.
Setting up logout view
After acessing the django.contrib.auth.views.logout view, Django will render the registration / logged_out.html template. In a similar way as we did in the login view, you can pass a different template like so:
url (r "^ logout / $", auth_views. logout, ( "template_name": "logged_out.html"), name \u003d "logout"),Usually I prefer to use the next_page parameter and redirect either to the homepage of my project or to the login page when it makes sense.
файл моделі model_portfolio.php помістимо в папку models. Ось його зміст:
class Model_Portfolio extends Model ( public function get_data () ( return array (array ( "Year" \u003d\u003e "2012", "Site" \u003d\u003e "http://DunkelBeer.ru", "Description" \u003d\u003e "Промо-сайт темного пива Dunkel від німецького виробника Löwenbraü випускається в Росії пивоварною компанією" CАН ІнБев "."), Array ( "Year" \u003d\u003e "2012", "Site" \u003d\u003e "http://ZopoMobile.ru", "Description" \u003d\u003e "Російськомовний каталог китайських телефонів компанії Zopo на базі Android OS і аксесуарів до них."), // todo); ))
Клас контролера моделі міститься в файлі controller_portfolio.php, Ось його код:
class Controller_Portfolio extends Controller (
function __construct () ( $ This -\u003e model \u003d new Model_Portfolio (); $ This -\u003e view \u003d new View (); ) function action_index () ( $ Data \u003d $ this -\u003e model-\u003e get_data (); $ This -\u003e view-\u003e generate ( "portfolio_view.php", "template_view.php", $ data); ))
У змінну data записується масив, що повертається методом get_data, Який ми розглядали раніше.
Далі ця змінна передається як параметр методу generate, В який також передаються: ім'я файлу з загальним шаблон і ім'я файлу, що містить вид c контентом сторінки.
Вид містить контент сторінки знаходиться в файлі portfolio_view.php.
Портфоліо
рік | проект | опис | ". $ Row [" Year "]." | ". $ Row [" Site "]." | ". $ Row [" Description "]." | " ; }