DbHelp.ru
Маленький Yii блог
Комментарии
Гость: комент
Гость: wahaha
zolter: Друпал на Yii? ))
nastia: http://drupal.org/
JB: Да там просто ад)) мне всего 3 значения нужно чтобы выпадало, все равно спасибо)...



Сервер Ultima Online - Forest Wars (от создателя данного блога)

Урок 4 : Создаем отдельную страницу для постов (тем)

Рубрика: Создаем блог вместе

Оцените эту статью:

Рейтинг: 0.00 (0)
4 Июн. 2009
Опубликовать в Twitter Написать в Facebook Опубликовать в своем блоге livejournal.com

Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут возникнуть ошибки из-за несовместимости. Обычно ответы на все вопросы работы на 1.1.х были описаны в комментариях ниже статьи.

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

---

Я надеюсь вы уже знакомы с уроком "Первый раз, первый контроллер.." и имеете на компьютере (хостинге) рабочую копию нашего проекта.

Начнем

Для создания отдельной страницы для поста я могу выбрать несколько путей:

  1. Расширить actionIndex дописав в нем проверку не висит ли в GET-е где то Id.
  2. Создать отдельный экшинс

Давайте выберем второй путь чтобы не засорять actionIndex.

Откройте файл PostController.php и добавьте в него два новых экшинса:

        public function actionView ()
        {
            $this->pageTitle = "";

            if (!empty($_GET['url'])) {
                // На всякий случай удаляю пробелы и устанавливаю
                // максимальную длину для url в 100 символов.
                $url = substr(trim($_GET['url']), 0, 100);
              
                // Только англ. буквы и цифры в url
                if(preg_match("/^[a-zA-Z0-9\-\_]+$/", $url)) {
                    $post = Posts::model()->find("url = :url", array(
                                ':url' => $url,
                            ));
                    if (!empty($post)) {
                        // Тема есть в базе
                        $this->render('view', array(
                            'post' => $post,
                        ));
                    } else {
                        // Такой темы в базе нет. 404?
                        Yii::app()->runController('post/error404');
                    }
                } else {
                    Yii::app()->runController('post/error403');
                }
            } else {
                // $_GET['url'] пустое. Выводим главную страницу
                Yii::app()->runController('post/index');
            }
        }

        public function actionError404 ()
        {
            $this->render('404');
        }

Разберем что у нас и для чего:

  1. actionView - проверяет есть ли в $_GET['url'] какое то значение. Если есть - шуршым в базе и находим нужную тему. Если поста с таким url нету - выполняем экшинс actionError404.
  2. actionError404 - просто рендерим на экран файл 404.php в котором будет описано мол "Такой страницы у нас нет"

Теперь давайте в views/post и создадим там два файла:

404.php:

<h1>Такой страницы у нас нет</h1>

view.php:

<table border="1" width="100%">

    <?php if (!empty($post)) : ?>
        <tr>
            <td><h1><?=$post->name;?></h1>
        <tr>
            <td><?=$post->created;?>
        <tr>
            <td><?=$post->text;?>
    <?php endif; ?>

</table>

Вот теперь в принципе всё готово.

