Базовый контроллер и его методы
На прошлом занятии мы набросали основу нашего ядра, а сегодня нам предстоит воспользоваться преимуществами ООП и написать базовый контроллер, от которого будут наследоваться все остальные.
Зачем это нужно? Да, хотя бы, затем, чтобы не прописывать одни и те же методы в каждом контроллере. Написать один общий, а потом менять только нужные части. Это гораздо правильнее и удобнее.
К тому же, чем меньше дублируется кода, тем больше гарантий, что этот код работает всегда одинаково. Отсюда следует простой вывод, что дублирования кода быть вообще не должно. Если вы в двух местах пишете один и тот же метод - у вас проблема с логикой работы приложения.
Итак, приступаем.
Базовый контроллер
Создаём новый файл Controller.php рядом c Core.php:
<?php
class Controller {
/** @var Core $core */
public $core;
/**
* Конструктор класса, требует передачи Core
*
* @param Core $core
*/
function __construct(Core $core) {
$this->core = $core;
}
/**
* Основной рабочий метод
*
* @return string
*/
public function run() {
return "Hello World!";
}
}
Как видите, это пока точная копия контроллеров из прошлого занятия. Фокус в том, что им теперь эти методы не нужны. Переписываем их так:
<?php
if (!class_exists('Controller')) {
require_once dirname(dirname(__FILE__)) . '/Controller.php';
}
class Controllers_Test extends Controller {
/**
* Основной рабочий метод
*
* @return string
*/
public function run() {
return "Мы выводим страницу <b>Test<b>";
}
}
Вначале идёт проверка наличия класса базового контроллера и, если его нет, подключение из директории выше. Дальше мы объявляем свой класс с добавлением специальной конструкции extends, что говорит PHP о расширении Controller. И с этого момента наш рабочий контроллер наследует базовый.
Так что мы убираем у него свойство $core и метод __construct(), потому что они уже прописаны в родителе. Однако оставляем метод run(), потому что именно им и будут отличаться наследники Controller.
Логика понятна? Есть родитель и есть потомки, которые обладают всеми качествами родителя и могут любые из них менять. Конечно, если только те не объявлены как private.
Код сейчас выглядит вот так. Теперь мы можем добавить какие-то общие методы в Controller.php.
Базовые методы контроллера
Во-первых, нам нужен метод инициализации, чтобы определять, будет ли вообще работать наш контроллер при переданных параметрах. Например, он будет проверять запрошенный URL, и есть тот не заканчивается на / - делать редирект на верный адрес.
Да, редирект это наше во-вторых. Меняем Controller.php
public function initialize(array $params = array()) {
return true;
}
public function redirect($url = '/') {
header("Location: {$url}");
exit();
}
Просто пока голые методы. Теперь запуск initialize() у каждого контроллера нужно прописать в Core::handleRequest():
// Имена контроллеров у нас с большой буквы
$name = ucfirst(array_shift($request));
// ...
// И запускаем
$controller = new $class($this);
$initialize = $controller->initialize($request);
if ($initialize === true) {
$response = $controller->run();
}
elseif (is_string($initialize)) {
$response = $initialize;
}
else {
$response = 'Возникла неведомая ошибка при загрузке страницы';
}
echo $response;
Видите? У каждого контроллера будет запущен, в первую очередь, метод initialize() и в зависимости от того, что он вернёт, дальше или запускается run(), или выводится ошибка. Причем, контроллер может сам вернуть текст ошибки.
Ну а теперь нам осталось только расширить initialize в методе Controllers_Test:
public function initialize(array $params = array()) {
if (empty($params)) {
$this->redirect('/test/');
}
return true;
}
Мы проверяем массив $params, который нам передаёт Core. Причем, выше я немного изменил его обработку в handleRequest(), чтобы первая часть url откусывалась методом array_pop() от начала массива.
Если URL был передан с косой на конце, то после explode('/', $_REQUEST) у нас получится массив ["имя страницы", ""] - второй параметр пуст. Затем мы откусываем первый параметр и выходит массив с один пустым значением: [""].
Если ни одного значения в массиве нет (даже пустого) - то он был передан без завершающей косой, и мы делаем в таком случае редирект на верный адрес через $this->redirect().
Если же всё ок, то мы возвращаем true, handleRequest продолжает работу, запускает run() и там выводится наша фраза.
Проверяем - http://s1889.bez.modhost.pro/test.
А вот в Controllers_Home мы сделаем другую проверку. Нам не нужно, чтобы страница открывалась как /home/ - ведь это же корень сайта. Так что, проверяем переменную $_REQUEST['q'] и если она не пуста, то делаем редирект в корень сайта.
public function initialize(array $params = array()) {
if (!empty($_REQUEST['q'])) {
$this->redirect('/');
}
return true;
}
Теперь любой левый адрес на сайте, для которого не нашлось контроллера будет отфутболен на Home, а тот проверит, по какому адресу он был открыт. И если это не корень сайта - то редирект.
Выходит, что при открытии несуществующей страницы вас отредиректит в корень сайта. Неплохо, правда?
Проверяем - http://s1889.bez.modhost.pro/wrong\_page/
Заключение
Вот мы и познакомились с наследованием и расширением PHP классов. У нас есть базовый контроллер, который содержит базовые методы для расширения и использования в дочерних.
Заодно у нас как-то сама собой написалась логика редиректа в корень сайта при запросе несуществующей страницы.
На данный момент код нашего "движка" выглядит вот так.
Думаю, на следующем уроке мы уже начнём выводить какой-то стандартный HTML на наших страницах.
0
👍
👎
❤️
🔥
😮
😢
😀
😡
2 742
29.05.2015, 18:52:00
Комментарии
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Дмитрий
21.12.2024, 13:27:06
Здравствуйте.В ModX есть полезная функция "заморозить url родителя". При ее включении вместо:
УРЛ п...
Вывод товаров на сайте
20
Дмитрий
14.12.2024, 09:10:38
Василий, прошу прощения, тупанул, не разобрался сразу. Фреймворк отличный! "Чистый лист" на vue, рис...
Начинаем новый курс!
14
Василий Наумкин
05.12.2024, 20:01:14
В итоге основная ошибка была в неправильном общем root в Nginx, из-за чего запросы не улетали на фай...
Запуск в продакшн
55
Василий Наумкин
22.11.2024, 03:33:54
Спасибо!
День рождения 42
5
inna
06.11.2024, 15:47:13
Да. Все работает. Спасибо.
Vesp 3.0
108
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Оплата заказа
2
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Обновление проекта
2
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
Создание нового проекта
63
Василий Наумкин
20.03.2024, 21:21:52
Volledig!
Поездка в Швейцарию
8
Андрей
14.03.2024, 13:47:10
Василий! Как всегда очень круто! Моё почтение!
День рождения 41
6
Уровни подписки
Спасибо!
500 ₽ в месяц
Эта подписка ничего не даёт, просто возможность сказать спасибо за мои заметки. Подписчики отмечаются зелёненьким цветом в комментариях.
Большое спасибо!
1 000 ₽ в месяц
И эта подписка не даёт ничего, кроме оранжевого цвета в комментариях и возможности сказать спасибо, но уже большое!