В прошлом уроке у нас была теория, а в этом немного попрактикуемся. Будем дорабатывать наш блог.
Мы уже сделали выборку всех статей из базы данных и вывели их на главной странице. Теперь нам нужно вывести не все статьи, а только одну. Для этого нужно знать ее идентификатор. Добавим ссылку «Подробнее» в файл Вида show.php:
<h3>Это главная страница</h3> <br /> <?php foreach($articles as $article): ?> <div style="padding:10px; margin-bottom:10px; border-bottom:#333 2px solid;"> <strong><?php echo $article['title']; ?></strong><br /> <i>Автор: <?php echo $article['author']; ?></i> / <i>Дата публикации: <?php echo $article['date']; ?></i><br /><br /> <p><?php echo $article['content_short']; ?></p> <p style="text-align:right; text-decoration:underline;"> <a href="<?php echo URL::site('articles/'. $article['id'] .'-'. $article['alt_title']); ?>">Подробнее</a> </p> </div> <?php endforeach; ?>
А также немного изменим нашу таблицу articles и добавим туда два поля.
ALTER TABLE `articles` ADD `alt_title` VARCHAR(250) NOT NULL COMMENT 'Название в урл' AFTER `title`; ALTER TABLE `articles` ADD `content_full` TEXT NOT NULL COMMENT 'Полный текст статьи';
Поле «alt_title» будет отвечать за название статьи в адресной строке. Заполните его значениями «about_framework», «yii_framework» и «symfony_framework». Поле «content_full» будет отвечать за полный текст статьи, который пользователь увидит при нажатии на кнопку «Подробнее». Продублируйте текст из поля «content_short» — это сейчас не принципиально.
Если сейчас зайти на главную страницу и посмотреть на ссылки в «Подробнее», то они будут иметь вид http://kohana/articles/1-about_framework, что и выглядит красиво, а также корректно с точки зрения SEO. Ссылки в принципе вполне рабочие и совпадают с роутом, но во-первых, роут пропускает и ссылки вида http://kohana-new/articles/about_framework, а во-вторых, в переменную $id у нас попадет не число, а вся часть 1-about_framework. Конечно число можно отсечь с помощью регулярных выражений в контроллере, но делать так — глупо. Проще переписать роут. Замените в файле bootstrap.php роут:
Route::set('articles', '<articles>(/<id>)', array('id' => '.+')) ->defaults(array( 'controller' => 'articles', 'action' => 'index', ));
на
Route::set('articles', '<articles>/<id>-<artname>', array('id' => '[0-9]+'), array('artname' => '.+')) ->defaults(array( 'controller' => 'articles', 'action' => 'article', ));
Теперь роут будет искать в адресе совпадение «число-любые символы», т.е. как раз то, что нам нужно. Обратите внимание, что в новом роуте изменился action. Это сделано для того, чтобы за вывод всех статей отвечал один action-метод, а за вывод одной статьи — другой. Если вы плохо помните, о чем речь, перечитайте этот урок. Следовательно теперь нам нужно видоизменить наш Контроллер Controller_Articles. Он станет таким:
<?php defined('SYSPATH') or die('No direct script access.'); class Controller_Articles extends Controller_Common { public function action_index() { $content = View::factory('/pages/articles'); $this->template->content = $content; } public function action_article() { $id = $this->request->param('id'); $content = View::factory('/pages/article') ->bind('article', $article) ->bind('comments', $comments); $article = Model::factory('Article')->get_article($id); $comments_url = 'comments/' . $id; $comments = Request::factory($comments_url)->execute(); $this->template->content = $content; } } // Articles
Теперь пришла очередь Модели. Добавим в класс Model_Article еще один метод, который как раз и будет извлекать статью по ее идентификатору:
<?php defined('SYSPATH') or die('No direct script access.'); class Model_Article extends Model { protected $_tableArticles = 'articles'; ... /** * Get article * @return array */ public function get_article($id = '') { $sql = "SELECT * FROM ". $this->_tableArticles ." WHERE `id` = :id"; $query = DB::query(Database::SELECT, $sql, FALSE) ->param(':id', (int)$id) ->execute(); $result = $query->as_array(); if($result) return $result[0]; else return FALSE; } }
И наконец финальный штрих — реализация страницы со статьей, которая лежит в Видах в файле article.php:
<?php if($article): ?> <div style="padding:10px; margin-bottom:10px; border-bottom:#333 2px solid;"> <strong><?php echo $article['title']; ?></strong><br /> <i>Автор: <?php echo $article['author']; ?></i> / <i>Дата публикации: <?php echo $article['date']; ?></i><br /><br /> <p><?php echo $article['content_full']; ?></p> </div> <?php echo $comments; ?> <?php else: ?> <div style="padding:10px; margin-bottom:10px;"> Статья не найдена или не существует </div> <?php endif; ?>
Вот теперь все готово. Загружаем сайт, жмем на «Подробнее» у любой статьи, смотрим. Должна получиться вот такая красота:
Если внимательно посмотреть, можно заметить, что комментарии к статьям перестали выводиться. Чтобы это исправить, все, что нужно сделать — это поменять article1 и article2 на 1 и 2 в проверке switch-case файла comments.php. Теперь все работает:
Сами комментарии правда пока добавлять нельзя, но это мы исправим, когда будем изучать Query Builder. Успехов!
<< Назад | Вперед >> |
Пожалуйста, зарегистрируйтесь для комментирования.
Доброго времени суток!
Не могу понять в чем дело, застрял на этом уроке…
Когда нажимаю на «Подробнее» вываливается ошибка Kohana_HTTP_Exception [ 404 ]: The requested URL articles/1- was not found on this server.
Подскажите в чем может быть дело.
если что вот роут (он собственно такой же как в уроке)
Route::set(‘articles’, ‘/-’,
array(‘id’ => ‘[0-9]+’), array(‘artname’ => ‘.+’))
->defaults(array(
‘controller’ => ‘articles’,
‘action’ =>
‘article’,
));
хм…код как то криво вставился…не обращайте на него внимания. он один в один с уроком
Все разобрался)))
здравствуйте, скажите, почему не получается сделать вот так class Controller_Articles extends Controller_Common {
public function action_index()
{
if ($id=$this->request->param(‘id’)){
$id=$this->request->param(‘id’);
$content=View::factory(‘pages/one_article’)
->set(‘id’, $id);
$this->template->content=$content;
} else {
$article=ORM::factory(‘article’)->find_all();//создаем объект модели, получаем все записи
$res=array();//здесь будут названия статей списком
foreach ($article as $row){
$res[]=$row->articlename;//заполняем массив названиями
}//получаем только названия статей в массив $res
$content=View::factory(‘pages/articles’)->set(‘res’, $res);//передаем в вид список статей
$this->template->content=$content;
}
},
но если вывод по id вынести в отдельный action то все работает
«SELECT * FROM «. $this->_tableArticles .» WHERE `id` = :id»;
Так аккуратнее:
$sql = «SELECT * FROM {$this->_tableArticles} WHERE `id` = :id»;
Тогда название таблицы не подсветит. По крайней мере не во всех редакторах.
Спасибо, без этого почему-то на Kohana 3.3 не работало.
для чего многоточия в классе Model_Article после строчки protected $_tableArticles = ‘articles’; или это часть комментария , но у меня подсвечивается красным
Это чтобы не писать повторно код метода, про который я рассказал в
http://kohanaframework.su/database/model_create
вместо многоточия вставьте метод get_all()
а почему выходит ошибка после нажатия Подробнее? Kohana_HTTP_Exception [ 404 ]: The requested URL articles/1- was not found on this server.
Видимо роут не настроен.
Доброго времени суток. Подскажите пожалуйста.
Выдает ошибку:
HTTP_Exception_404 [ 404 ]: The requested URL article/article was not found on this server.
В чем может быть причина?))
Хмм… теперь это ErrorException [ Fatal Error ]: Call to undefined method Model_Article::get_all()
Усё, разобрался. Надо было вставить
public function get_all()
{
$sql = «SELECT * FROM «. $this->_tableArticles;
return DB::query(Database::SELECT, $sql)
->execute();
}