Так как у вас в базе уже есть пару постов (http://yii.dbhelp.ru/step/?n=6), то мы можем попробовать обратиться к одному из них. Для этого в браузере загружаем localhost/post/view/?url=test и смотрим на результат. Если вы всё делали правильно, у вас должно было получиться что то вроде этого http://yii.dbhelp.ru/post/view/?url=hello-yii

Как мне кажется передавать в URL-е таким образом название поста - не красиво, поэтому надо написать простой маршрут. Подробнее почитать как организовать ЧПУ (человеко понятные урлы) на вашем сайте смотрите вот тут

Заходим в protected/config/main.php и добавляем:

    'components'=>array(
    ...  
        'urlManager'=>array(
            'showScriptName' => false,  // что бы не цеплялся index.php к ссылкам
            'urlFormat'=>'path',
            'rules'=>array(
                '<url>/post/'=>'post/view',
            ),
        ),
     ...

Обратите внимательно куда именно я добавил правила, не надо лепить просто в любое место!
Теперь наше правило позволяет нам вместо localhost/post/view/?url=test писать localhost/test/post/

Можете по тестировать, всё должно работать.

Если вдруг не работает и к адресу добавляется "index.php" тогда,
открываем .htaccess (в корне сайта) и пишем туда:

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php
Еще одна мелочь которую мы с вами не написали - это ссылку с главной страницы на страницу поста. Т.е. на странице localhost/post/index/ надо сделать редирект на страницу поста, при нажатии на название.

Открываем файл views/post/_list.php

<tr><td>
    <table border="1" width="100%">
        <tr><td><h2>Название : <?=$post->name;?></h2>
        <tr><td><?php echo $post->created;?>
        <tr><td><?php echo mb_substr($post->text, 0, 500), "...";?>
    </table>

и немного его меняем:

    <tr><td>
    <table border="1" width="100%">
        <tr>
            <td><h2>
                <?php echo CHtml::link($post->name,array('post/view/', 'url'=>$post->url)); ?>
                </h2>
        <tr><td><?php echo $post->created;?>
        <tr><td><?php echo mb_substr($post->text, 0, 500), "...";?>
    </table>

п.с. такой перенос строчек сделан специально что б они не вылезли за блок code моего блога.

Теперь заходим на главную страницу (localhost/ или localhost/post) и нажимаем на название поста.
Барабанная дробь, тун-турурун-турурурурн, все работает :)

Вот такая вот простенькая статья описала вам процесс создания отдельных страниц для постов.



Если хотите опубликовать этот материал у себя - пожалуйста, разместите ссылку на страницу откуда вы его взяли.
Другие yii статьи:

  1. Сегодня обнаружил что мой бывший сокурсник написал свой некий мод на Yii Blog. Исходные коды я не смотрел, но ... "Yii blog new [update]"

  2. Разговор сегодня пойдет про SwiftMailer. Это удобный инструмент для отправки почты из php скрипта. Вы сможете:   очень легко и ... "Подключаем SwiftMailer к Yii"

  3. Рано или позно каждый программист подходит к моменту написания собственной CMS или системы управления сайтами. Несмотря на обильное кол-во опенсорс ... "Идея проекта [OzYii]"

[guest] Гость

Было сказано: Четверг, 04 Июнь 2009

Спасибо!
Жду продолжения!

[guest] xoma

Было сказано: Четверг, 04 Июнь 2009

А почему вместо Yii::app()->runController('post/error404');
не использовать код типа:
throw new CHttpException('404','message')???

[adm] zolter

Было сказано: Четверг, 04 Июнь 2009

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

[guest] xoma

Было сказано: Четверг, 04 Июнь 2009

Понял! Спасибо!

[guest] Ponf

Было сказано: Среда, 10 Июнь 2009

При клике на заголовок:
CException
Description

Property "Posts.date" is not defined.

n1ck

Было сказано: Четверг, 11 Июнь 2009

если не секрет, по какому принципу урл вида

/post_url/post а не скажем: /posts/post_url
От общего к частному так сказать

[adm] zolter

Было сказано: Четверг, 11 Июнь 2009

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

[adm] zolter

Было сказано: Четверг, 11 Июнь 2009

to Ponf
Скорее всего вы в коде вместо "created" написали date. отсюда и ошибка, мол поля такого не найдено. Проверьте базу и проверьте код, где-то точно в этом ошибка

[guest] Ponf

Было сказано: Пятница, 12 Июнь 2009

Спасибо, заработало =)
Ещё небольшая просьба: комментируйте свой код поподробнее, пожалуйста. В предыдущем уроке некоторые действия больше похожи на колдунство, чем на понятный алгоритм)

