ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Начальный практикум в Kohana
  #1  
Старый 31.05.2009, 20:35
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию Начальный практикум в Kohana

Начальный практикум в Kohana
Официальный сайт фреймворка: http://kohanaphp.com/
Русскоязычный сайт фреймворка: http://kohanaphp.ru/ (на данный момент крайне плохо проработан, лучше посещать официальный ресурс)
Версия фреймворка на момент написания статьи: 2.3.2

К сожалению редактор не позволяет создавать структурированный текст, из-за чего большие части кода порой трудно читаются. В этом случае рекомендую Вам скачать PDF-вариант статьи: http://kuzya.name/files/kohana/practical_intro_kohana.pdf (22 страниц, шрифт Times New Roman, 12pt).

Здравствуйте. Данная статья, как и все остальные из этой серии, ориентирована на людей которые умеют пользоваться документацией и хотя бы в малой степени с ней ознакомились. Англоязычное описание фреймворка построено довольно хорошо и понятно. По моему можно даже не знать английского языка, а руководствоваться примерами которые приводят авторы. Многие моменты в статье описываться не будут так как уже описаны в документации. В тексте статьи я постарался выставить ссылки на определённые разделы руководства везде где могут возникнуть вопросы. Вообщем, проблем быть не должно. А если Вы ранее работали с Code Igniter, то постигнуть Kohana не составит никакого труда. Ведь это прямой потомок CI, модернизированный и лишённый многих недостатков.
Думаю стоит отметить что в статье я немного отступаю от стандартов разработки кода в Kohana. В каждый файл разработчики рекомендуют встраивать следующий код.

PHP код:
defined('SYSPATH') OR die('No direct access allowed.'); 
Я его не встраиваю. Просто из привычки. К тому же мне кажется что ничего плохого от этого нет. Вы же можете поступать как захотите.
Ниже я опишу использование базовых инструментов Kohana на примере создания сайта компании торгующей своим программным продуктом (в качестве подопытного будет программа Bred 3). Сайт будет крайне простой и незамысловатый. Состоять он будет из следующих частей:
1. Главная страница с новостями
2. Страница скриншотов программы
3. Раздел оформления заказов
4. Гостевая книга
5. Раздел загрузки программы
В процессе написания ресурса мы постараемся задействовать как можно больше полезных компонентов фреймворка.

1. Подготовка
Первым делом скачайте свежую версию фреймворка. Что интересно, при скачивании Вы можете указать какие модули, библиотеки и языки включать в будущий архив. Дистрибутив, который я использовал при написании этой статьи, не включал в себя никаких дополнительных модулей кроме Archive. Из библиотек я выбрал только SwiftMailer. Ну и в варианте языков кроме английского был выбран русский. После скачивания распакуйте архив на "чистый" хост (у меня он называется kohana, у Вас он может иметь другое имя, учитывайте это в будущем) и обратитесь к нему через браузер. Обращаться следует именно в корень хоста, а не к файлу install.php. Никаких проблем возникнуть не должно и в низу страницы появится надпись "Your environment passed all requirements. Remove or rename the install.php file now." гласящая о том что всё хорошо. Удалите файл install.php и откройте example.htaccess для редактирования. В нём строку

RewriteBase /kohana/

измените на

RewriteBase /

После чего переименуйте файл в .htaccess. Этим мы включили использование mod_rewrite для красивого вида URL. Теперь пройдите по ссылке http://kohana/welcome/index. Браузер должен отобразить страницу приветствия. Если бы мы не производили вышеописанные манипуляции с .htaccess то тоже самое обращение выглядело вот так http://kohana/index.php/welcome/index. Полную информацию по установке фреймворка Вы найдёте тут: http://docs.kohanaphp.com/installation и тут http://docs.kohanaphp.com/installation/troubleshooting (на случай если возникнут какие-то проблемы).
Так же нам нужно немного подчистить конфигурацию от значений по умолчанию. Откройте файл /application/config/config.php. Нас интересуют параметры site_domain и index_page. Из комментариев понятно что первый параметр содержит директорию в которой установлена Kohana. Его значение можно либо вообще удалить, либо заменить на одиночный слэш (корень сайта). Второй параметр обозначает индексный файл фреймворка. Так как мы с помощью .htaccess избегаем использования index.php при обращении к сайту, значение этой ячейки тоже нужно очистить. Если этого не сделать то при автоматической генерации ссылок (например при разбитии материала на страницы) это всплывёт и будет серьёзно мешать. Вообщем, придётся изменять в любом случае.
Теперь займёмся базой данных. Создайте у себя на сервере базу с любым именем. Затем выполните в ней код из файла database.sql. Он создать 2 таблицы - kh_news и kh_gb. Они содержат информацию о новостях и отзывах в гостевой книге соответственно. Для того что бы фреймворк мог нормально к ней подключаться нужно указать необходимые настройки в файле /system/config/database.php. Изначально он имеет следующее содержимое:

PHP код:
$config['default'] = array
(
'benchmark'     => TRUE,
'persistent'    => FALSE,
'connection'    => array
(
'type'     => 'mysql',
'user'     => 'dbuser',
'pass'     => 'p@ssw0rd',
'host'     => 'localhost',
'port'     => FALSE,
'socket'   => FALSE,
'database' => 'kohana'
),
'character_set' => 'utf8',
'table_prefix'  => '',
'object'        => TRUE,
'cache'         => FALSE,
'escape'        => TRUE
); 
Изменим содержимое массива "Connection", его ячейки user, pass, host и database. Подставьте туда свои данные. Вы могли заметить что таблицы у нас имеют префикс "kh_". Укажите его в ячейке "prefix" основного массива. Больше ничего менять не нужно. Более подробная информация по конфигурации БД располагается здесь: http://docs.kohanaphp.com/libraries/database/configuration.
Возьмёмся за локализацию. Если при скачивании дистрибутива Вы выбирали поддержку русского языка то в дирекотрии /system/i18n должна находится папка ru_RU с языковыми файлами. Зайдите в /system/config и откройте файл locale.php. В нём есть всего одна строка отвечающая за используемый язык. По умолчанию она настроена на работу с английским языком.

PHP код:
$config['language'] = array('en_US''English_United States'); 
Замените её на следующую

PHP код:
$config['language'] = array('ru_RU''Russian_Russian Federation'); 
Теперь фреймворк стал русскоязычным. Полная информация по интернационализации фреймворка - http://docs.kohanaphp.com/general/i18n
2. Дизайн
Все необходимые элементы дизайна находятся в соответствующем архиве. В корень хоста, туда где находятся папки application и system, скопируйте директорию images и файл стилей. Находящийся там же шаблон index.php скопируйте в папку application/views, откройте и разбейте на следующие части. Код находящийся с начала шаблона и до открывающего тега "body" поместите в файл header.php.

Код:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Начальный практикум в Kohana - http://kuzya.name</title>
<meta name="keywords" content="" />
<meta name="description" content="" />
<link href="/styles.css" rel="stylesheet" type="text/css" />
</head>
За место него в основной шаблон поставьте код отображения переменной $header.

PHP код:
<?=$header?>
Далее поместите в файл menu.php код начинающийся сразу после комментария "start header" и до комментария "start page"

Код:
<!-- start header -->
<div id="header">
<div id="logo">
<h1><a href="#">Metamorph_global</a></h1>
<h2><a href="http://www.metamorphozis.com/" id="metamorph">Design by Metamorphosis Design</a></h2>
</div>
<div id="menu">
<ul>
<li><a href="/">Главная</a></li>
<li><a href="/screenshots/">Скриншоты</a></li>
<li><a href="/buy/">Купить</a></li>
<li><a href="/gb/">Гостевая</a></li>
<li><a href="/download/">Скачать</a></li>
</ul>
</div>
</div>
<!-- end header -->
<hr />
На его место вставьте код отображения переменной $menu

PHP код:
<?=$menu?>
Ну и всё начиная с комментария "start footer" и до конца файла перенесите в файл footer.php, поместив за место него соответствующий код.

PHP код:
<?=$footer?>

Последний раз редактировалось Kuzya; 31.05.2009 в 22:27..
 
Ответить с цитированием

  #2  
Старый 31.05.2009, 20:43
Аватар для gibson
gibson
Moderator - Level 7
Регистрация: 24.02.2006
Сообщений: 447
Провел на форуме:
2872049

Репутация: 705
Отправить сообщение для gibson с помощью ICQ
По умолчанию

Тема сисек не раскрыта, пересмотри материал, не нужно "тупо" копипастить со своего ресурса.

Опиши все по подробней или дай ссылки где про то или иное можно прочитать.

не добавишь, придеться удалить из за недостатка материала.
 
Ответить с цитированием

  #3  
Старый 31.05.2009, 22:15
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

3. Программирование
3.1 Главная страница, новости.

