Создание движка на MVC. Дорабатываем роутер.
Здарова всем! Это уже третья статья. Продолжаем создавать наш движок на php.
Для начала возьмем весь код из главного файла index.php и вынесим его в отдельный класс с названием Bootstrap, который будет находиться в папке libs.
Файл bootstrap.php в папке libs.
<?php
class Bootstrap {
public function __construct() {
$url = $_GET['url'];
$url = rtrim($url, '/');
$url = explode('/', $url);
$file = 'controllers/'.$url[0].'.php';
if(file_exists($file)) {
require $file;
} else {
require 'controllers/error.php';
$controller = new Error();
return false;
}
$controller = new $url[0];
if(isset($url[2])) {
$controller->$url[1]($url[2]);
} else {
if(isset($url[1])) {
$controller->$url[1]();
}
}
}
}
?>
Как вы можете видеть, здесь были добавлены некоторые проверки. Если файл есть, то подключаем его, иначе же подключаем контроллер, отвечающий за обработку ошибок и останавливаем скрипт. Давайте напишем наш контроллер ошибок. Для этого создайте файл error.php в папке controllers.
<?php
class Error {
public function __construct() {
echo "Контроллер обработки ошибок";
}
}
?>
Все, что нам теперь осталось, прописать в нашем главном файле index.php, который у нас сейчас пустой, следующее:
<?php
require 'libs/Bootstrap.php';
$app = new Bootstrap();
?>
Все! Теперь у нас все должно работать, как и раньше, но если вы введете какое-нибудь неверное название контроллера, то увидите надпись, которую выводит наш контроллер ошибок
Что же, давайте теперь создадим базовый контроллер, который будет самым главным, а остальные контроллеры будут наследовать его. Для этого создайте файл Controller.php в папке libs.
<?php
class Controller {
public function __construct() {
echo "Это главный контроллер";
}
}
?>
Теперь абсолютно всем контроллерам пропишите: extends Controller
Вот пример того, что нужно сделать со всеми контроллерами, на примере контроллера Error.php
<?php
class Error extends Controller {
public function __construct() {
echo "Контроллер обработки ошибок";
}
}
?>
После того, как вы сделали это, всем контроллерам в конструкторе также следует прописать вызов родительского конструктора.
parent::__construct();
Теперь в нашем главном файле index.php добавьте подключение нашего главного контроллера.
<?php
require 'libs/Bootstrap.php';
require 'libs/Controller.php';
$app = new Bootstrap();
?>
Теперь пропишем в нашем главном контроллере создание объекта View, который будет отвечать за вид.
<?php
class Controller {
public function __construct() {
echo 'Это главный контроллер';
$this->view = new View();
}
}
?>
Все. На этом я заканчиваю эту статью. Сегодня мы доработали наш роутер и создали контроллер, отвечающий за ошибки, а также главный контроллер. В следующем уроке мы уже перейдем ко второй части паттерна MVC - виду. До скорого!
-
- Михаил Русаков
Комментарии (10):
Доброго времени суток. Сразу хочу отблагодарить Вас за замечательные уроки и статьи. Как раз по ним мне получилось подтянуть свои знания по PHP. Сейчас же я сталкиваюсь с проблемой разработки архитектуры для своего сайта. У меня уже есть готовый, выполненный в рамках дипломного проекта, но когда я посмотрел на код движка через месяц, я понял, что меня накрыло. :) В общем - бросился срочно переписывать. Решил как раз попрактиковаться с паттерном MVC и применить его в практически чистом виде. Из того, что у меня получилось: написать свой роутер, разобраться с контроллерами, моделями, видами. Ныне пытаюсь внедрить базовый класс для работы с БД, и именно здесь я спотыкаюсь. На ровном месте. Идеи для класса с работой с БД позаимствовал с Ваших уроков. Конечно, понимаю, что в контроллерах SQL-запросы как минимум нежелательны, но пока что такой путь для дебага. Вот кусок моего кривокода: http://pastebin.ru/OeMWwdBJ Наблюдения показали, что запросы я могу выполнять в рамках конструктора без проблем (как, например, в запросе указания кодировки), но не могу в рамках любой другой функции, которая обращается к объекту $this->mysqli. Вопрос: где я спотыкаюсь?
Ответить
Не совсем понял, что Вам нужно. У Вас этот класс будет базовым и от него будут другие наследники, так? Из кода, вроде, все верно. По ошибке понятно, что mysqli не является объектом. Нужно больше информации, чтобы это понять. И, кстати, у Вас не закрыта фигурная скобка класса.
Ответить
(много текста) Спасибо огромное за ответ. Криво скопировал кусок кода. Продолжаю сидеть над своим движком. Плюнул на всё и полностью переписал затею. А вообще да, именно, этот класс планировался как базовым, от которого будут наследоваться другие. Теперь у меня в ядре (папка core) есть основные файлы: controller.php, view.php, model.php, от которых наследуются, соответственно, контроллеры, модели и представления различных страничек сайта. Весь API авторизации пришлось реализовать в контроллере ядра (http://pastebin.ru/IxdZdyfc); для доступа к БД подключается простенький класс: (http://pastebin.ru/RivMztvb). Не знаю, как, но избавиться от ошибки получилось. Грешил на то, что я переопределял потомком конструктор родителя, в котором производилась инициализация БД. Решилось добавлением "parent::__construct();" в конструктор потомка. В контроллерах-потомках лишь проверяется "ответ" от функции "loginProcess()", которая возвращает true в случае успешной проверки всех данных (логин, пароль, куки и пр.) - http://pastebin.ru/me7SsQ01. Сейчас я испытываю другую проблему. В данном случае, при подключении главной страницы и её шаблона (в качестве шаблонизатора использую сам PHP, понимая, что конструкции наподобии "<?=$row['blah']?>" ни к чему хорошему не приведут), с модели "тащатся" данные лишь для последних 5 записей (двумерный массив), но я хочу подключить меню, для которого формируется отдельный массив (с отдельной модели). И как спроектировать это аккуратно, не пользуюясь include'ами в видах, я пока не знаю...
Ответить
На ошибках учатся. Делайте так, как делаете, главное, чтобы работало. Со временем поймете, как будет лучше. Однако, лично мой Вам совет, изучите фреймворк. Если вы уже на достаточно хорошем уровне знаете ООП, то не думайте, что фреймворк пока что рано и стоит сначала сделать что-то свое. Советую изучить Laravel. На мой взгляд, это самый лучший фреймворк на данный момент. Быстрый, удобный, а главное там очень хорошая архитектура. Если вы его изучите и сделаете, например, блог с его использованием, то обязательно поймете, как правильно делать организацию файловой структуры, а также, как правильно использовать ООП при создании своего приложения и в будущем спокойно сможете написать качественное, объектно-ориентированное приложение без использования фреймворка.
Ответить
К ООП я приучен после программирования на С++ с использованием Qt - шикарный фреймворк, но в вебе я могу быстрее реализовать свои задумки - не приходится играться с типизацией и указателями, а это привлекает. Да и вообще я просто обожаю программировать. Забросил Паскаль уже после ветвлений, начал заниматься С++, так как он очень хорошо пошёл. После бега со стороны в сторону решил, что хочу связать с программированием свою жизнь (и работу в том числе). Весь опыт в программировании я получил самоучкой, и меня останавливает неуверенность в качестве моих познаний в этой области. Извиняюсь за оффтоп. В общем... Как раз намедни почитал про Laravel и обязательно попробую с ним поработать, и если Михаил не будет против - я буду рад отписаться здесь о достижениях. Параллельно, время от времени, испытываю себя в программировании на Python и знакомлюсь с django. Люблю строить своё и узнавать новое - это круто! Спасибо огромное за ответы и совет!
Ответить
Да, пишите здесь свои достижения) Обязательно изучите Laravel) Он классный! И, кстати, то, что Вы интересуетесь многим, это хорошо, только не кидайтесь из стороны в сторону. Изучите сначала хорошо php, а уже потом переходите к другим языкам, как, например, python. Ну, я думаю, Вы это сами понимаете. Удачи! :)
Ответить
Devtester вы бегаете со стороны в сторону. Определитесь, какой именно язык программирования вы будите использовать и изучайте его. Можно и 12 языков знать, но толку с этого не будет, в каком то языке вы будите сильны, а в другом слабы. Всё знать не получится и уж тем более с пользой. Это всё равно что я буду писать скрипты на php не дописанные или не нужные, по сути скрипт будет работать, но толку с него ни какого, всё равно, что написать скрипт hello world, будет с него польза для сайта? Не думаю... Кстаи, насчёт фреймоворка... Я знаю один фрймоворк по которому сам занимался, по сути он мало весит и у него хорошая структура, а называется он Codeigniter рекомендую вам его посмотреть и попробовать сделать что - то, всё что нужно знать вам это основы php, mysql и объектно ориентированный подход.
Ответить
Спасибо за вашу статью. Есть небольшие дополнения. "Файл bootstrap.php в папке libs." замените на: "Файл Bootstrap.php в папке libs." Также я бы заменил: "$url = $_GET['url'];" на: if (isset($_GET['url'])){ $url = $_GET['url']; } else{ $url = 'index'; } Иначе если перейти на http://example.com/ вместо http://example.com/index выдаст ошибку "Undefined index: url"
Ответить
Теперь абсолютно всем контроллерам пропишите: extends Controller //... Укажите в коде куда именно! ///.... После того, как вы сделали это, всем контроллерам в конструкторе также следует прописать вызов родительского конструктора. parent::__construct(); ///.... и про это тоже.
Ответить
class Index extends Controller { public function __construct() { parent::__construct(); echo 'Мы в контроллере Index'; } }
Ответить
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.