[adm] zolter

Было сказано: Пятница, 12 Июнь 2009

Окей) Следующий раз постараюсь по подробнее :)

[guest] Ponf

Было сказано: Пятница, 12 Июнь 2009

И ещё: Вашему блогу катострофически не хватает поиска)

[adm] zolter

Было сказано: Пятница, 12 Июнь 2009

Скоро будет)
Просто когда было мало статей - в нем не было смысла :)

[guest] Ponf

Было сказано: Пятница, 12 Июнь 2009

[guest] Ponf

Было сказано: Пятница, 12 Июнь 2009

пофиксил (перепутал местами post и view)) ), осталась проблема с линкпэйджером
при запросе http://blog.ru/post/index выводится 404.php

[adm] zolter

Было сказано: Пятница, 12 Июнь 2009

Вы всё перемешали :) Если вы хотите что б урл был вида : localhost/post/название_темы(url)/ тогда в main.php:


'post/


т.е. просто местами надо было поменять

сделайте:
'post2/

И сразу все проблемы пропадут. :) Просто из-за одинаковых имен такая фигня.

[guest] Ponf

Было сказано: Пятница, 12 Июнь 2009

это я понял :)
Только с Pager'ом проблема осталась.
линк вида:
localhost/post/index
По идее работает так-контроллер PostController, действие actionIndex. там проверяем наш адресс, и почему-то переходим на 404.php
Не понимаю, в чём косяк(
и то, что title страницы не выводится, это нормально?)

[adm] zolter

Было сказано: Пятница, 12 Июнь 2009

Читай пост выше :)
Объясняю почему 404.
1. мы написали правило что всё что post/текст - это ссылка на тему.
2. следовательно post/index это у нас не ссылка на actionIndex теперь, а ссылка на тему с url = "index" которой в базе у нас нету. отсюда и 404 ошибка.

поэтому я и говорю что префикс в урле (в данном случае post) надо поменять на что то другое, что б не совпадало с названием контроллера.

[guest] Ponf

Было сказано: Пятница, 12 Июнь 2009

Жесть, магия)
Спасибо за помощь, жду новых уроков :)

[adm] zolter

Было сказано: Пятница, 12 Июнь 2009

Пожалуйста :)

[guest] Гость

Было сказано: Суббота, 20 Июнь 2009

А есть ли в Yii каких нить хелперов ? что б не делать вот этого


preg_match("/^[a-zA-Z0-9\-\_]+$/", $url)


Я имею ввиду что б написать к примеу так
$a = getVar('aaa');
и в а мы получили чистую переменную от всяких XSS... etc

[guest] Макс

Было сказано: Суббота, 20 Июнь 2009

Можно проверять через модель. Т.е. в rules написать правило.
Но это кому как удобнее.

[adm] zolter

Было сказано: Суббота, 20 Июнь 2009

Регулярные выражения это вечная фишка поэтому не вижу ничего такого что б их не использовать :) В Yii нет встроенной фишки каких то таких проверок насколько я знаю (ну разве что как встроенные правила в моделе). Вы такое можете подключить хелперы из Kohana и использовать их (как это сделать я уже описывал в статьях)

[guest] Гость

Было сказано: Воскресенье, 28 Июнь 2009

А как заменить localhost/post/index/page/3 на localhost/page/3 ?

[guest] Maxx

Было сказано: Воскресенье, 28 Июнь 2009

Вот почитайте - http://www.dbhelp.ru/how-to-remove-indexphp/page/

[guest] Trainer

Было сказано: Пятница, 07 Август 2009

Не, тут проблемка, 2-я страница блога имеет адрес
http://localhost/post/index/page/2

т.е. post - это модель, а "/index/page/2" добавляет уже модуль разбиения по страницам...
как убрать???

[guest] Maxx

Было сказано: Пятница, 07 Август 2009

А вы как хотите что б было на 2,3,4й странице без page/номер?

