Ядро. Легкая версия

ПРЕДИСЛОВИЕ

Этот раздел написан по многочисленным просьбам тех, кто не смог разобраться в следующем разделе.

Представленный набор скриптов представляет из себя его облегченную, спартанскую версию настоящего ядра. Это просто попытка помочь более плавно адаптироваться в премудростях последующих скриптов.

Кто чувствует в себе силы сразу изучать более серьёзные вещи, может этот раздел пропустить.
В следующем придется начать все сначала. Хотя повторение - мать учения. Впрочем, выбирать Вам.
Шаг 1
Подготовительные работы.
С чего обычно начинается построение сайта? Вы думаете, что нужно сделать первый файл, допустим index.php, и пошло-поехало.
Ан нет.

Для того чтобы было быстрее и аккуратнее, доложна быть готовая рама, на которую мы и понавешаем нужный функционал, чтоб не повторяться.

Назвать это можно ядром, фреймворком, шаблоном, паттерном, горшком, чертом лысым или как душе угодно. Суть одна - все, что обычно повторяется в разных сайтах (структура и общие функции) должно быть готово. Как замороженные пельмени. Останется сварить и добавить специи.

Нужно сразу заметить, что ядром в нашем понимании, является не какие то догмы и рамки, которые обычно ставятся фреймворками и всевозможными CMS. У нас это просто структура, которая позволяет упорядочить скрипты и иные принадлежности сайта. Оставляя полную свободу выбора как и что реализовывать. И хотя "framework" и переводится как "основа" или "рабочая рама", в классическом понимании это больше язык программирования со своим синтаксисом и законами. Наша структура более точно подходит под определение "рама".

Вот сейчас и сделаем такую кухню. Приступим, помолясь.
Мы уже изучили структуру сайта, сейчас будет намного проще понять: что где и зачем. Возьмем этот скрипт и на его основе начнем разворачивать боевые действия.

Начнем с того, что обычно оставляется "на потом", так как это кажется не очень важным. И зачастую это "потом" так и не наступает.

А именно с конфигурации и сопутствующих фишек.

Начнем со страниц ошибок. В корневой директории нужно сделать, как минимум, три файла.

401.html
403.html
404.html

Оформлять их не нужно, это дело верстальщиков. Нам будет достаточно этого:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<title>404</title> 
</head> 
<body> 
<h2 style="color:#FF0000">404</h2> 
Запрашиваемая страница отсутствует на нашем сайте. 
</body> 
</html>

Еще там же в корне нужно сделать файл .htaccess с таким содержанием:
AddDefaultCharset UTF-8 
php_flag magic_quotes_gpc Off 
php_flag magic_quotes_runtime Off 
php_flag register_globals Off 
ErrorDocument 401 /401.html 
ErrorDocument 403 /403.html 
ErrorDocument 404 /404.html 
Options -Indexes

Что тут.

1. Кодировка. Все сайты мы будем делать в кодировке UTF-8.
2, 3. Убиваем магические кавычки.
4. Отключаем глобальные переменные
5-8. Обработка ошибок запросов. Вот тут и пригодятся странички. Обратите внимание на строку

Options -Indexes

Эта строка запретит вывод списка файлов и директорий, если в папке не окажется индекса. А директива ErrorDocument перенаправляет запросы на подготовленные страницы в случае ошибки сервера. Допустим набран адрес несуществующей страницы. В таком случае откроется 404.html

А пока что на данный момент должны иметь:

1. Всю структуру с прошлого занятия.
К ней добавили:
2. Три страницы с ошибками.
3. Файл .htacces в корневой директории.

Это точка отправления.

Шаг 2

Инициализация внешних переменных
Итак, начало у нас положено.
Продолжим-с.

Теперь у нас стоит задача выставить текущие и глобальные настройки сайта.
Основные и незыблемые две - кодировку и уровень ошибок, они прописаны первыми строчками индекса.
<?php
/** 
* We establish the charset and level of errors 
* Устанавливаем кодировку и уровень ошибок 
*/ 
    header("Content-Type: text/html; charset=utf-8"); 
    error_reporting(E_ALL);

Но понадобятся еще и текущие настройки. Их будет много, и чтобы не носиться по всему сайту в поисках вчерашнего дня, все настройки принято держать в одном месте, а именно в конфигурационном файле. Вот и мы не лыком шиты, у нас есть такой в корне - config.php

