Здравствуйте, мои маленькие психологически зрелые личности!
В свободное от работы время, в своё удовольствие, когда никому ничего не должен, когда нет кредитов и долгов, никаких обязательств перед кем-либо, когда приходишь домой, а дома тишина, чистота, покой и умиротворение, и никто слова тебе поперёк не скажет, — я занимаюсь разработкой своего проекта, сайта, на базе которого можно создавать другие сайты и управлять ими.
Исходный код вы можете скачать по ссылке http://www.netboot.ru/latest.tar, сейчас это сугубо-черновой вариант только чтобы продемонстировать рабочий прототип, оценить качество кода и может быть внести своё предложение по развитию.
Проверить как оно работает вживую вы можете на сайте http://www.netboot.ru/blog/, где пока на время тестирования вы можете свободно добавлять и редактировать любые сообщения.
Как я писал ранее, я не осилил ООП, поэтому проект написан в олдскульном стиле (или депрекейтед, уж кому как), с использованием исключительно простых функций, но при этом без использования глобальных переменных! Я большой перфекционист и строг прежде всего к самому себе в плане качества работы и кода, поэтому старался писать правильно.
Так например, у меня заведено в правилах, что каждая, подчёркиваю, _каждая_ функция возращает false, всегда! Чтобы функция вернула нужный нам результат, мы должны сами, подчёркиваю, _сами_, через условия добывать этот результат. Только так. В противном случае всегда будет false, и функции, которые друг-друга вызывают, получают false и отвечают тоже false, и клиент получает ошибку. С этим у меня очень строго.
Но не смотря на это, функции всё ещё поделены логически на отдельные пространства имён, то есть, все функции, которые работают с базой данных, начинаются с префикса db_, все функции, которые работают с сессиями, начинаются с префикса session_ и т.д. Соответсвенно такие списки функций я выделил в отдельные файлы, которые назвал не-классами, в ./src/noclasses лежат .noclass.php файлики.
Весь, целиком и полностью весь проект написан на функциях и ничего нигде «случайно» не происходит. Так, если вызвать php-файл напрямую из браузера, то ничего не произойдёт, т.к. там просто объявляются функции!
Проект состоит из /index.php файлика, ./src/noclasses/*.noclass.php функций и ./src/contollers/*.php контроллеров.
В /index.php самой первой вызывается функция:
run($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']);
То есть, по-сути, чтобы сэмулировать какой-то запрос и получить на него ответ, вы можете дёргать эту функцию руками.
Далее в main.noclass.php эта функция обрабатывает запрос и выдаёт ответ.
function run($request_uri, $request_method) {
$route = route($request_uri, $request_method);
$buffer = process($route);
$output = output($buffer);
return false;
}
route() смотрит какой документ запросили и выдаёт контроллер, который должен обработать запрос.
process() запускает заданный контроллер на выполнение, контроллер возвращает ответ, сгенерированную страничку например.
output() просто отдаёт ответ клиенту.
Функция route() требует доработки, т.к. каждый запрашиваемый документ проверяется вручную, а нам нужно реализовать динамический роутинг, который будет по списку смотреть маршрут и выдавать контроллер. //TODO в общем.
function route($request_uri, $request_method) {
$request_path = strtok($request_uri, '?');
$request = explode('/', $request_path);
$require = false;
if (end($request) == '') {
if ($request[1] == '') {
$require = 'index.php';
return $require;
}
}
return false;
}
Функция process() занимается вызовом котроллера.
function process($route) {
if ($route == false) {
echo 'kernel panic: controller not found';
return false;
}
$request = $route['request'];
$require = $route['require'];
ob_start();
$exec = (@include($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'controllers' . DIRECTORY_SEPARATOR . $require));
$ob_buffer_length = ob_get_length();
$ob_buffer = ob_get_contents();
ob_end_clean();
if ($ob_buffer_length > 0) {
echo 'kernel panic: buffer overflow outside of request() function in ' . $require;
return false;
}
if ($exec == false) {
echo 'kernel panic: failed to execute ' . $require;
return false;
}
if (function_exists('request')) {
$exec = request($request['request_uri'], $request['request_method'], $request['request']);
if ($exec == false) {
echo 'kernel panic: request() function returned false in ' . $require;
return false;
}
return $exec;
}
else {
echo 'kernel panic: request() function is not defined in ' . $require;
return false;
}
return false;
}
Вы видите, что, если php-скрипт что-то выводит вне вызываемой функции, это приводит к «панике»: kernel panic: buffer overflow outside of request()
Каждый контроллер обязан содержать функцию request(), которая уже обрабатывает запрос и выдаёт ответ.
Вот пример такого контроллера, который обрабатывает GET и POST запросы и выводит ответ.
function request($request_uri, $request_method, $request) {
if ($request_method == 'GET') {
return get_index();
}
if ($request_method == 'POST') {
return post_index();
}
return false;
}
function get_index() {
return 'Hello World!';
}
function post_index() {
return 'Hello World!';
}
Например, мы хотим отрисовать шаблон, тогда функция get_index будет выглядить так.
function get_index() {
$var = array(
'title' => 'Welcome!',
'body' => 'Hello world!'
);
$view = view('index.view-get-request', $var);
return $view;
}
И шаблон будет загружен из файла ./themes/localhost.localdomain/index.view-get-request.php
Как вы видите, не смотря на то, что код полностью написан на функциях, я бы сказал, что он напоминает чем-то ООП: на функциях тоже можно писать хорошо!