Yii (дерево страниц с добавлением и удалением элементов)
Забегу вперед, покажу что мы хотим получить
Пойдем по шагам. Подразумевается, что yii у вас установлен и настроен. Если нет, то смотрите как это делается в предыдущих уроках.
1. Создаем таблицу.
Я решил работать с PostgreSQL поэтому DDL такой
DDL for MySQL
2. Создаем model и crud
3.Дальше пошла магия.
Вот качаем расширение
Кидаем как обычно в ..\protected\extensions
добавляем в main
4. Систему мы настроили
5.А сейчас пойдет самое интересное
Изменим page/index.php
6. В модели добавляем функцию dataTree
.
иконки здесь
кидаем в \images всю папку
7.В контроллере переопределяем функцию индекс
8.Поменяем _form
на данном этапе нужно создать корневой элемент
9.Для добавления новых элементов перекроим _form
здесь внимательно.
но это не заработает если не изменить метод в контроллере
..
надеюсь при нажатии на плюсик вы видите примерно следующее
..
..
10. переходим к удалению
в модели пишем
в контроллере
11.апдейт. практически ничего не меняем
12.как вижу вроде все сделано.
13.можно вывести дерево страниц
в column2 пропишем следующее
..
..
14. хорошим тоном считается выкладывать исходники
вот они
1. Создаем таблицу.
Я решил работать с PostgreSQL поэтому DDL такой
CREATE TABLE "SC_Wonder".t_page ( p_id SERIAL, p_title TEXT NOT NULL, p_link TEXT, p_parent INTEGER, p_order INTEGER, p_type INTEGER, p_comment TEXT ) WITH (oids = false); COMMENT ON TABLE "SC_Wonder".t_page IS 'таблица страниц'; COMMENT ON COLUMN "SC_Wonder".t_page.p_id IS 'ид'; COMMENT ON COLUMN "SC_Wonder".t_page.p_title IS 'название'; COMMENT ON COLUMN "SC_Wonder".t_page.p_link IS 'ссылка'; COMMENT ON COLUMN "SC_Wonder".t_page.p_parent IS 'предок'; COMMENT ON COLUMN "SC_Wonder".t_page.p_order IS 'позиция'; COMMENT ON COLUMN "SC_Wonder".t_page.p_type IS 'тип'; COMMENT ON COLUMN "SC_Wonder".t_page.p_comment IS 'комментарий';
DDL for MySQL
CREATE TABLE `t_page` ( `p_id` INTEGER(11) NOT NULL AUTO_INCREMENT COMMENT 'ид', `p_title` TEXT COLLATE utf8_general_ci NOT NULL COMMENT 'название', `p_link` TEXT COLLATE utf8_general_ci COMMENT 'ссылка', `p_parent` INTEGER(11) DEFAULT NULL COMMENT 'предок', `p_order` INTEGER(11) DEFAULT NULL COMMENT 'позиция', `p_type` INTEGER(11) DEFAULT NULL COMMENT 'тип', `p_comment` INTEGER(11) DEFAULT NULL COMMENT 'комментарий', PRIMARY KEY (`p_id`) USING BTREE, UNIQUE KEY `p_id` (`p_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' COMMENT='таблица страниц' ;..
2. Создаем model и crud
3.Дальше пошла магия.
Вот качаем расширение
Кидаем как обычно в ..\protected\extensions
добавляем в main
//config/main.php 'components' => array( 'import' => 'simpletree_widget',..
4. Систему мы настроили
5.А сейчас пойдет самое интересное
Изменим page/index.php
<?php /* @var $this PageController */ /* @var $dataProvider CActiveDataProvider */ $this->breadcrumbs = array( 'Страницы', ); ?> <?php if (Yii::app()->user->hasFlash('flash')): ?> <div class="info"> <?php echo Yii::app()->user->getFlash('flash'); ?> </div> <?php endif; ?> <?php $this->menu = array( array('label' => 'Поиск', 'url' => array('admin')), ); ?> <h1>Страницы</h1> <?php $this->widget('CTreeView', array( 'data' => $dataTree, 'htmlOptions' => array( 'id' => 'treeview-categ', 'class' => 'treeview-red', //there are some classes that ready to use ), )); if (!$dataTree) echo CHtml::link('Создать корневой элемент?', array('page/create?new=true')); ?>..
6. В модели добавляем функцию dataTree
.
.
public function getModelName()
{
return __CLASS__;
}
public static function dataTree($buttons = false)
{
$refs = array();
$list = array();
$result = self::model()->findAll(array('order'=>'id_parent ASC, p_order ASC'));
foreach ($result as $data)
{
$thisref = &$refs[$data['id']];
$thisref['id_parent'] = $data['id_parent'];
$self = strtolower(self::model()->modelName);
$button = array(
'addChild' => CHtml::link(CHtml::image(Yii::app()->baseUrl . '/images/icons/sm2_addChild.png', 'Добавить'),
array( $self.'/create', 'id_parent' => $data['id']), array('title' => 'Добавить')),
'update' => CHtml::link(CHtml::image(Yii::app()->baseUrl . '/images/icons/update.png',
'Изменить'), array($self.'/update', 'id' => $data['id']), array('title' => 'Изменить')),
'order' => CHtml::link(CHtml::image(Yii::app()->baseUrl . '/images/icons/order.png',
'Сортировать'), array($self.'/order', 'id' => $data['id']), array('title' => 'Сортировать')),
'delete' => CHtml::ajaxLink(
CHtml::image(Yii::app()->baseUrl . '/images/icons/sm2_delete.png', 'delete'),
Yii::app()->createUrl('admin/'.$self.'/delete', array('id' => $data['id'])), array(
'type' => 'POST',
'success' => 'function(data) {
top.location.href="' . Yii::app()->createUrl('admin/'.$self.'/index') . '";
}',
), array(
'href' => Yii::app()->createUrl('admin/'.$self.'/delete', array('id' => $data['id'])),
'confirm' => 'Уверены?',
'title' => 'Удалить',
)
),
);
if ($buttons)
{
$thisref['text'] = "<span title='{$data['id']}'>" . $data['title'] . "</span>";
if ($data['id_parent'] == 0)
{
$thisref['text'] .= ' ' . $button['addChild'];
// $thisref['text'] .= ' ' . $button['order'];
}
// if ($data['id'] > 1)
if ($data['id_parent'] > 0)
{
$thisref['text'] .= ' ' . $button['addChild'];
$thisref['text'] .= ' ' . $button['update'];
$thisref['text'] .= ' ' . $button['delete'];
}
}
else
{
$thisref['text'] = $data['title'];
}
$thisref['id'] = $data['id'];
if ($data['id_parent'] == 0)
{
$list[$data['id']] = &$thisref;
}
else
{
$refs[$data['id_parent']]['children'][$data['id']] = &$thisref;
}
}
return $list;
}
.
.иконки здесь
кидаем в \images всю папку
7.В контроллере переопределяем функцию индекс
public function actionIndex() { $dataProvider=new CActiveDataProvider('Page'); $this->render('index',array( //'dataProvider'=>$dataProvider, 'dataTree' => Page::dataTree(true), )); }..
8.Поменяем _form
<?php /* @var $this PageController */ /* @var $model Page */ /* @var $form CActiveForm */ ?> <div class="form"> <?php $form = $this->beginWidget('CActiveForm', array( 'id' => 'page-form', // Please note: When you enable ajax validation, make sure the corresponding // controller action is handling ajax validation correctly. // There is a call to performAjaxValidation() commented in generated controller code. // See class documentation of CActiveForm for details on this. 'enableAjaxValidation' => false, )); ?> <p class="note">Fields with <span class="required">*</span> are required.</p> <?php echo $form->errorSummary($model); ?> <div class="row"> <?php echo $form->labelEx($model, 'title'); ?> <?php echo $form->textArea($model, 'title', array('rows' => 6, 'cols' => 50)); ?> <?php echo $form->error($model, 'title'); ?> </div> <div class="row"> <?php echo $form->labelEx($model, 'link'); ?> <?php echo $form->textArea($model, 'link', array('rows' => 6, 'cols' => 50)); ?> <?php echo $form->error($model, 'link'); ?> </div> <div class="row"> <?php echo $form->labelEx($model, 'id_parent'); ?> <?php if ($_GET['new'] == 'true') $model->id_parent = 0; else $model->id_parent = $model->idParent->title; echo $form->textField($model, 'id_parent', array('disabled' => true)); ?> <?php echo $form->error($model, 'id_parent'); ?> </div> <div class="row"> <?php echo $form->labelEx($model, 'p_order'); ?> <?php echo $form->textField($model, 'p_order'); ?> <?php echo $form->error($model, 'p_order'); ?> </div> <div class="row"> <?php echo $form->labelEx($model, 'type'); ?> <?php $type = array('1' => 'внешняя ссылка', '2' => 'внутренння ссылка'); echo $form->radioButtonList($model, 'type', $type, array('separator' => ' ', 'labelOptions' => array('style' => 'display:inline'), // add this code )); ?> <?php echo $form->error($model, 'type'); ?> </div> <div class="row"> <?php echo $form->labelEx($model, 'hidden'); ?> <?php echo $form->checkBox($model, 'hidden'); ?> <?php echo $form->error($model, 'hidden'); ?> </div> <div class="row"> <?php echo $form->labelEx($model, 'comment'); ?> <?php echo $form->textArea($model, 'comment', array('rows' => 6, 'cols' => 50)); ?> <?php echo $form->error($model, 'comment'); ?> </div> <div class="row buttons"> <?php echo CHtml::submitButton($model->isNewRecord ? 'Создать' : 'Сохранить'); ?> </div> <?php $this->endWidget(); ?> </div><!-- form -->..
на данном этапе нужно создать корневой элемент
9.Для добавления новых элементов перекроим _form
здесь внимательно.
idParentэто название отношения
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( 'idParent' => array(self::BELONGS_TO, 'Page', 'p_parent'), 'tPages' => array(self::HAS_MANY, 'Page', 'p_parent'), ); }..
но это не заработает если не изменить метод в контроллере
public function actionCreate() { $model = new Page; // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if (isset($_GET['p_parent'])) $model->p_parent = $_GET['p_parent']; if (isset($_POST['Page'])) { $model->attributes = $_POST['Page']; if ($model->save()) //$this->redirect(array('view','id'=>$model->p_id)); { Yii::app()->user->setFlash('flash', "Успешное создание."); $this->redirect(array('index')); } } $this->render('create', array( 'model' => $model, )); // }
..
надеюсь при нажатии на плюсик вы видите примерно следующее
..
..
10. переходим к удалению
в модели пишем
public function beforeDelete() { if ($this->id_parent == NULL) throw new CHttpException(400, 'Главную категорию нельзя удалить'); /* $res = Yii::app()->db2->createCommand() ->select('COUNT(*) as cnt') ->from('t_page') ->where('p_parent=:id', array('id' => $this->p_id)) ->queryRow();*/ $count = Page::Model()->count("p_parent=:id", array("id" => $this->id)); //if ($res['cnt'] > 0) if ($count > 0) throw new CHttpException(400, 'Можно удалить только пустую категорию.'); return parent::beforeDelete(); }..
в контроллере
public function actionDelete($id) { if (Yii::app()->request->isPostRequest) { // we only allow deletion via POST request try { $this->loadModel($id)->delete(); Yii::app()->user->setFlash('flash', "Успешное удаление."); } catch (Exception $e) { Yii::app()->user->setFlash('flash', $e->getMessage()); } } else throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.'); }..
11.апдейт. практически ничего не меняем
public function actionUpdate($id) { $model = $this->loadModel($id); // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if (isset($_POST['Page'])) { $model->attributes = $_POST['Page']; if ($model->save()) { Yii::app()->user->setFlash('flash', "Успешное создание."); $this->redirect(array('index', 'id' => $model->p_id)); } } $this->render('update', array( 'model' => $model, )); }..
12.как вижу вроде все сделано.
13.можно вывести дерево страниц
в column2 пропишем следующее
<?php $a = Page::model()->findAll(); foreach ($a as $user) { $all[$user->p_parent][] = array(id => $user->p_id, text => CHtml::link($user->p_title, Yii::app()->createUrl('site/page', array('view' => 'frameset', 'frame' => $user->p_id))), //text=> $user->p_title, parent_id => $user->p_parent); } function RecursiveTree2(&$rs, $parent) { $out = array(); if (!isset($rs[$parent])) { return $out; } foreach ($rs[$parent] as $row) { $chidls = RecursiveTree2($rs, $row['id']); if ($chidls) { if ($row['parent_id'] == 0) { $row['toggle'] = false; $row['expanded'] = true; $row['children'] = $chidls; $row['text'] = ''; } else { $row['expanded'] = false; $row['children'] = $chidls; } } $out[] = $row; } return $out; } $this->widget('CTreeView', array('data' => RecursiveTree2($all, 0), 'htmlOptions' => array('class' => 'treeview-red')));получили примерно следующее
..
..
14. хорошим тоном считается выкладывать исходники
вот они
Комментарии
Отправить комментарий