Еще в config.php добавим еще две константы (одна там уже есть). Обратите внимание на префиксы констант. Они нужны, чтобы невзначай не пересечься с предопределенными константами или константами сторонних скриптов, которые мы, может быть, будем интегрировать в систему.
<?php
/** 
* Configuration file 
* Конфигурационный файл 
* @author IT studio IRBIS-team 
* @copyright © 2009 IRBIS-team 
*/ 
///////////////////////////////////////////////////////// 
/**  
* Choice of language of a site  
* Выбор языка сайта  
*/   
    define('IRB_LANGUAGE', 'ru');  

/**   
* Establishes a physical path to a root directory of a script   
* Устанавливает физический путь до корневой директории скрипта   
*/   
    define('IRB_ROOT', str_replace('\\', '/', $_SERVER['DOCUMENT_ROOT']) .'/');   

/**   
* Establishes a path to a script root for HTTP   
* Устанавливает путь до корневой директории скрипта   
* по протоколу HTTP   
*/   
    define('IRB_HOST', 'http://'. $_SERVER['HTTP_HOST'] .'/');

Первая для указания полных физических путей, а вторая нужна для полных ссылок.

Для чего это нужно. А для того, чтобы скрипт можно было использовать не только в корне, а в отдельной папке, как дополнение или расширеник какого то готового сайта.
Для этого достаточно добавить в путь эту директорию.
/**  
* Establishes a path to a script root for HTTP  
* Устанавливает путь до корневой директории скрипта  
* по протоколу HTTP 
*/ 
    define('IRB_HOST', 'http://'. $_SERVER['HTTP_HOST'] .'/my_site/');

Теперь нужно все пути (к картинкам, стилям и т.д.) начинать с этого
<?php echo IRB_HOST ?>

и не бояться, что в определенный момент нужно будет перенести скрипт в другое место. Просто меняем путь в конфиге и насвистываем веселенький мотивчик.
Теперь ссылки в меню можно написать так:
<!-- skins/tpl/menu.tpl begin -->  
Сегодня <?php echo $date ?> года  
<ul>  
<li><a href="<?php echo IRB_HOST ?>?page=main">Главная страница</a></li>  
<li><a href="<?php echo IRB_HOST ?>?page=second">Вторая страница</a></li>  
</ul>  

<!-- skins/tpl/menu.tpl end -->

А ссылки - это важно. Потому что на гет-параметрах этих ссылок и будет строиться вся навигация и переключение модулей, так как все внутренние ссылки будут вести только на один файл (точку входа) - index.php

Это значит, что нам нужно бережно принять эти параметры и обработать их.

У нас уже был такой прецидент, мы инициализировали переменную $page в файле variables.php как раз для переключения модулей. Еще нам потребуется переменная для переключения разделов модуля (контроллеров). Назовем её $rem. Еще пригодится переменная для постранички. $num И переменная идентификатора чего-либо. Соответственно $id. А чтобы нам не греть голову, откуда появились в скрипте переменные, сложим их все в один массив $GET (не путать с $_GET). И теперь в любом месте будет ясна их принадлежность.
Ну а за одно сразу установим значения по умолчанию. Лишним никогда не будет.
variables.php
/**   
* Initialization of variables GET-parametres   
* Инициализация переменных GET-параметров   
*/   
    $GET['page'] = !empty($_GET['page']) ? $_GET['page'] : 'main'; 
    $GET['rem']  = !empty($_GET['rem']) ? $_GET['rem'] : 'read'; 
    $GET['num']  = !empty($_GET['num']) ? $_GET['num'] : 1;     
    $GET['id']   = !empty($_GET['id']) ? $_GET['id'] : 1;

В главном индексе нужно тоже изменить переменную, коль скоро они у нас все в массиве:
<?php

