Управление и передача значений на страницах компонента


Памяти Светланы посвящается.


Ссылки

К оглавлению
Справочник: Структура Модуля
Справочник: Структура Шаблона
Справочник: Структура Компонента
Справочник: Библиотека jQuerry
Справочник: Компилирующий обработчик шаблонов Smarty
Справочник: API InstansCMS - руководство для разработчиков

Примечание. С момента написания этой статьи прошло уже довольно много времени, поэтому некоторые ядерные методы InstantCMS уже не используются, или считаются устаревшими и не рекомендуются к использованию. Например, метод request() до сих пор присутствует в ядре (файл /core/cms.php) на строчке 994 (для версии инстанта 1.10.3) и, безусловно, будет работать, как описано ниже. Тем не менее, обращение к этому методу несколько изменилось. Теперь к этому методу стоит обращаться так:

cmsCore::request('do', 'str', 'view_all');

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

Введение

Очень часто при создании компонента или модуля начинающий программист сталкивается с несколько запутаным механизмом передачи значений переменных или массивов между скриптами InstantCMS. На самом деле ничего сложного нет, вся «заковыристость» возникает из совершенно логичной модели Модель-Представление-Контроллер (МПК) или, по английски, Model-View-Controller (MVC).

Упрощения и соглашения

1. Эта статья написана в предположении, что читатель знаком с понятиями объектно-ориентированного программирования. Поэтому, если я пишу строчку вида

$do=$inCore->request('do', 'str', 'view_all');

предполагается, что метод request класса cmsCore уже ранее проинициализирован строчкой

$inCore = cmsCore::getInstance();

и экземпляр $inCore класса cmsCore создан. Аналогичное рассуждение применимо к инициализации других методов.

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

<a href="/museum">{$LANG.MUSEUM}</a>,

а в виде

<a href="/museum">{$LANG.MUSEUM}.html</a>.

Изложеные ниже примеры, конечно, работают, и передают информацию точно также. Суффикс .html в изложении был опущен просто для удобства понимания.

Несколько замечаний перед началом

Любой компонент Инстанта является страницей. Следовательно эта страница должна обладать своим адресом url. Естественно, Вы можете сконструировать любой url, однако желательно, чтобы этот адрес был «человекопонятным». Например, вы даете своему компоненту имя «Музей» (museum). Будет естественно, если url тоже будет содержать это сочетание букв. Например, http://ваш_адрес_сайта.ru/museum будет вести на страницу компонента «Музей».

Простые компоненты содержат всего одну страницу. Как быть, если Вы задумали компонент, содержащий несколько страниц? Для этого следует предусмотреть для каждой страницы свой url. Например, http://ваш_адрес_сайта.ru/museum/add_exibit будет вести на страницу добавления экспоната в музей.

Для перехода к компоненту имеет смысл создать пункт меню и назначить этому пункту вывод компонента. Однако, если Вы задумали интегрировать новый компонет с другими компонентами (или статьями), движок предусматривает и такую возможность.

Для того, чтобы попасть на свою страницу из ЛЮБОГО места Инстанта, вам следует найти и открыть шаблон страницы того компонента, куда Вы хотите поставить ссылку. Например, Вы хотите поставить ссылку на свой компонент из Универсального Каталога. Откройте файл com_catalog_view.tpl и в то место, где Вы хотите видеть свою ссылку, вставьте строку вида

<a href="/museum">{$LANG.MUSEUM}</a>

Естественно, чтобы ссылка отобразилась на русском языке, Вам придется заодно отредактировать и файл languages/ru/components/catalog.php, чтобы определить элемент массива $LANG.MUSEUM. Для этого в файл catalog.php вставьте строку

$_LANG['MUSEUM']='Музей';

Я полагаю, Вы знакомы с доступом к элементам массива из шаблонизатора SMARTY и в php, поэтому подробно останавливаться на этом не буду.

Метод GET и метод POST

Как быть, если Вы хотите передать в свой компонент более сложную информацию? В вашем распоряжении два метода - GET и POST, причем они оба применимы.
Метод GET очень удобен тем, что позволяет сконструировать url таким образом, чтобы в зависимости от значения переменных можно было попасть на разные страницы. Недостатков у метода всего два.

  • Первый - большой объем информации через url не передашь.
  • Второй - передаваемые данные видны в адресе, и, в принципе, могут быть перехвачены. Поэтому этим методом не стоит передавать логины и пароли.

Метод POST несколько сложнее в реализации (больше писанины), но позволяет передавать значительные объемы информации. Вся информация передается помимо адресной строки. Хотя перехватить передачу заголовка с методом POST (и информацию, содержащуюся в этом заголовке)тоже при желании можно.

