понедельник, 11 июля 2011 г.

Модуль статических страниц

Продолжаю работать над своим проектом. Сейчас сделал так, чтобы нужная страница открывалась бы по названию, то есть по значению поля url из таблицы tbl_sppage.
Сначала я добавил еще одну колонку в таблице tbl_sprelation для того, чтобы сообщения на странице можно было бы сортировать
ALTER TABLE `tbl_sprelations` ADD `sort` INT NOT NULL
Также изменил первичный ключ этой таблицы, теперь он составной и включает в себя все три колонки
ALTER TABLE `tbl_sprelations`
  DROP PRIMARY KEY,
   ADD PRIMARY KEY(
     `tbl_sppage_id`,
     `tbl_spmessage_id`,
     `sort`);
Так как страницы будут открываться по полю url, его надо сделать индексным:
ALTER TABLE `tbl_sppage` ADD INDEX ( `url` )
Затем я заполнил таблицы моего модуля данными через phpmyadmin, который встроен в denwer. В нем я делаю и остальные действия с базой данных.
--
-- Dumping data for table `tbl_spmessage`
--

INSERT INTO `tbl_spmessage` (`id`, `title`, `message`) VALUES
(1, 'Адрес', 'Проспект Комсомола 12-45'),
(2, 'Телефон', 'Секретарь: 546546546'),
(3, 'Предложение 1', 'Возьми 2 заплати за 1'),
(4, 'Предложение 2', 'Купи больше плати меньше');

--
-- Dumping data for table `tbl_sppage`
--

INSERT INTO `tbl_sppage` (`id`, `name`, `url`) VALUES
(1, 'About our firm', 'about'),
(2, 'Special offers', 'offers');

--
-- Dumping data for table `tbl_sprelations`
--

INSERT INTO `tbl_sprelations` (`tbl_sppage_id`, `tbl_spmessage_id`, `sort`) 
VALUES
(1, 1, 0),
(1, 2, 0),
(2, 2, 4),
(2, 3, 2),
(2, 4, 3);
Теперь у меня есть две страницы: «О фирме» и «Специальные предложения». И на страницах сообщения: Адрес, Телефон, и два предложения. Какое сообщение где находится, определено в таблице tblsprelations

На данном этапе я понял, что вроде как начал что-то соображать в yii.

Теперь надо прописать отношения этих таблиц.
В файле Z:\home\catalog.loc\www\protected\modules\staticpage\models\sppage.php
Пишу:
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'messages' => array(self::MANY_MANY, 'Spmessage', 
'tbl_sprelations(tbl_sppage_id, tbl_spmessage_id)',
'order'=>'messages_messages.sort ASC'));
   }