/** 
* The switch of modules 
* Переключатель страниц 
*/       
    switch($GET['page'])  
    {  
/**   
* Подключаем модуль приветствия   
* Includes the greeting module   
*/          
        case 'main':     
            include './modules/main/router.php';             
        break;

Еще нам понадобятся $_POST переменные. Мы же будем делать интерактивные приложения. В файле с переменными нужно просто указать несколько таких про запас. Если не хватит, потом добавим еще.
variables.php
<?php


/**  
* The block of initialization and processing of entering variables  
* Блок инициализации и обработки переменных  
* @author IT studio IRBIS-team  
* @copyright © 2009 IRBIS-team  
*/  
///////////////////////////////////////////////////////// 

/**   
* Initialization of variables GET-parametres   
* Инициализация переменных GET-параметров   
*/   
    $GET['page'] = !empty($_GET['page']) ? $_GET['page'] : 'main'; 
    $GET['rem']  = !empty($_GET['rem']) ? $_GET['rem'] : 'read'; 
    $GET['num']  = !empty($_GET['num']) ? $_GET['num'] : 1;     
    $GET['id']   = !empty($_GET['id']) ? $_GET['id'] : 1;     
     
/**   
* Initialization of variables POST   
* Инициализация переменных POST   
*/  
    
    $ok       = !empty($_POST['ok'])?true:false;   
    $delete   = !empty($_POST['delete'])?true:false; 
   
    $POST['value1'] = !empty($_POST['value1']) ? $_POST['value1'] : NULL;   
    $POST['value2'] = !empty($_POST['value2']) ? $_POST['value2'] : NULL;  
    $POST['value3'] = !empty($_POST['value3']) ? $_POST['value3'] : NULL;  
    $POST['value4'] = !empty($_POST['value4']) ? $_POST['value4'] : NULL;

Обратите внимание, мы не знаем, какие понадобятся переменные. Если приложение большое, то их может оказаться огромное количество. По этому, не мудря, просто пронумеруем их и будем использовать по порядку.

Еще в этот же файл сразу добавим функцию для удаления магических кавычек.
Весь файл variables.php теперь такой:
<?php


/**  
* The block of initialization and processing of entering variables  
* Блок инициализации и обработки переменных  
* @author IT studio IRBIS-team  
* @copyright © 2009 IRBIS-team  
*/  
///////////////////////////////////////////////////////// 

/**  
* We kill magic inverted commas  
* Убиваем магические кавычки  
*/          
    function stripslashesDeep($data)      
    {      
        if(is_array($data))       
            $data = array_map("stripslashesDeep", $data);       
        else     
            $data = stripslashes($data);       
        return $data;  
    }  

    if(get_magic_quotes_gpc())   
    {   
        $_GET = stripslashesDeep($_GET);    
        $_POST = stripslashesDeep($_POST);    
        $_COOKIE = stripslashesDeep($_COOKIE);  
        $_REQUEST = stripslashesDeep($_REQUEST);  
    } 
     
/**   
* Initialization of variables GET-parametres   
* Инициализация переменных GET-параметров   
*/   
    $GET['page'] = !empty($_GET['page']) ? $_GET['page'] : 'main'; 
    $GET['rem']  = !empty($_GET['rem']) ? $_GET['rem'] : 'read'; 
    $GET['num']  = !empty($_GET['num']) ? $_GET['num'] : 1;     
    $GET['id']   = !empty($_GET['id']) ? $_GET['id'] : 1;     
     
/**   
* Initialization of variables POST   
* Инициализация переменных POST   
*/  
    
    $ok       = !empty($_POST['ok'])?true:false;   
    $delete   = !empty($_POST['delete'])?true:false; 
   
    $POST['value1'] = !empty($_POST['value1']) ? $_POST['value1'] : NULL;   
    $POST['value2'] = !empty($_POST['value2']) ? $_POST['value2'] : NULL;  
    $POST['value3'] = !empty($_POST['value3']) ? $_POST['value3'] : NULL;  
    $POST['value4'] = !empty($_POST['value4']) ? $_POST['value4'] : NULL; 
     
     
/**   
* Other variables   
* Другие переменные   
*/     
   $info  = array();

Это основа всех наших дальнейших поползновений.

Шаг 3
Паттерн MVC. Модель.
Ну раз у нас есть гостевая книга - не пропадать же добру. Попробуем на её основе построить что то более менее приличное.
Начнем с данных. Как помнится, для этого у нас была организована директория data. Ну и тут сделаем тоже самое. Это будет частью модели, а именно хранилищем данных.

Вторая часть - скрипт получения этих данных из хранилища. У нас в гостевой книге за это отвечает функция сканирования директории.
Поместим её в файл libs/model.php
<?php


/**    
* Model functions   
* Функции модели    
* @author IT studio IRBIS-team    
* @copyright © 2009 IRBIS-team    
*/ 
////////////////////////////////////////////////////////////////// 


/**      
* Function of reading of a directory     
* Функция чтения директории 
* @param string      
* @return array     
*/  
    function dirScan($dir)  
    {   
        static $files;  
          
            if(empty($files))  
            {  
                $files = scandir($dir);  
                $files = array_diff($files, array('.', '..'));  
            }  
   
        $files = count($files) ? $files : array('1');  
                  
        return $files;  
    }


Ну и для полного счастья добавим туда же еще две функции. Получения и записи информации, хранимой в виде сериализованных массивов.
<?php


/**     
* Model functions    
* Функции модели     
* @author IT studio IRBIS-team     
* @copyright © 2009 IRBIS-team     
*/  
//////////////////////////////////////////////////////////////////  


/**       
* Function of reading of a directory      
* Функция чтения директории  
* @param string       
* @return array      
*/   
    function dirScan($dir)   
    {    
        static $files;   
           
            if(empty($files))   
            {   
                $files = scandir($dir);   
                $files = array_diff($files, array('.', '..'));   
            }   
    
        $files = count($files) ? $files : array('1');   
                   
        return $files;   
    } 
     
     
/**       
* Function of reception of the information    
* Функция получения информации  
* @param string       
* @return array       
*/   
    function getData($file)   
    {    
        if(file_exists($file)) 
            $string = trim(file_get_contents($file));  
        else 
            exit('No such file '. $file); 

         
        return !empty($string) ? unserialize($string) : array();  
              
    } 

/**       
* Data recording function    
* Функция записи информации 
* @param string       
* @return array      
*/   
    function setData($file, $array)   
    {    
        return file_put_contents($file, serialize($array));  
    }

Вот и вся модель. Тоесть хранилище (папка data в корне) и эти три функции, позволяющие с этими данными работать. То есть находить нужный файл, чтать его, десериализовать массив и выдавать результат. Ну или наоборот - сериализовать массив и складывать в файл по месту назначения.

Пока работы этих скриптов мы не увидим, это внутренняя кухня. А чтобы увидеть, нам потребуется продолжение банкета - вид и контроллер.

Шаг 4
Паттерн MVC. Контроллер
Начнем с контроллера. В нем, для наглядности, будет два блока. Один для вывода информации, другой для записи.

Гостевая книга, как ей и положено, будет находиться на второй странице.
Итак, открываем файл modules/second/read_controller.php и пишем туда это:
<?php


/**   
* The controller of a conclusion of the information   
* Контроллер вывода информации   
* @author IT studio IRBIS-team   
* @copyright © 2009 IRBIS-team   
*/   
/////////////////////////////////////////////////////////   


/**   
* We connect a file of the model functions   
* Подключаем файл функций модели  
*/     
   include './libs/model.php'; 


/**   
* The block of reading of the information   
* Блок чтения информации   
*/  
    $posts = getData('./data/'. $GET['num']);  
    include './libs/bb_tags.php'; 
     
    $rows = '';  
         
    foreach($posts as $id => $post)  
    {  
        $date  = $post['date'];          
        $name  = htmlspecialchars($post['name']);  
        $mess  = nl2br(bbTags(htmlspecialchars($post['mess'])));  
        $rows .= '<div class="guest_post">'. $date .' / <strong> 
                 '. $name .'</strong><hr width="30%" align="left" /> 
                 '. $mess .'</div>';        

    } 

Всё это мы уже проходили в гостевой книге, просто сейчас пытаемся привести в удобоваримый вид. По этому на самом функционале акцентироваться не будем.
Но несколько важных момента отметить надо.
1. Не все страницы и модули будут работать с данными. А значит файл с функциями модели мы будем подключать непосредственно в контроллер.
2.Весь вывод мы поместим в переменную $rows, а не отправим тут же в поток. За вывод отвечает часть паттерна MVC "вид", так что не будем нарушать принципов. И хоть у нас там затесались предательские html-теги, это будет идеологически верно. А с тегами мы разберемся чуть позже.
3. Теперь нет необходимости в контроллере проверять наличие файла, это сделает функция чтения, которую мы поместили в модель. Она нам пригодиться в той же админке или в другом модуле. Допустим можно сделать блок комментариев к статьям или даже модуль новостей. Принцип работы с данными останется прежним.
4. Функция bb-тегов нам понадобится и в админке. Поэтому мы вынесем её в отдельный файл и будем подключать там, где потребуется. Чтобы не переписывать одно и тоже по 10 раз.
libs/bb_tags.php
<?php


/**  
* Replacement function bb-tags and smilies        
* Функция замены bb-тегов и смайликов     
* @param string     
* @return string   
* @author IT studio IRBIS-team  
* @copyright © 2009 IRBIS-team  
*/  
///////////////////////////////////////////////////////// 


    function bbTags($text)   
    {      
        $bb = array(  
                    '[B]',   
                    '
',
'', '',
'
',   
                    '
',
'', '',
'[:)]',
'[:(]',
'[;)]',
'[:D]'
);

$tag = array(
'<b>',
'</b>',
'<i>',
'</i>',
'<s>',
'</s>',
'<u>',
'</u>',
'<img src="'. IRB_HOST .'skins/images/smiles/1.gif" />',
'<img src="'. IRB_HOST .'skins/images/smiles/2.gif" />',
'<img src="'. IRB_HOST .'skins/images/smiles/3.gif" />',
'<img src="'. IRB_HOST .'skins/images/smiles/4.gif" />'
);

return str_ireplace($bb, $tag, $text);
}[/PHP]
Ну скучно же делать что то, не получая тут же результата. Так давайте веселиться. Для начала выведем переменную $rows в шаблон:
<!-- skins/tpl/second/show.html begin --> 

<div style="padding:10px; background-color:#e6e6e6;"> 
<?php echo $rows ?> 
</div> 

<!-- skins/tpl/second/show.tpl end -->

Потом сделаем файл стилей и поместим на свое законное место: skins/css/style.css
/* CSS Document */ 
.guest_post{ 
    border:1px solid;  
    width:70%;  
    background-color:#66FFFF;  
    min-height:100px;  
    margin:5px;  
    padding:5px; 
}

Подключим его к главному шаблону: skins/tpl/index.tpl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head>  
<title>Мой сайт</title>
 
    <link href="<?php echo IRB_HOST ?>skins/css/style.css" rel="stylesheet" type="text/css" />
 
</head> 
<body> 
<?php echo $content ?> 
</body> 
</html>

И - на старт! Внимание! Мааааарш!
Запускаем.

Вот так и будет работать дебаггер, если вдруг не окажется нужного файла с данными. Ну откуда ему взяться, если мы еще не сделали контроллер записи?
А вот отсюда можно взять пока прямо всю папку data

Теперь работает? Если нет, вот тут точно работает.

Ну а мы продолжим. Исправим ситуацию и соорудим блок записи.

Шаг 5
Контроллер. Продолжение.
Итак, нам нужно срочно добавить записей. Для этого нужен блок записи, но для начала разберемся с формой.
Вообще, форма - это тоже вещь, касаемая данных. И её тоже можно, с небольшой натяжкой, отнести к модели. Но суть в том, что как бы мы её не обзывали, формой она быть от этого не перестанет. Я вообще противник каких-либо ярлыков и рамок. Если комуто понравилось назвать это все MVC, ну и Бог ему судья. Нам же гораздо важнее, чтобы все безупречно работало. А назвать можно хоть MVC, хоть VCM, хоть Семен Семенычем, хоть крылатой ракетой "Першинг".

Итак, форма. Добавим её в шаблон модуля:
<!-- skins/tpl/second/show.html begin --> 

<div style="padding:10px; background-color:#e6e6e6;"> 
  
<strong style="color:#FF0000"><?php echo getInfo($info); ?></strong> 

<?php echo $rows ?> 
<form action="" name="post" id="post" method="post">    
Имя:<br />    
<input name="value1" type="text" value="<?php echo $POST['value1'] ?>"/>
<br />   
<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/bold.gif" 
alt="Жирный" onclick="tag('[b]','
')">

<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/italics.gif"
alt="Курсив" onclick="tag('','')">

<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/underline.gif"
alt="Подчеркнутый" onclick="tag('','')">

<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/strikethrough.gif"
alt="Зачеркнутый" onclick="tag('
','
')">

<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/1.gif" onclick="tag('[:)]','')">
<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/2.gif" onclick="tag('[:(]','')">
<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/3.gif" onclick="tag('[;)]','')">
<img style="cursor:pointer" src="<?php echo IRB_HOST ?>skins/images/smiles/4.gif" onclick="tag('[:D]','')">
<br />
Сообщение:<br />
<textarea name="value2" id="value2" cols="40" rows="10"><?php echo $POST['value2'];?></textarea><br />
<input name="ok" type="submit" />
</form>
</div>

<!-- skins/tpl/second/show.tpl end -->[/PHP]
Форма нам знакомая, изменились только названия полей и добавилась функция вывода ошибок. Для красоты.
<?php

/** 
* Information conclusion 
* Вывод информации         
*/   
    function getInfo($info) 
    { 
        if(count($info)) 
            return '<br>' . implode('<br>', $info); 
        else 
            return '&nbsp;'; 
    }

Добавилась она, как можно догадаться, в файл с общими функциями (libs/default.php)

И еще нужно взять смайлики и поместить их в папку skins/images
А вот для того, чтобы заработали эти смайлики и bb-теги, нужно в папку skins/js положить этот скрипт:
skins/js/script.js
function tag(text1, text2) 
{

    if ((document.selection)) 
    { 
        document.getElementById('value2').focus(); 

        document.post.document.selection.createRange().text = 
        text1+document.post.document.selection.createRange().text + text2; 

    } else if(document.forms['post'].elements['value2'].selectionStart != undefined) { 
        var element = document.forms['post'].elements['value2']; 
        var str = element.value; 
        var start = element.selectionStart; 
        var length = element.selectionEnd - element.selectionStart; 
        element.value = str.substr(0, start) + text1 + str.substr(start, length) 
        + text2 + str.substr(start + length); 

    }
}

и подключить в главный шаблон:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head>  
<title>Мой сайт</title> 
<link href="<?php echo IRB_HOST ?>skins/css/style.css" rel="stylesheet" type="text/css" />
 
    <script type="text/javascript" language="javascript" src="<?php echo IRB_HOST ?>skins/js/script.js"></script> 
 
</head> 
<body> 
<?php echo $content ?> 
</body> 
</html>

Вот теперь пора сделать и сам блок записи. Функционал его практически не изменился, такой же и был в гостевой книге.
modules/second/read_controller.php
<?php


/**   
* The controller of a guestbook   
* Контроллер гостевой книги   
* @author IT studio IRBIS-team   
* @copyright © 2009 IRBIS-team   
*/   
/////////////////////////////////////////////////////////   


/**   
* We connect a file of the model functions   
* Подключаем файл функций модели  
*/     
   include './libs/model.php'; 

/**   
* The block of recording of the information   
* Блок записи информации   
*/  
    if($ok)    
    {    
        if(!$POST['value1'])    
            $info[] = IRB_LANG_NO_NAME;  
                
        if(!$POST['value2'])    
            $info[] = IRB_LANG_NO_TEXT;;   
               
        if(count($info) == 0)    
        {    
               
             $file = max(dirScan('data'));  
             $posts = getData('data/'. $file);      
                  
             if(count($posts)) 
             {  
                 $keys = array_keys($posts);  
                 $id = max($keys) + 1;  
                 $num = count($posts);  
             }  
             else  
                 $num = $id = 1;  
                  
            if($num >= IRB_NUM_POSTS)  
            {  
                ++$file;  
                unset($posts);  
            }                     
                          
            $posts[$id]['date'] = date('d-m-Y');  
            $posts[$id]['name'] = $POST['value1'];  
            $posts[$id]['mess'] = $POST['value2'];                        
              
            setData('./data/'. $file, $posts);    

            header('location: '. IRB_HOST .'?page=second&num='. $file);    
            exit();    
        }    
    }  
     
     
/**   
* The block of reading of the information   
* Блок чтения информации   
*/  
    $posts = getData('./data/'. $GET['num']);  
    include './libs/bb_tags.php'; 
     
    $rows = '';  
         
    foreach($posts as $id => $post)  
    {  
        $date  = $post['date'];          
        $name  = htmlspecialchars($post['name']);  
        $mess  = nl2br(bbTags(htmlspecialchars($post['mess'])));  
        $rows .= '<div class="guest_post">'. $date .' / <strong> 
                 '. $name .'</strong><hr width="30%" align="left" /> 
                 '. $mess .'</div>';        

    }

Разница только в методах получения и записи информации (теперь это осуществляют специальные функции) и в редиректе. Мы в него подставили константу.

Кстати, о константах. Нужно добавить еще одну в конфигу. Она будет определять количество постов на странице.
<?php


/** 
* Configuration file 
* Конфигурационный файл 
* @author IT studio IRBIS-team 
* @copyright © 2009 IRBIS-team 
*/ 
///////////////////////////////////////////////////////// 

/**  
* Choice of language of a site  
* Выбор языка сайта  
*/   
    define('IRB_LANGUAGE', 'ru'); 
     
/**      
* Quantity of posts on page   
* Количество постов на странице    
*/  
   define('IRB_NUM_POSTS', 5);       

/**   
* Establishes a physical path to a root directory of a script   
* Устанавливает физический путь до корневой директории скрипта   
*/   
    define('IRB_ROOT', str_replace('\\', '/', $_SERVER['DOCUMENT_ROOT']) .'/');   

/**   
* Establishes a path to a script root for HTTP   
* Устанавливает путь до корневой директории скрипта   
* по протоколу HTTP   
*/   
    define('IRB_HOST', 'http://'. $_SERVER['HTTP_HOST'] .'/');

и еще парочку в языковой файл - для валидации данных формы:
language/ru.php (en.php)
<?php


/** 
* Варианты модуля приветствия   
* Variants of the module of a greeting 
*/ 
    define('IRB_WHO_FIRST', 'Мир');  
    define('IRB_WHO_SECOND','Солнце');  
    define('IRB_WHO_THIRD', 'Небо');  
    define('IRB_WHO_FOURTH','Вася');  
    define('IRB_WHO_FIFTH', 'Петя'); 
      
/** 
* Массив месяцев   
* The month array  
*/ 
    $month = array(  
                    '01' => 'января',  
                    '02' => 'февраля',  
                    '03' => 'марта',  
                    '04' => 'апреля',  
                    '05' => 'мая',  
                    '06' => 'июня',  
                    '07' => 'июля',  
                    '08' => 'августа',  
                    '09' => 'сентября',  
                    '10' => 'октября',  
                    '11' => 'ноября',  
                    '12' => 'декабря'  
                  ); 
                   
/** 
* Check data   
* Валидация  
*/                   
    define('IRB_LANG_NO_NAME', 'Нет имени');                   
    define('IRB_LANG_NO_TEXT', 'Текстовая область не заполнена.');

Ну вот теперь кажется и все, контроллер готов к бою. Можно пробовать.

Шаг 6
Паттерн MVC. Вид.
Ну а теперь займемся приведением в порядок отображения. У нас с ним далеко не все в порядке. Начнем с того, что уже проходили. А именно с возврата данных. Самые наблюдательные могли заметить, что у нас пропала обработка данных, которыен выводятся в элементы формы. Напомню:
<input name="value1" type="text" value="<?php echo $POST['value1'] ?>"/>

Тут отсутствует функция htmlspecialchars(). Это все неспроста.

Дело в том, что данные у нас хранятся не в разрозненных переменных, а в массиве $POST (не путать с $_POST). А раз они в массиве, то и обработать их можно одним махом. Для этого сочиним специальную функцию-обертку, которая заставит htmlspecialchars() работать с массивами.
Поместим её в файл libs/view.php, так как данные нужно обрабатывать всегда и повсеместно.
<?php


/** 
* Library of the views functions 
* Библиотека функций отображения 
* @author IT studio IRBIS-team 
* @copyright © 2009 IRBIS-team 
*/ 
/////////////////////////////////////////////////////////<br /> 

/**    
* Function of processing of variables for a conclusion in a stream    
* Функция обработки переменных для вывода в поток     
*/                                                        
    function htmlChars($data)       
    {       
        if(is_array($data))  // Если данные - массив, вызываем эту же функцию.             
            $data = array_map("htmlChars", $data);     
        else  // Если нет, обрабатываем  htmlspecialchars()               
            $data = htmlspecialchars($data);       
       // На выход                             
        return $data;    
    } 

/** 
* Date formatting 
* Форматирование даты  
*/ 
    $date = formatDate(date("Y-m-d"), false);

А теперь просто открываем вьюшку модуля и добавляем туда всего одну строчку:
modules/second/view.php
<?php


/** 
* View 
* Вид 
* @author IT studio IRBIS-team 
* @copyright © 2009 IRBIS-team 
*/ 
///////////////////////////////////////////////////////// 


   $POST = htmlChars($POST); 


/**   
* Подключаем шаблон   
* Includes a templates   
*/ 
    include './skins/tpl/second/show.tpl';

Все, теперь ни одна мышь не проскочит незамеченной. Все данные будут обязательно обработаны. Это мало того, что удобно, так еще и повышает безопасность.
Только один момент, эта обработка должна производиться непосредственно перед подключением шаблона, как не был велик соблазн обработать все сразу на входе. Это приведет к искажению данных.

Поехали дальше. Блок чтения информации. Тут точно также можно обработать сразу весь массив:
/**   
* The block of reading of the information   
* Блок чтения информации   
*/  
    $posts = getData('./data/'. $GET['num']);  
    include './libs/bb_tags.php'; 
     
    $rows = '';  
         
    foreach($posts as $id => $post)  
    {  
        $post = htmlChars($post); 
        $date  = $post['date'];          
        $name  = $post['name'];  
        $mess  = nl2br(bbTags($post['mess']));  
        $rows .= '<div class="guest_post">'. $date .' / <strong> 
                 '. $name .'</strong><hr width="30%" align="left" /> 
                 '. $mess .'</div>';        

    }

Это удобно, но не столь важно. А важно то, что вот и попались нам эти бессовестные html теги, которым совсем не место в контроллере. Их нужно немедленно поместить в шаблон. Вот так:
<!-- skins/tpl/second/rows.html begin --> 

<div class="guest_post">          
<?php echo $date; ?> / <strong><?php echo $name; ?></strong>  
<hr width="30%" align="left" />  
<?php echo $mess; ?>  
</div> 

<!-- skins/tpl/second/rows.tpl end -->

А вот сам этот шаблон запихать в переменную $rows . Но как это сделать, ведь там переменные, и они должны меняться в каждом витке цикла... А для этого сочиним функцию, которая нам в этом поможет. Поместим её в файл libs/view.php
<?php


/** 
* Library of the views functions 
* Библиотека функций отображения 
* @author IT studio IRBIS-team 
* @copyright © 2009 IRBIS-team 
*/ 
///////////////////////////////////////////////////////// 

/**   
* Function of analysis of a template   
* Функция разбора шаблона   
*/        
    function parseTpl($file, $data = array())   
    {   
                       
            extract($data);   

            ob_start();   
                include $file;   
            $cont = ob_get_contents();     
            ob_end_clean();     

       return $cont;   
    }   
     
     
/**    
* Function of processing of variables for a conclusion in a stream    
* Функция обработки переменных для вывода в поток     
*/                                                        
    function htmlChars($data)       
    {       
        if(is_array($data))  // Если данные - массив, вызываем эту же функцию.             
            $data = array_map("htmlChars", $data);     
        else  // Если нет, обрабатываем  htmlspecialchars()               
            $data = htmlspecialchars($data);       
       // На выход                             
        return $data;    
    } 

/** 
* Date formatting 
* Форматирование даты  
*/ 
    $date = formatDate(date("Y-m-d"), false);

Что это за зверь такой. Ну вопервых, сразу оговорочка. Так делать вообще то нежелательно, потому что мы при каждой интерации (витке) цикла вынуждены обращаться к файловой системе. В следующем разделе я покажу, как этого избежать. А пока для наглядности так.
Но по порядку. Функция extract() разбирает массив на переменные. Теперь (хоть их и не видно) у нас внутри функции определены переменные с названиями, эдентичными ключам массива, и значениями соответственно. Тоесть, если мы передадим в неё массив
    array( 
            'name'  => 'Вася', 
            'mess'  => 'Привет!' 
         )

то внутри нашей функции, после обработки extract() образуются переменные
    $name = 'Вася'; 
    $mess = 'Привет!';

которые мы и подставим в подключенный шаблон. А дальше вступает в силу буферизация, и мы получаем шаблон с нужными значениями в виде строки. Которую и выдаем, как результат работы функции. Теперь нужно немного изменить контроллер (блок чтения) и все будет в порядке. Весь вывод - в шаблонах. А логика в контроллере.
/**   
* The block of reading of the information   
* Блок чтения информации   
*/  
    $posts = getData('./data/'. $GET['num']);  
    include './libs/bb_tags.php'; 
     
    $rows = '';  
         
    foreach($posts as $id => $post)  
    {  
        $post = htmlChars($post); 
        $post['mess']  = nl2br(bbTags($post['mess']));  
        $rows .= parseTpl('./skins/tpl/second/rows.tpl', $post);        

    }

Вот и всё. Основные принципы я показал. Если есть желание достроить эту гостевуху до полного ажура - теперь Вы знаете, как это делать.
Добавить в общую вьюшку функцию формирования ссылок постранички и организовать такой же модуль админки к примеру.
Лично я не стал бы на Вашем месте тратить на это время и перешел бы к более серьёзным занятиям - следующему разделу.

А вот итог этого занятия.
Теги:
Ядро
Добавлено: 11 Мая 2018 08:41:10 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...