Передача данных методом GET

Данные в Ваш компонент могут быть направлены из любого места сайта. Это может быть как Ваш разрабатываемый компонент, так и другие компоненты, вроде уже упоминавшегося Универсального Каталога. Например, вы хотите со страницы Универсального Каталога передать в свой компонент значение текущей категории Каталога и id текущей записи. Информация об этих переменных уже передана шаблонизатору в файл com_catalog_view.tpl, поэтому Вам следует немного изменить вид приведенной выше ссылки, написав

<a href="/museum/{$current_category}/{$item.id}">{$LANG.MUSEUM}</a>

В этом случае в дело включается механизм роутера Инстанта. Для этого в файле components/museum/router.php (подробнее о структуре компонента читайте соответствующую статью) Вам следует определить массив $routes как

$routes[] = array(
    '_uri'  => '/^museum\/([0-9]+)\/([0-9]+)$/i',
    'do'    => 'view_exponat',
    1       => 'categogy',
    2	    => 'id_exibit'
);

Подробнее о правилах написания роутера читайте в соответствующей статье. Эти данные должны попасть в файл components/museum/frontend.php. Для этого в этом файле должны быть такие строчки:

$do=$inCore->request('do', 'str', 'view_all');
$categogy=$inCore->request('categogy', 'int', 0); 
$id_exibit=$inCore->request('id_exibit', 'int', 0);

В большинстве компонентов Инстанта переменная $do определяет действие, совершаемое на разных страницах этих компонентов. В случае совпадения url cсылки с регулярным выражением роутера переменной $do присваивается значение 'view_exponat'. Теперь, написав выражение вида

if($do=='view_exponat'){...}

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

Теперь рассмотрим метод POST.

Передача данных методом POST

Как и в случае с методом GET, данные всегда передаются из файла шаблонизатора *.tpl через роутер в файл компонента frontend.php. Для этого используется форма

<form enctype="multipart/form-data" action="/museum/exponat_load" method="POST">
<input......./>
...
<input type="submit" value="{$LANG.UPLOAD}">
<input type="button" onclick="window.history.go(-1);" value="{$LANG.CANCEL}"/>
</form>

Обратите внимание на значение свойства формы enctype=«multipart/form-data». Это свойство можно не упоминать, если Вы не собираетесь отправлять этой формой на сервер файлов. Все остальные данные передаваться будут, как положено. Но при отправке файлов это свойство является обязательным - если Вы забыли его указать, файлы на сервер отправляться не будут.

Естественно, элементы массива $LANG (надписи на кнопках) должны быть заранее определены в языковом файле languages/ru/components/museum.php В роутер вставляем запись

$routes[] = array(
    '_uri'  => '/^museum\/exponat_load$/i',
    'do'    => 'load_exponat'
);

Как видим, параметр action формы имеет значение, совпадающее с регулярным выражением роутера. В случае этого совпадения переменной $do присваивается значение 'load_exponat'. Естественно, внутри файла frontend.php должен быть код if($do=='load_exponat'){…}, включающий получение и обработку данных, переданых внутри формы.

Остановимся на этом чуть подробнее. Все нижеследующие примеры вписываются в форму в том порядке, какой Вы опредеделите, до кнопки SUBMIT.

Галка (чекбокс)

Например, мы хотим передать единицу или ноль в зависимости от установленой или сброшенной галки чекбокса. В форме пишем:

<input name="published"  type="checkbox"  value="1" checked />

В файле frontend.php тогда должна быть строчка

$published = $inCore->request('published', 'int', 0);
Передача файла на сервер и последующая обработка

При передаче файла (например, фотографии) в форме записываем

<input name="Filedata" type="file" size="60" />

В файле frontend.php тогда:

$file=$inDB->escape_string($_FILES['Filedata']['name']); //Здесь имя файла, переданное на сервер
$source=$_FILES['Filedata']['tmp_name']; //Здесь путь к временной папке, куда файл попадает после пересылки 
                                         //на сервер; отсюда он будет удален после завершения скрипта
$errorCode=$_FILES['Filedata']['error']; //Коды ошибок, возникших при пересылке. 

Поскольку файл хранится во временной папке, его следует переместить на постоянное место хранения. Для этого можно воспользоваться методом ядра Инстанта:

$inCore->moveUploadedFile($source, 'путь_к папке_хранения/'.$file, $errorCode);
Передача текста

Для передачи текста пишем внутри формы:

<input name="exponat_name"  type="text" size="40" maxlength="200" value="{$exibit_name}"/>

Естественно, переменная $exibit_name должна быть заранее передана в шаблонизатор. Подробнее об этом чуть ниже. В frontend.php тогда:

$exponat_name=$inCore->request('exponat_name', 'str', "");
Передача скрытого параметра

Если необходимо передать скрытый параметр, например, тот же id экспоната в базе данных, который пользователю, загружающему фото экспоната, совсем не интересен, в форме пишем:

<input name="id_exibit" type="hidden" value="{$id_exibit}"/>

В frontend.php тогда:

$id_exibit = $inCore->request('id_exibit', 'int', 0);
Визуальный редактор WYSIWYG

В движок Инстант интегрирован красивый он-лайн редактор wysiwyg. Если надо передать большую статью с форматированым текстом, можно воспользоваться им. Внутрь формы вставляем:

<input name="max_id" type="hidden" value="{$max_id}"/>
{wysiwyg name="fdata[$max_id]" value=$field.value height=300 width='98%' toolbar='Basic'}

Естественно, переменная $max_id и элемент массива $field['value'] должны быть определены и переданы в шаблонизатор заранее. Переменная $max_id в данном случае содержит id последней записи в базу и пригодится нам при сохрании текста в базу данных. Элемент массива $field['value'] может содержать уже ранее сохраненый текст, который теперь передается шаблонизатору для редактирования в wysiwyg.

Здесь есть один «подводный камень». Если Вы, по привычке, будете принимать в фронтэнде данные через метод request() ядра Инстанта:

$max_id = $inCore->request('max_id', 'int');
$fdata = $inCore->request('fdata', 'array_str', "{$_LANG['NO_EXPONAT']}");
$text = $fdata[$max_id];

то получите полную очистку текста от сгенерированых редактором wysiwyg тегов форматирования. Возможно, это кому-то и пригодится, но если Вы хотите сохранить форматирование, прием данных в фронтэнде следует делать через метод badTagClear():

$max_id = $inCore->request('max_id', 'int');
$fdata = $_POST['fdata'];
$text = trim($inCore->badTagClear($fdata[$max_id]));
Передача массивов

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

<input name="property[0]" type="hidden" value=""/>
<input name="property[1]" type="hidden" value=""/>
<input name="property[2]" type="hidden" value=""/>
<input name="property[3]" type="hidden" value=""/>
.......

Получаем данные в frontend.php:

$propertys = $inCore->request('property', 'array');

Передача значений в шаблонизатор SMARTY

Этот шаблонизатор интегрирован в Инстант и является удобным подспорьем в конструировании компонентов. Про сам SMARTY написаны тонны мануалов, изучив которые, можно создавать вполне приличные страницы. Лично для себя я вижу удобство этого шаблонизатора в том, что он содержит обработку логики, таким образом, от значений передаваемых в него переменных может зависить внешний вид страницы. Мы раньше несколько раз натыкались на упоминание, что некие данные нужно заранее сформировать перед передачей в шаблонизатор. Теперь покажем, как данные передаются в этот шаблонизатор из файла frontend.php. Естественно, для того, чтобы данные куда-то передать, необходим приемник информации. Этим приемником служит написаный Вами файл с расширением *.tpl. Например, файл com_museum_exponat.tpl был написан мною для отображения компонентом Музей разных загруженых в него экспонатов. Тогда в файле frontend.php пишем:

if($do=='view_exponat'){
	... // Здесь принимаем, вычисляем и/или получаем из базы данных все нужные переменные или массивы
        $items  =  array (...);

	$smarty = $inCore->initSmarty('components', 'com_museum_exponat.tpl');   //Инициализация экземпляра класса
		...
        $smarty->assign('items', $items);                                        //Передача значений массива $items
		...
        $smarty->display('com_museum_exponat.tpl');                              //Отображение страницы
}

Как видите, первая строчка содержит инициализацию экземпляра класса, объекта $smarty, которому передается указание, что следует открыть файл templates/текущий_шаблон/components/com_museum_exponat.tpl.

Напомню, что движок ищет этот файл сперва в папке с текущим (включенным) шаблоном. Если находит, открывает и передает управление ему. Если не находит, ищет в папке с дефолтным шаблоном. Это особенно удобно, если Вы написали шаблон, в котором внешний вид страниц компонентов отличается от дефолтного. Однако, если Вы поместите Ваши файлы *.tpl только в свой шаблон, не поместив их копии в дефолтный, в случае включения дефолтного (или другого) шаблона Вы «потеряете» свои страницы, а SMARTY напишет Вам об ошибке.

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

Последняя строчка содержит указание отобразить страницу.


Написал stroller7


Ссылки
 
справочник/управление_и_передача_значений.txt · Последние изменения: 2014/02/19 19:37 От stroller7