В этом описании уже добавлена сортировка по полю order!
В файле Z:\home\catalog.loc\www\protected\modules\staticpage\models\spmessages.php
Пишу:
/**
* —return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'pages' => array(self::MANY_MANY, 'Sppage', 'tbl_sprelations
(tbl_spmessage_id,tbl_sppage_id)'),
);

Отношения многие ко многим определены. И в моделях появились новые атрибуты, приведу их все, а новые выделю жирным:

В модели Sppage:

sppage->id
sppage->name
sppage->url
sppage->messages->id
sppage->messages->title
sppage->messages->message


и в Spmessage:

spmessage->id
spmessage->title
spmessage->message
spmessage->pages->id
spmessage->pages->name
spmessage->pages->url

Теперь надо чтобы на странице http://catalog.loc/page/1 вышли сообщения, принадлежащие этой странице.
Для этого в файле Z:\home\catalog.loc\www\protected\modules\staticpage\views\sppage\view.php (именно он отвечает за показ конкретной страницы) удаляю вывод zii.widgets.CDetailView, а вместо него вывожу сообщения:

foreach($model->messages as $item)
{
  echo '<H2>'.$item->title.'</H2>';
  echo $item->message;
  echo '<br><br>';
}  
Ну и меняю заголовок с
<h1>View Sppage #<?php echo $model->id; ?></h1>
На
<h1><?php echo $model->name; ?></h1>
В результате при выборе конкретной страницы показываются нужные сообщения.
А теперь, то, что обещал вначале: страницы должны открываться по полю url.

Для этого в файле Z:\home\catalog.loc\www\protected\config\main.php изменяю правило для показа конкретной страницы на
'page=<id:\w+>'=>'staticpage/sppage/view',
'page/<action:\w+>/<id:\w+>'=>'staticpage/sppage/<action>',		
'page/<action:\w+>'=>'staticpage/sppage/<action>',
		
'message'=>'staticpage/spmessage',
'message/<id:\d+>'=>'staticpage/spmessage/view',
'message/<action:\w+>/<id:\d+>'=>'staticpage/spmessage/<action>',		
'message/<action:\w+>'=>'staticpage/spmessage/<action>',
То есть адрес вида http://catalog.loc/page=любое слово, выполнит 'staticpage/sppage/view' с GET параметром id равным этому слову.

Действие view описано в контроллере модели Sppage, значит в файле Z:\home\catalog.loc\www\protected\modules\staticpage\controllers\SppageController.php надо изменить метод view
/**
  * Displays a particular model.
  * @param char $url the url of the model to be displayed
  */
 public function actionView($url)
 {
   $this->render('view',array(
   'model'=>$this->loadModel($url),
   
  ));
 }
Вместо id используем url. И в этом же файле надо изменить метод loadModel
/**
  * Returns the data model based on the url field given in the GET variable.
  * If the data model is not found, an HTTP exception will be raised.
  * @param char the url of the model to be loaded
  */
 public function loadModel($url)
 {
  $model=Sppage::model()->findByAttributes(array('url'=>$url));
  if($model===null)
   throw new CHttpException(404,'The requested page does not exist.');
  return $model;
 }
Здесь использовал findByAttributes по полю url модели.
Теперь заходим на сайт http://catalog.loc/page=about и видим результат!
Кажется все просто :)
Продолжение следует.

6 комментариев:

  1. Отлично написано, все понятно.
    Жалко, что нельзя использовать это в admin.
    C другой стороны, можно после вставки картинки результат работы функции положить в текстовое поле и выводить его уже готовым.

    Причем, даже не после вставки, а при любом изменении записи, положим это в свойство модели.

    Так и сделаю.

    ОтветитьУдалить
    Ответы
    1. А что значит использовать в admin?

      Удалить
  2. Хотелось бы уточнить несколько моментов: 1. при замене в actionView и loadModel значений с id на url, y вас в коде здесь:
    'page='=>'staticpage/sppage/view',
    'page//'=>'staticpage/sppage/',
    'page/'=>'staticpage/sppage/'
    указан везде id, то есть по GET передается id, а actionView должен получить значение url?
    2. если все таки все меняем на url то доступ в админ часте к конкретной странице будет по полю url также? не совсем понятно

    ОтветитьУдалить
  3. сам начинаю изучать yii. документация отвратительная. пока тыщу форумов не облазишь не поймешь ничего. пишите пожалуйста очень подробно и желательно для полных нубов. инфы для профи попой жуй, на форумах активность за yii нулевая. так сказать ниша свободна. жду с нетерпением поста о создании вложенного дерева страниц из базы (а может уже есть?) нужно будет посмотреть. в общем респект и продвижение

    ОтветитьУдалить
    Ответы
    1. Этот комментарий был удален автором.

      Удалить
    2. Вы где-то не там ищете. Документация отличная, активность на оф. форуме (как англ. так и русском) огромная.
      Руководство - http://yiiframework.ru/doc/guide/ru/index
      Рецепты - http://yiiframework.ru/doc/cookbook/ru/index
      API (англ.) - http://www.yiiframework.com/doc/api/
      Форум - http://yiiframework.ru/forum/
      Если что-то непонятно и нужно "для полных нубов", может стоит сначала почитать про основы php, sql и ООП?

      Удалить