Вывод статей по ид

Комментарии: 44  Просмотры: 20 815

В прошлом уроке у нас была теория, а в этом немного попрактикуемся. Будем дорабатывать наш блог.
Мы уже сделали выборку всех статей из базы данных и вывели их на главной странице. Теперь нам нужно вывести не все статьи, а только одну. Для этого нужно знать ее идентификатор. Добавим ссылку «Подробнее» в файл Вида 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; ?>

Вот теперь все готово. Загружаем сайт, жмем на «Подробнее» у любой статьи, смотрим. Должна получиться вот такая красота:
Вывод одной статьи в Kohana v3.2
Если внимательно посмотреть, можно заметить, что комментарии к статьям перестали выводиться. Чтобы это исправить, все, что нужно сделать — это поменять article1 и article2 на 1 и 2 в проверке switch-case файла comments.php. Теперь все работает:
Вывод одной статьи в Kohana v3.2

Сами комментарии правда пока добавлять нельзя, но это мы исправим, когда будем изучать Query Builder. Успехов!

<< Назад | Вперед >> | Обсудить на форуме


К записи оставлено 44 коммент.

Доброго времени суток!
Не могу понять в чем дело, застрял на этом уроке…
Когда нажимаю на «Подробнее» вываливается ошибка 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();
}



Оставить комментарий или два

Пожалуйста, зарегистрируйтесь для комментирования.