[guest] Trainer

Было сказано: Понедельник, 10 Август 2009

если основная страница блока http://localhost/
то хотелось бы чтобы страницы были http://localhost/page/2 и т.п.
а сейчас получается http://localhost/post/index/page/2
т.е. проставляется имя контроллера и экшена. как бы от них избавиться без?

[guest] Гость

Было сказано: Вторник, 11 Август 2009

Маршрут надо по умолчанию прописать post/index

[guest] snn

Было сказано: Понедельник, 31 Август 2009

приписать в rules

'page/<page>' => 'post/index'

[guest] Гость

Было сказано: Пятница, 04 Сентябрь 2009

А как сделать что бы в pageTitle выводилось названия поста??

[guest] Гость

Было сказано: Пятница, 04 Сентябрь 2009

Я разобрался но не уверен что это правильно)) в view.php прописал

<?php $this->pageTitle = $post->name;?>

p.s. Спасибо за уроки))

[adm] zolter

Было сказано: Пятница, 04 Сентябрь 2009

Идея верна :) молодец.

Тока это надо в экшинсе прописать который отвечает за вывод постов, а не в отображении. Ну просто по идеологии, а так будет работать и там и там :)

[guest] Гость

Было сказано: Пятница, 04 Сентябрь 2009

если делать в действие у меня почему-то выводит title
My Web Application - View Post

[adm] zolter

Было сказано: Пятница, 04 Сентябрь 2009

Кинь код всего действия сюда, я посмотрю

[adm] zolter

Было сказано: Пятница, 04 Сентябрь 2009

В том месте где у меня комментарий написан:
"// Тема есть в базе"
вставьте на его место $this->pageTitle = $post->name

и должно будет заработать

mrsmile

Было сказано: Пятница, 04 Сентябрь 2009

что не так))) надо удалить этот коммент

[adm] zolter

Было сказано: Пятница, 04 Сентябрь 2009

Я ссылку получил. Вобщем как я и думал :)
Ты пытаешься использовать $post->name; до того как обьявлена и заполнена переменная $post.

Т.е. в тот момент когда ты делаешь:

$this->pageTitle = "$this->pageTitle = $post->name;";


у тебя в переменной $post - еще ничего нету. Поэтому это дело надо сделать чуть ниже, вот так вот:

public function actionView ()
{


if (!empty($_GET['url'])) {
// На всякий случай удаляю пробелы и устанавливаю
// максимальную длину для url в 100 символов.
$url = substr(trim($_GET['url']), 0, 100);

// Только англ. буквы и цифры в url
if(preg_match("/^[a-zA-Z0-9\-\_]+$/", $url)) {
$post = Posts::model()->find("url = :url", array(
':url' => $url,
));
if (!empty($post)) {


// ВОТ ТУТ!!
$this->pageTitle = $post->name;;


// Тема есть в базе
$this->render('view', array(
'post' => $post,
));
} else {
// Такой темы в базе нет. 404?
Yii::app()->runController('post/error404');
}
} else {
Yii::app()->runController('post/error403');
}
} else {
// $_GET['url'] пустое. Выводим главную страницу
Yii::app()->runController('post/index');
}
}

mrsmile

Было сказано: Понедельник, 07 Сентябрь 2009

Помогло спасибо большое

[guest] Гость

Было сказано: Суббота, 26 Сентябрь 2009

Кто подскажет а какое правило написать, чтобы страница /post/show/id/1.html стала faq.html?

[guest] zolter

Было сказано: Суббота, 26 Сентябрь 2009

ну типа

'rules'=>array(
'/post/show/id/1'=>''faq,
),

плюс еще поле суфикс надо что б .html в конце было

[guest] Гость

Было сказано: Суббота, 26 Сентябрь 2009

наоборот?
...
'faq'=>'post/show/id/1'
...

но так не работает

[guest] Maxx

Было сказано: Суббота, 26 Сентябрь 2009