Новости должны располагаться в виде ленты на главной странице. Для начала сделаем обычный вывод тех шаблонов, которые мы только что сформировали. Создадим контроллер новостей и как действие по умолчанию впишем это отображение (Информация по контроллерам - http://docs.kohanaphp.com/general/controllers и работе с отображениями - http://docs.kohanaphp.com/general/views).

PHP код:
class News_Controller extends Controller {
public function 
index() {
// Обрабатываем все шаблоны
$view           = new View('index');
// Переменный header, menu и footer
$view->header   = new View('header');
$view->menu     = new View('menu');
$view->footer    = new View('footer');

// Показываем
$view->render(true);
}

Сохраните контроллер в соответствующей папке и обратитесь по ссылке http://kohana/news/. Вы должны увидеть пустой шаблон со словом "text" вместо основного контента.


Из за того что на главной странице всегда должна отображаться лента новостей мы сделаем её контроллер контроллером по умолчанию. Для этого откройте файл /system/config/routes.php и единственную настройку установите в значение "news"

PHP код:
$config['_default'] = 'news'
После этого обращения к корню сайта будут автоматически вызывать контроллер новостей.
Вернёмся к коду. Сейчас нам нужно вывести все имеющиеся новости на экран. Они находятся в базе и надо их оттуда достать. Для этого создадим новую модель (http://docs.kohanaphp.com/general/models) News_Model в файле /application/models/news.php. В неё поместим конструктор создающий объект БД для этой модели и пустой метод который будет получать список новостей. Назовём его "newsList"

PHP код:
class News_model extends Model {
public function 
__construct() {
parent::__construct();
// Создаём новый объект БД
$this->db = new Database();
}
public function 
newsList() {

}

Этот метод должен будет возвратить массив новостей. Для их получения из базы мы воспользуемся конструктором запросов (http://docs.kohanaphp.com/libraries/database/builder). На данный момент нам пригодятся лишь 3 метода - from (указывает из какой таблицы взять данные), orderby (указание сортировки данных) и get (получение данных). Выполним их по очереди, а результат работы метода get вернём в качестве результата функции.

PHP код:
$this->db->from("news");
$this->db->orderby("id","DESC");
return 
$this->db->get(); 
Это эквивалентно запросу "SELECT * FROM `news` ORDER BY `id` DESC". В контроллере нам нужно вызвать вышеописанный метод и передать то что он вернёт в отображение. Там с помощью foreach-цикла мы обойдём массив новостей и отобразим всё одной лентой. Назовём параметр шаблонизатора, содержащий список новостей, newsList, по аналогии с методом модели. Сразу после обработки шаблона "index" добавьте вызов метода модели.

PHP код:
$view->newsList $this->news->newsList(); 
Параллельно с этим нам нужно создать конструктор у контроллера новостей, в котором модель будет автоматически подгружаться что бы в дальнейшем быть доступной из методов контроллера.

PHP код:
public function __construct() {
parent::__construct();
$this->news = new News_Model;

Не забывайте в конструкторах прописывать вызовы конструктора класса-предка, иначе за место сайта получите горы ошибок. Откройте шаблон "index.php" и за место слова text добавьте следующий код.

Код:
 <?foreach ($newsList as $news):?>
<h1 class="title"><a href="/news/view/<?=$news->id?>"><?=$news->title?></a></h1>
<p class="meta"><small><?=date('d-m-Y',$news->pub_date)?></small></p>
<div class="entry">
<!-- Показываем анонс - 200 символов от всего текста -->
<p><?=substr($news->text,0,200)?>...</p>
</div>
<?endforeach;?>
Теперь на главной странице отображаются все 4 новости которые находятся в базе.
Отойдём от основной темы и вернёмся к модели новостей. Формируя запрос в методе newsList мы написали 3 строки кода. Но конструктор запросов к БД в Kohana имеет одну интересную особенность. Вызываемые методы конструктора возвращают в качестве результата свой же объект (в нашем случае $this->db). То есть мы из вызова одного метода можем вызывать другие методы, выстраивая так называемую "цепочку". Вот пример такого вызова. Этот код можно поставить за место тех трёх строк.

PHP код:
return $this->db->from("news")->orderby("id","DESC")->get(); 
Результат работы от этого не изменится, но кода стало значительно меньше. Такой подход сильно облегчает жизнь при разработке больших проектов.
В начале статьи я писал про разбиение контента на страницы. У нас 4 новости, давайте разобьём их на 2 страницы, отображая 3 новости за раз. Воспользуемся классом "Pagination" (http://docs.kohanaphp.com/libraries/pagination). Перед тем как его задействовать нужно определится с настройками. При разбиении контента они передаются классу Pagination двумя способами - через специальный конфигурационный файл (/system/config/pagination.php) или же массивом прямо при создании объекта. Мне кажется что первый вариант лучше не использовать так как он является "центральным", а разбиение может понадобится не только в одном контроллере или методе. Пойдём по пути массива с настройками. Нам понадобится всего 4 опции
1. base_url - ссылка куда будет подставляться номер страницы. В нашем случае эта опция примет значение "/news/index/" потому что третьей частью адреса будет именно номер страницы.
2. total_items - общее количество объектов. В модель мы добавим метод который вернёт число новостей.
3. items_per_page - сколько объектов отображать на страницу. Мы отображаем по 3 новости.
4. style - стиль отображения ссылок. Здесь укажем "digg". На мой взгляд он выглядит приличнее остальных.
Метод возвращающий количество новостей в базе будет называться "newsCount" и содержать всего одну строку:

PHP код:
public function newsCount() {
return 
$this->db->count_records("news");

Поместите его в модель и вернёмся к контроллеру. Массив с настройками и их значениями можно объявить прямо в начале метода index:

PHP код:
// Настройки разбиения на страницы
$pagination_config = Array('base_url'              => '/news/index/',
'total_items'        => $this->news->newsCount(),
'items_per_page' => 3,
'style'                   => 'digg'
); 
И сразу можно создать общедоступный объект класса Pagination, передав ему в конструктор массив с настройками.

PHP код:
$this->pagination = new Pagination($pagination_config); 
Обратите внимание на то что объект имеет вид не локальной переменной ($pagination). Сделано это для того чтобы мы могли обращаться к нему из отображения без лишних проблем. Теперь в шаблоне "index.php" разместим код который вызовет отображение ссылок на страницы.

Код:
<center><?=$this->pagination->render()?></center>
Он должен идти сразу после foreach-цикла. Сохраните все изменения и обновите главную страницу. В низу покажется список страниц со ссылками на предыдущую и следующую страницы.
На очереди ограничение вывода новостей. Ссылка на вторую страницу имеет вид http://kohana/news/index/2, то есть номер страницы передаётся методу index как единственный параметр. Обозначим его, изменив объявление метода.

PHP код:
public function index($page 0) { 
Так как изначально параметр не передаётся (например, при обращении к главной странице) то мы указали его значение по умолчанию. Теперь значение переменной $page нужно передать в модель, в метод выборки новостей. Заменим код его вызова с

PHP код:
$view->newsList $this->news->newsList(); 
на

PHP код:
$view->newsList $this->news->newsList($page); 
Ну и соответственно добавим методу newsList один параметр.

PHP код:
public function newsList($page) { 
Вместе с этим вставим в формирование запроса вызов метода "limit", где укажем ограничение на выборку новостей

PHP код:
limit(3,$page*3
Здесь есть один важный момент. Так как отсчёт страниц у нас начинается ни с нуля (фактически нулевой страницы нет, как и ссылки на неё) то нам нужно постоянно уменьшать значение страницы на единицу. Если Вы сейчас попробуйте посмотреть новости то на главной странице у Вас покажутся 3 последние, а на второй новостей не будет вообще. Потому что при просмотре второй страницы, формируя лимит новостей, значение с которого нужно начать отбирать будет равно 6 ($page*3), а не 3. Поэтому в начало метода модели следует добавить строчку декремента параметра $page

PHP код:
$page--; 
А что бы при нулевом значении в первую границу limit не попадало число -3 (-1*3) мы изменим эту строку на

PHP код:
if($page 0$page--; else $page 0
Таким образом, после наших многочисленных манипуляций, полный код метода index, контроллера новостей становится следующий.

PHP код:
public function index($page 0) {
// Настройки разбиения на страницы
$pagination_config = Array('base_url'       => '/news/index/',
'total_items'    => $this->news->newsCount(),
'items_per_page' => 3,
'style'          => 'digg'
);
$this->pagination = new Pagination($pagination_config);
// Обрабатываем все шаблоны
$view           = new View('index');
$view->header   = new View('header');
$view->menu     = new View('menu');
$view->footer   = new View('footer');
$view->newsList $this->news->newsList($page);

// Показываем
$view->render(true);

А два метода модели выглядят вот так.

PHP код:
public function newsList($page) {
if(
$page 0$page--; else $page 0;

return 
$this->db->from("news")->limit(3,$page*3)->orderby("id","DESC")->get();

PHP код:
public function newsCount() {
return 
$this->db->count_records("news");

Единственное что осталось - написать метод просмотра полной новости. Как Вы могли заметить из кода главного шаблона, его имя "view".
Действие просмотра новости крайне простое. Нужно лишь взять информацию из базы и вывести её в шаблон. Ссылка показа новости имеет следующий вид: http://kohana/news/view/4. То есть в качестве идентификатора новости у нас передаётся её id. Он же является единственным параметром для нашего метода. Сначала создадим в модели функцию которая будет получать данные о новости по её id.

PHP код:
public function newsData($id) {
$result $this->db->from("news")->where("id",(int) $id)->get();
return 
$result[0];

Теперь опишем метод view в контроллере.

PHP код:
public function view($id) {
$view  = new View('./news/view');
$view->header = new View('header');
$view->menu   = new View('menu');
$view->footer = new View('footer');
$view->news   $this->news->newsData($id);

$view->render(true);

Из кода видно что данные новости передаются в шаблон через переменную news. Сам код шаблона точно такой же как на главной странице, но с тремя отличиями. В нём нет цикла (мы же выводим одну новость), строки разбиения на страницы, и полный текст новости показывается целиком, а не первые 200 символов.

Код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<h1 class="title"><a href="/news/view/<?=$news->id?>"><?=$news->title?></a></h1>
<p class="meta"><small><?=date('d-m-Y',$news->pub_date)?></small></p>
<div class="entry">
<p><?=$news->text?></p>
</div>
</div>
</div>
<!-- end content -->
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<hr />
<?=$footer?>
Вот и всё. Новостная часть полностью готова. Идём дальше.
 
Ответить с цитированием

  #4  
Старый 31.05.2009, 22:16
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

3.2 Скриншоты.
Отображать скриншоты программы мы будем на отдельной странице. Они будут считываться из директории /images/screenshots (скопируйте туда содержимое соответствующей папки из архива с дополнительными файлами) и выводится в уменьшенном размере на страницу. Директория здесь используется для того что бы не заморачиваться с различными панелями загрузки скриншотов. Закинул картинку в папку - она отобразилась на сайте. Всё просто.
В самом начале мы получим список уже имеющихся в директории изображений. Это действие я решил поместить в модель. Возможно помещение его в контроллере тоже было бы правильным, но мне кажется что раз происходит операция с данными то находится она должна в модели. Создайте пустую модель Screenshots_model и поместите туда единственный метод под именем imagesList.

PHP код:
class Screenshots_Model extends Model {
public function 
imagesList() {

}

С помощью функции scandir мы обработаем папку скриншотов и вернём список существующих картинок.

PHP код:
// Получаем список файлов
$images scandir("./images/screenshots");

// Убираем "." и ".."
for($i 0$i count($images); $i++) {
if(
$images[$i] == "." OR $images[$i] == "..")
unset(
$images[$i]);
}

return 
$images
Теперь передадим эти данные в отображение и выведем пользователю. Конечно, надо написать функцию изменения размера изображений, ведь скриншот может быть большим и весить несколько мегабайт. Мы её опишем в контроллере Screenshots применяя библиотеку для работы с изображениями (http://docs.kohanaphp.com/libraries/image). Назовём эту функцию resize. У неё будет 2 входящих параметра - имя картинки и требуемая ширина.

PHP код:
// Нам нужно только имя файла, а не всякие ../file
$image basename($image);
// Создаём новый объект Image
$image = new Image("./images/screenshots/{$image}");
// Изменяем размер изображения основываясь его на ширине
$image->resize($width200Image::WIDTH);
// Выводим изображение
$image->render(); 
Обратите внимание на то что методу resize, объекта image, третьим параметром мы передаём значение константы Image::WIDTH. Это нужно для того что бы размер изображения изменялся с сохранением пропорции основываясь на ширине. То есть цифра 200 указывающая высоту в нашем случае ничего не значит.

Так как мы собрались передавать массив изображений в шаблон, то нам ничего не стоит вывести код показа изменённого изображения. В самом контроллере нам нужно лишь поработать с отображениями - вывести их и передать результат работы "imagesList"

PHP код:
public function index() {
$view  = new View('screenshots/index');

$view->header        = new View('header');
$view->menu          = new View('menu');
$view->footer          = new View('footer');
$view->screenshots $this->screenshots->imagesList();

$view->render(true);

В шаблоне мы обойдём массив с помощью цикла foreach и отобразим картинки вот с такими источниками:

/screenshots/resize/имя_изображения/300

Так же мы организуем в отображении счётчик и после вывода каждых двух картинок будем создавать новую строку.

PHP код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<h1 class="title"><a href="/screenshots/">Скриншоты нашей программы</a></h1>
<div class="entry">
<p>
<table width="100%" cellspacing="10" cellpadding="5">
<tr>
<?$i 0;?>
<?
foreach($screenshots as $screenshot):?>
<!--Если остаток от деления на 2 - 0 (число кратно 2) то начинаем новую строку-->
<?if(!fmod($i,2)):?></tr><tr><?endif;?>
<td>
<img src="/screenshots/resize/<?=$screenshot?>/300" onClick="window.open('/screenshots/resize/<?=$screenshot?>/800');"/>
</td>
<?$i++;?>
<?
endforeach;?>
</tr>
</table>
</p>
</div>
</div>
</div>
<!-- end content -->
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<?=$footer?>
Сохраните этот шаблон под именем index.php в папке /application/view/screenshots/
В итоге мы должны получить следующее.


И сколько бы мы не клали изображений в директорию скриншотов - страница будет вытягиваться только вниз. Вы могли заметить что в коде шаблона, при отображении картинки, указывается событие onClick. В нём прописан код открытия скриншота шириной 800 пикселей.
 
Ответить с цитированием

  #5  
Старый 31.05.2009, 22:16
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

3.3 Оформление покупки.
В отдельном разделе нашего сайта посетителям должна предоставляться возможность оформить заказ на программу. Они будут делать это с помощью формы, в которой нужно указать все необходимые регистрационные данные. После чего запрос уйдёт на E-mail менеджеру.
Создайте контроллер buy с методом index. Разместим в нём код показа формы, которую клиент должен будет заполнить. Вот её шаблон. Сохраните его в директории отображений, в папке buy, под именем index.php.

Код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<h1 class="title"><a href="/buy/">Купить программу</a></h1>
<div class="entry">
<p>
<form action="/buy/send/" method="POST" >
<table width="100%" cellspacing="10" cellpadding="5">
<tr>
<td width="25%">Ваше ФИО:</td>
<td><input type="text" name="fio" /></td>
</tr>
<tr>
<td width="25%">E-mail для связи:</td>
<td><input type="text" name="email" /></td>
</tr>
<tr>
<td width="25%">Тип необходимой лицензии:</td>
<td>
<select name="license">
<option value="0">Корпоративная</option>
<option value="1">Домашняя</option>
</select>
</td>
</tr>
<tr>
<td width="25%">Тип программы:</td>
<td>
<select name="type">
<option value="0">Lite</option>
<option value="1">Standart</option>
<option value="2">Pro</option>
</select>
</td>
</tr>
<tr>
<td width="25%">Дополнительная информация:</td>
<td><textarea name="additional" rows="7"></textarea></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Отправить заявку"/></td>
</tr>
</table>
</form>
</p>
</div>
</div>
</div>
<!-- end content -->

<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<?=$footer?>
И код контроллера.

PHP код:
class Byu_Controller extends Controller {
public function 
index() {
$view               = new View('buy/index');
$view->header = new View('header');
$view->menu   = new View('menu');
$view->footer  = new View('footer');

$view->render(true);
}

Ничего сложного. После отправки формы информация передаётся методу send. В него поместим код отправки письма менеджеру. Отправка будет происходить с помощью SwiftMailer (хэлпер email - http://docs.kohanaphp.com/helpers/email). Сначала получим нужные данные

PHP код:
$fio        $_POST['fio'];
$email    $_POST['email'];
$license = ((int) $_POST['license']) ? "Домашняя" "Корпоративная";

$type       = (int) $_POST['type'];
switch(
$type) {
case 
1$type "Lite"; break;
case 
2$type "Standart"; break;
case 
3$type "Pro"; break;
}

$additional nl2br($_POST['additional']); 
Затем формируем информацию для письма.

PHP код:
$to            "manager@company.com";
$from       "site@company.com";
$subject    "Заказ на покупку программы";
$message  "Здравствуйте. {$fio}($email) оформил заказ на покупку нашей программы.<br />";
$message .= "Выбранный тип лицензии - `{$license}`, тип программы - `{$type}`<br />";
$message .= "Дополнительная информация от клиента: {$additional}"
И отправим сообщение.

PHP код:
email::send($to$from$subject$messageTRUE); 
Параллельно с этим нужно показать пользователю сообщение о том что заказ отправлен и скоро ему ответят. Возьмём для этого следующий шаблон и сохраним его под именем sended.php в той же директории.

PHP код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<div class="entry">
<p>
Спасибо за заказ. Наш менеджер обработает его в самое ближайшее время и вышлет ответ на указанный Вами E-mail.
</p>
</div>
</div>
</div>
<!-- end content -->
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<?=$footer?>
И внесём отображение в контроллер. В итоге код метода send примет следующий вид.

PHP код:
public function send() {
$fio        $_POST['fio'];
$email      $_POST['email'];
$license    = ((int) $_POST['license']) ? "Домашняя" "Корпоративная";

$type       = (int) $_POST['type'];
switch(
$type) {
case 
1$type "Lite";
case 
2$type "Standart";
case 
3$type "Pro";
}

$additional nl2br($_POST['additional']);

$to         "manager@company.com";
$from    "site@company.com";
$subject "Заказ на покупку программы";
$message "Здравствуйте. {$fio}($email) оформил заказ на покупку нашей программы.<br />";
$message .= "Выбранный тип лицензии - `{$license}`, тип программы - `{$type}`<br />";
$message .= "Дополнительная информация от клиента: {$additional}";

email::send($to$from$subject$messageTRUE);

$view  = new View("buy/sended");

$view->header = new View('header');
$view->menu   = new View('menu');
$view->footer = new View('footer');

$view->render(true);

Если Вы сейчас отправите форму, то увидите сообщение об обработке заказа. А с сайта, на адрес manager@company.com, уйдёт письмо с введённой информацией. Те кто используют Denwer могут убедится в этом просмотрев папку /tmp/!sendmail.
Но, что бы клиент случайно не пропустил одно из важных полей, мы организуем проверку данных с помощью валидации (http://docs.kohanaphp.com/libraries/validation). Создадим объект класса Validation, передав ему в конструктор массив $_POST. После этого мы обозначим 2 правила. Обязательно должны быть заполнены поля с ФИО и E-mail`ом. И указанный E-mail должен иметь соответствующий формат.

PHP код:
$post = new Validation($_POST);
$post->add_rules('fio','required');
$post->add_rules('email','required','email'); 
Теперь, вызвав метод validate, мы можем проверить совпадают ли с указанными правилами поля массива $_POST. В зависимости от решения этого метода мы либо отправим письмо, либо сообщим о допущенных ошибках.
Немного отойдём от основной темы. Для того что бы отобразить пользователю тексты ошибок мы должны создать языковой файл с ними. Пройдите в директорию /system/i18n/ru_RU и создайте там файл form_errors.php. В него мы должны поместить массив с фраз. Он будет состоять из двух ячеек, названных аналогично полям формы. В ячейках будет содержаться текст ошибок, у которого ключами будут имена правил.

PHP код:
<?php

$lang 
= Array(
'email' => Array(
'required' => 'Вы должны обязательно указать E-mail для связи',
'email'    => 'Введённый вами E-mail ошибочен'
),
'fio' => Array(
'required' => 'Вы должны указать Фамилию, Имя, Отчество'
)
);

?>
Теперь нужно встроить в контроллер обработку данных. Массив же ошибок можно получить сразу после вызова метода validate, из функции errors. Ей в качестве параметра нужно передать имя используемого языкового файла без расширения. Полученный текст мы передадим в шаблон. При отображении просто будем проверять - если массив с ошибками есть то выводим их, если нет - сообщаем об отправке письма. Вот полный код получившегося метода send.

PHP код:
public function send() {
$view         = new View('buy/sended');
$view->header = new View('header');
$view->menu   = new View('menu');
$view->footer = new View('footer');

// Валидация. Установка правил.
$post = new Validation($_POST);
$post->add_rules('fio','required');
$post->add_rules('email','required','email');

// Отсылаем письмо если всё нормально
if($post->validate()) {
$fio        $_POST['fio'];
$email      $_POST['email'];
$license    = ((int) $_POST['license']) ? "Домашняя" "Корпоративная";

$type       = (int) $_POST['type'];
switch(
$type) {
case 
0$type "Lite"; break;
case 
1$type "Standart"; break;
case 
2$type "Pro"; break;
}

$additional nl2br($_POST['additional']);

$to      "manager@company.com";
$from    "site@company.com";
$subject "Заказ на покупку программы";
$message "Здравствуйте. {$fio}($email) оформил заказ на покупку нашей программы.<br />";
$message .= "Выбранный тип лицензии - `{$license}`, тип программы - `{$type}`<br />";
$message .= "Дополнительная информация от клиента: {$additional}";

email::send($to$from$subject$messageTRUE);

} else {
// Если нет, передаём в отображение все ошибки
$view->validation_errors $post->errors('form_errors');
}

$view->render(true);

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

Код:
<?if(isset($validation_errors)):?>
Внимание! Обнаружены следующие ошибки:
<ul>
<?foreach($validation_errors as $error):?>
<li><?=$error?></li>
<?endforeach;?>
</ul><br />
Вернитесь пожалуйста <a href="/buy/">назад</a> и заполните форму правильно.
<?else:?>
Спасибо за заказ. Наш менеджер обработает его в самое ближайшее время и вышлет ответ на указанный Вами E-mail.
<?endif;?>
Теперь зайдите на страницу оформления заказа и отправьте форму не заполнив поля. Вы должны увидеть страницу с ошибками.



При правильном же заполнении формы пользователь увидит то же сообщение что и раньше.
 
Ответить с цитированием

  #6  
Старый 31.05.2009, 22:17
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

3.4 Гостевая книга.
Поработаем над гостевой. В базе данных, во второй таблице, kh_gb, уже имеется 2 отзыва о программе. Сделаем сначала их вывод, а затем и добавление.
Сперва создайте пустую модель Gb_Model с конструктором, в котором создаётся объект класса Database (как в модели новостей)

PHP код:
class Gb_Model extends Model {
public function 
__construct() {
parent::__construct();
$this->db = new Database();
}

Затем создайте контроллер с пустым методом index и конструктором создающим объект модели.

PHP код:
class Gb_Controller extends Controller {

public function 
__construct() {
parent::__construct();
$this->gb = new Gb_Model;
}

public function 
index() {

}

Далее, в модели создадим метод answersList, который будет возвращать массив отзывов гостевой книги.

PHP код:
public function answersList() {
return 
$this->db->from("gb")->orderby("id","DESC")->get();

В контроллере мы вызовем отображение шаблона /application/views/gb/index.php и передадим в него список отзывов в параметре answersList.

PHP код:
public function index() {
$view           = new View('gb/index');
$view->header   = new View('header');
$view->menu     = new View('menu');
$view->footer   = new View('footer');
$view->answersList $this->gb->answersList();

$view->render(true);

И сам код шаблона гостевой.

Код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<?foreach ($answersList as $answer):?>
<h2 class="title">
<b>
<?=$answer->author?>(<?=date('d-m-Y',$answer->pub_date)?>)
</b>
</h2>
&nbsp;&nbsp;&nbsp;<?=$answer->text?>
<?endforeach;?>
</div>
</div>
<!-- end content -->
<!-- start sidebar two -->

<!-- end sidebar two -->
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<?=$footer?>
Сейчас обратитесь к главной странице гостевой книги. Должно отобразиться 2 записи.
Теперь разберёмся с формой добавления отзыва. Она будет содержать всего 2 поля - имя и текст сообщения.

Код:
<br />
<br />
<form action="/gb/send/" method="POST" >
<table width="100%" cellspacing="10" cellpadding="5">
<tr>
<td width="15%">Ваше имя:</td>
<td width="85%"><input type="text" name="name" /></td>
</tr>
<tr>
<td colspan="2"><textarea name="text" rows="7"></textarea></td>
</tr>
<tr>
<td colspan="2" width="30%"><input type="submit" value="Отправить отзыв"/></td>
</tr>
</table>
</form>
Добавьте его сразу после окончания цикла вывода отзывов. В модель добавим метод add, который будет вставлять в таблицу новую запись принимая 2 параметра соответствующих полям формы.

PHP код:
public function add($name,$text) {
$this->db->insert("gb",Array("author"=>$name,"text"=>$text,"pub_date"=>time()));

В контроллере мы позаботимся о безопасности с помощью хэлпера security (http://docs.kohanaphp.com/helpers/security). Воспользуемся его методом xss_clean(). А после добавления записи перенесём пользователя на главную страницу с помощью метода redirect, хэлпера url (http://docs.kohanaphp.com/helpers/url).

PHP код:
public function send() {
$name security::xss_clean($_POST['name']);
$text security::xss_clean($_POST['text']);

$this->gb->add($name,$text);

url::redirect("/gb/");

Обратите внимание на то что если в файле /application/config/config.php параметр "global_xss_filtering" установлен в значение "true" то входящие данные автоматически проходят XSS-фильтрацию.
Дальше введём валидацию. Нам нужно будет лишь проверять поля формы на пустоту.

PHP код:
$post = new Validation($_POST);
$post->add_rules("*","required"); 
Откроем языковой файл с ошибками и добавьте туда ещё 2 поля из этой формы.

PHP код:
'name' => Array(
'required' => 'Вы должны указать своё имя'
),
'text' => Array(
'required' => 'Заполните поле сообщения'
), 
Добавим ещё фразу для поля captcha. Ниже мы соорудим проверку на робота.

PHP код:
'captcha' => Array(
'required' => 'Введите текст с картинки'

Для вывода ошибок создадим отдельный шаблон аналогичный шаблону ошибок заказа. Назовём его error.php.

Код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<div class="entry">
<p>
Внимание! Обнаружены следующие ошибки:
<ul>
<?foreach($validation_errors as $error):?>
<li><?=$error?></li>
<?endforeach;?>
</ul><br />
Вернитесь пожалуйста <a href="/gb/">назад</a> и заполните форму правильно.
</p>
</div>
</div>
</div>
<!-- end content -->
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<?=$footer?>
Ну и соответствующим образом поменяем код функции добавления.

PHP код:
public function send() {
// Валидация
$post = new Validation($_POST);
// Все поля должны быть заполнены
$post->add_rules("*","required");
// Если всё правильно то добавляем запись
if($post->validate()) {
// Чистим данные
$name security::xss_clean($_POST['name']);
$text security::xss_clean($_POST['text']);
// Добавляем их в базу
$this->gb->add($name,$text);
// Переносим пользователя
url::redirect("/gb/");
}
// Если же валидация не прошла то показываем ошибки
$view = new View("gb/error");

$view->header = new View('header');
$view->menu   = new View('menu');
$view->footer = new View('footer');
$view->validation_errors $post->errors("form_errors");

$view->render(true);

Теперь стоит позаботится о спам-защите и воспользовать Captcha. Благо в Kohana уже есть встроенная библиотека для решения таких задач (http://docs.kohanaphp.com/libraries/captcha). Создадим объект этой библиотеки в методе index и передадим в отображение результат работы функции render - она выводит html-код показывающий защитную картинку.

PHP код:
public function index() {
$captcha = new Captcha;

$view  = new View('gb/index');

$view->header   = new View('header');
$view->menu     = new View('menu');
$view->footer    = new View('footer');
$view->answersList $this->gb->ansersList();
// Передаём код <img src...
$view->captcha  $captcha->render();

$view->render(true);

И в шаблон формы сразу после поля сообщения добавим код отображения картинки и поля ввода.

Код:
<tr>
<td colspan="2"><?=$captcha?></td>
</tr>
<tr>
<td width="15%">Текст с изображения</td>
<td width="85%"><input type="text" name="captcha" /></td>
</tr>
Далее, в контроллер, в функцию добавления встроим проверку введённого с картинки текста. Для этого строку

PHP код:
if($post->validate()) { 
поменяем на

PHP код:
if($post->validate() AND Captcha::valid($_POST['captcha'])) { 
И в конце функции передадим в отображение (сразу после объявления свойства validation_errors) информацию о том что текст введён не правильно.

PHP код:
if(!Captcha::valid($_POST['captcha']))
$view->captcha_error true
А в отображении, прямо перед выводом ошибок валидации, мы встроим проверку на истинность параметра captcha_error.

Код:
<?if($captcha_error):?>
<li>Неправильно введён текст с картинки</li>
<?endif;?>
 
Ответить с цитированием

  #7  
Старый 31.05.2009, 22:18
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

3.5 Страница загрузки
Самый последний и самый лёгкий раздел. На этой странице пользователю будет предложено скачать программу в различных вариантах (архивы или exe-файл). Создайте контроллер download, а в нём метод отображающий страницу applications/views/download/index.php. Кода контроллера я приводить не буду потому что выше такие простые операции уже описывались. Вот код шаблона.

Код:
<?=$header?>
<body>
<?=$menu?>
<!-- start page -->
<div id="page">
<!-- start content -->
<div id="content">
<div class="post">
<h1 class="title"><a href="/download/">Скачать</a></h1>
<div class="entry">
<p>
<a href='/bred.exe'>Как EXE-файл</a><br />
<a href='/download/archive/zip/'>Как ZIP-архив</a><br />
<a href='/download/archive/tar/'>Как TAR-архив</a><br />
</p>
</div>
</div>
</div>
<!-- end content -->
<div style="clear: both;">&nbsp;</div>
</div>
<!-- end page -->
<hr />
<?=$footer?>
Как видно из шаблона, ссылка загрузки exe-файла ведёт прямо на него, а архивных файлов - на действие archive. И в случае с архивом, в ссылке передаётся его тип. Осуществлять формирование архивов мы будем с помощью модуля Archive (документация по нему - http://docs.kohanaphp.com/addons/archive). Просто создадим объект этого класса, добавим в него файл дистрибутива и выведем пользователю. Архив будем формировать в зависимости от переданного типа. По умолчанию будем использовать zip-архивы.

PHP код:
public function archive($type) {
// В зависимости от типа формируем архив
switch($type) {
case 
"zip":
$this->archive = new Archive("zip");
break;
case 
"tar":
$this->archive = new Archive("tar");
break;
// По умолчанию zip
default:
$type "zip";
$this->archive = new Archive("zip");
break;
}

// Добавляем в архив программу
$this->archive->add("bred.exe");
// Скачиваем под именем bred.расширение
$this->archive->download("bred.{$type}");

Вот и всё. Наш сайт полностью готов.

4. Заключение.
Мне очень понравился данный фреймворк. Раньше я думал что фреймворков проще Code Igniter просто быть не может. Но, как говорится, нет пределов совершенству. Вообщем от работы с Kohana я в восторге. Надеюсь на Вас он произвёл то же самое впечатление. Удачи!
P.S. Если у Вас что-то не получилось то Вы можете взять готовый исходный код в файле ready.zip.

5. Приложенные файлы
1.http://kuzya.name/files/kohana/ready.zip – готовый вариант сайта
2.http://kuzya.name/files/kohana/design.zip — дизайн
3.http://kuzya.name/files/kohana/database.sql — код базы данных
4.http://kuzya.name/files/kohana/additional_files.zip — дополнительный файлы (скриншоты + дистрибутив Bred3).
 
Ответить с цитированием

  #8  
Старый 31.05.2009, 22:22
Аватар для Kuzya
Kuzya
Участник форума
Регистрация: 27.04.2008
Сообщений: 224
Провел на форуме:
140661

Репутация: 313
По умолчанию

Извиняюсь перед посетителями за то что после публикации первой части долго не было остальных. В силу определённых обстоятельств я не смог сразу опубликовать остальные куски статьи.
Цитата:
Тема сисек не раскрыта
Если ты ещё в возрасте "темы сисек" то не думаю что статья вообще будет интересна.
Цитата:
пересмотри материал, не нужно "тупо" копипастить со своего ресурса.
Про Cake и CI тоже было "тупо скопипастено с моего ресурса" и ничего, людям нравилось. Просто статьи я публикую у себя, здесь и ещё на 1 форуме. У меня они появляются пораньше на пару дней (по личным соображениям).
Цитата:
не добавишь, придеться удалить из за недостатка материала.
Удалишь - твоя воля.
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Начальный практикум в CakePHP Kuzya Авторские статьи 7 20.03.2009 11:13
Начальный практикум в Code Igniter Kuzya Авторские статьи 9 20.02.2009 23:12



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