Да, наоборот. золт ошибся походу.
А что пишет? ты указываешь youdomain.ru/post/show/id/1 и дает что происходит?

[guest] Гость

Было сказано: Суббота, 26 Сентябрь 2009

Да в том и дело что ничего не дает!

сбивает работу всех правил и вообще переходит на index.php?r=post.....

[guest] Maxx

Было сказано: Суббота, 26 Сентябрь 2009

Стоп. а ты что index.php не убрал с урла?
Попробуй тогда написать index.php?r=faq
если переведет - тогда читай следующую статью про то как убрать index.php с урла.

[guest] Гость

Было сказано: Воскресенье, 27 Сентябрь 2009

это у меня работало!

у меня не получается с правой стороны указать id :-)

[guest] Гость

Было сказано: Воскресенье, 27 Сентябрь 2009

т.е. если убрать строку
'faq'=>'post/show/id/1'

то /post/show/id/1.html прекрасно работает, но вот как длбилься чтобы эта же вещь отзывалась на /faq.html вот это у меня не получается

[guest] Maxx

Было сказано: Воскресенье, 27 Сентябрь 2009

Вобще очень странно, должно работать...
Сделай модреврайтом тогда в htaccess-е если срочно надо. Хотя это наверно не вариант..

[guest] дед Захар

Было сказано: Вторник, 27 Октябрь 2009

Всем здравия!
Такое маленькое уточнение
использование Yii::app()->runController('post/error404');
действительно "ложится в тему", но при 404 ошибке нужно еще и заголовок соответствующий послать
использование же throw new CHttpException('404','message'); как в стандартном примере проще в том плане, что заголовок формируется самим Yii.
Это я просто к тому, что не нужно забывать про заголовки, кто будет пользоваться методом зольтера.
Спасибо.

[adm] zolter

Было сказано: Вторник, 27 Октябрь 2009

Спасибо за уточнение :)

[guest] дед Захар

Было сказано: Четверг, 29 Октябрь 2009

Не за что. Огромное спасибо за статьи и переводы.

[guest] Антошка

Было сказано: Пятница, 30 Октябрь 2009

привет! спасибо за хороший цикл статей. вопрос такой: я хочу из CPagination убрать отображение index.php, т.е. сделать так, чтобы в ссылке вместо index.php/bla/bla/1 было просто /bla/bla/1 (в .htaccess все необходимые настройки сделал). как это сделать?

[guest] Гость

Было сказано: Пятница, 30 Октябрь 2009

ой, прошу прощения за невнимательность. вопрос отменяется :)

[adm] zolter

Было сказано: Пятница, 30 Октябрь 2009

пожалуйста :)

[guest] babbik

Было сказано: Четверг, 11 Март 2010

Вопрос про название скрипта в url. zolter, почему на твоем блоге, в некоторым местах в ссылках остался index.php - например в нумерации страниц? там как-то формируются другим способом ссылки, в отличии от остальных?

[guest] zolter

Было сказано: Четверг, 11 Март 2010

Там кажется явно в пагинаторе надо указывать что б index.php не приклеивало. Надо api посмотреть будет.

[guest] like2dev

Было сказано: Суббота, 20 Март 2010

Зачем добавлять проверку в действии , если можно сделать в юрл мэенеджере например так :


/page/test

'/page/<url:\w+>/'=>'post/view',

[guest] like2dev

Было сказано: Суббота, 20 Март 2010

Примечание: Использование правил URL снижает производительность приложения. Это происходит по той причине, что в процессе парсинга запрошенного URL CUrlManager пытается найти соответствие каждому правилу до тех пор, пока какое-нибудь из правил не будет применено. Чем больше правил, тем больший урон производительности. Поэтому в случае высоконагруженных приложений использование правил URL стоит минимизировать.

Понятно, почему =)

[guest] zolter

Было сказано: Суббота, 20 Март 2010

ну и плюс к тому что я писал этот урок когда была версии yii только 1.0.5 кажысь. А там такого еще не было в CUrlManager :)

[guest] like2dev

Было сказано: Суббота, 20 Март 2010

Ну так давайте обновлять уроки =)

[guest] zolter

Было сказано: Суббота, 20 Март 2010

Это не так просто :)

[guest] Гость

Было сказано: Вторник, 18 Май 2010

по поводу .htaccess прописал, и как было index.php/post/index так и осталось, в чем дело? если забить в урл /post/index то чатес работает страница грузиться, значит нужно в меню в представлении править ссылки по которым кликаем, но там итак нету индекса array('label'=>'Contact', 'url'=>array('site/contact')), где че убрать?

[guest] Maxx

Было сказано: Вторник, 18 Май 2010

А в конфиге прописали?

[guest] Гость

Было сказано: Вторник, 18 Май 2010

Спасибо! 'showScriptName' => false, провтыкал сорри

[guest] Maxx

Было сказано: Вторник, 18 Май 2010

Бывает :)

takius

Было сказано: Вторник, 24 Август 2010

Спасибо, хорошая тема

[guest] wlnner

Было сказано: Вторник, 31 Август 2010

При выполнении первой части этого урока возникла ошибка.
Перехожу по ссылке localhost/post/view/?url=test, выдается ошибка CException Description PostController cannot find the requested view "view".
Кодил пошагово, без ошибок.

[guest] zolter

Было сказано: Вторник, 31 Август 2010

Файлик view.php точно создать не забыли в папке view/post ?

[guest] wlnner

Было сказано: Вторник, 31 Август 2010

Не забыл. Есть.

[guest] wlnner

Было сказано: Вторник, 31 Август 2010

Не забыл. Есть.

[guest] Гость

Было сказано: Воскресенье, 13 Февраль 2011

блин после того как исправил url у меня даже перелистывать на 2-ую страницу не хочет... говарит что нет её

[guest] Гость

Было сказано: Воскресенье, 13 Февраль 2011

убираешь когда из main корректор url тогда листает

[guest] Гость

Было сказано: Четверг, 17 Март 2011

после добавления кода в PostController.php сайт полностью перестает работать, не как не разберусь почему(

[guest] Гость

Было сказано: Четверг, 17 Март 2011

мой косяк разобрался

[guest] Паша

Было сказано: Вторник, 10 Январь 2012

Разбираюсь по-маленьку. Спасибо, очень интересно.

[guest] Паша

Было сказано: Четверг, 12 Январь 2012

Подскажите, почему может не отображаться Captcha?
Т.е. Она вроде как выводится, но самой картинки нет.
Перепроверил, всё вроде как надо.

Usercontroller.php


class UserController extends CController
{
public function actions()
{
return array(
// Создаем экшинс captcha.
// Он понадобиться нам для формы регистрации (да и авторизации)
'captcha'=>array(
'class'=>'CCaptchaAction',
'backColor'=> 0x003300,
'maxLength'=> 3,
'minLength'=> 3,
'foreColor'=> 0x66FF66,

),
);
}

User.php
 class User extends CActiveRecord
{
// для капчи
public $verifyCode;

registration.php
	        <td><?php $this->widget('CCaptcha', array('buttonLabel' => '<br>[новый код]')); ?></td>
<td><?=CHtml::activeTextField($form,'verifyCode'); ?></td>


Поставил 1.1.9 Там работает (на этом же сервере). Пробывал прописывать как там, результат тот же...
Из=за чего это может быть? Где искать, что попробывать?

[guest] Паша

Было сказано: Четверг, 12 Январь 2012

Ой, сорри, не в тот урок спросил.

[guest] Гость

Было сказано: Четверг, 12 Январь 2012

Скинь код контроллера и модели где идет разговор про качпу в другой урок какой то. Тут как то глюкнул низ страницы

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


Код:
Имя: