yii-treemp

Yii1 active record behavior based on materialized path strucute

  • 所有者: wartur/yii-treemp
  • 平台:
  • 许可证: BSD 2-Clause "Simplified" License
  • 分类:
  • 主题:
  • 喜欢:
    0
      比较:

Github星跟踪图

YII-TREEMP (Русская версия)

Extension for Yii for working with tree structure using an algorithm materialized path.
When using this extension do not forget to use table locks or transactions.

DEMO: http://yii-treemp.wartur.ru

Release 2.0.1 for Yii second and last. Further development to be carried out on Yii2

From the author

This extension was created for fun and to meet their vile,
vulgar and useless in practice, perfectionism.

(Sorry for my english. I'm using google translate)

Abstract

Extension for working with tree structure in a relational database.
Algorithm materialized path.
The algorithm speeds up the tree in such operations as sampling branches, tree building or part of the tree.
Due to the algorithm materialized path accelerated insertion rate in an arbitrary position in the table.
For additional sorting branches at each level of the need to use an additional algorithm.
As an example, take https://github.com/wartur/yii-sorter

IMPORTANT: all operations using this extension shall be made through
the transaction (ISOLATION LEVEL SERIALIZABLE) / lock.
Otherwise, there is a possibility of destruction of the database.
All actions of this expansion include transactions in cases when
the table does not support transactions in the component
you want to specify that you want to use a table lock.

Connecting to the expansion project

  1. Download the latest release

  2. Unpack yii-treemp in the directory ext.wartur.yii-treemp

  3. Add a new alias path to the top of the configuration file (default: config / main.php)

Yii::setPathOfAlias('treemp', 'protected/extensions/wartur/yii-treemp');
  1. Add behavior to a model in which support is required to work with tree structure.
    Minimum configuration:
public function behaviors() {
	return array_merge(parent::behaviors(), array(
		'TreempActiveRecordBehavior' => array(
			'class' => 'treemp.behaviors.TreempActiveRecordBehavior',
		)
	));
}
  1. Check that your model satisfies the schema given in the
    treemp.tests.env.schema.
    Remember to work the behavior required field VARCHAR (255) path with a unique key. More you can read in
    API reference поведения.
    MySQL does not support indexing the text field more then 255 characters.

  2. If you already have a tree structure based on the parent_id.
    Make restructuring materialized path by calling the API treempRebuildAllPath

$treeModel = Treetest::model();
$treeModel->treempRebuildAllPath();

Software API

// attach some node to the current node
$currentNode = Treetest::model()->findByPk(1);
$newNode = new Treetest();
$newNode->name = 'newName1';
$currentNode->treempAppendChild($newNode);

// attach current node to other node (the result will be equal)
$currentNode = Treetest::model()->findByPk(1);
$newNode = new Treetest();
$newNode->name = 'newName1';
$newNode->treempAppendTo($currentNode);

// materialized path reconstructed automatically if you change the parent_id (the result will be equal)
$currentNode = Treetest::model()->findByPk(1);
$newNode = new Treetest();
$newNode->name = 'newName1';
$newNode->parent_id = $currentNode->id;
$newNode->save();

// obtain an arbitrary node on the identifier.
$node = Treetest::model()
$rootLine = $node->treempGetNodeByPk(100500);	// This node will be cached
$rootLine2 = $node->treempGetNodeByPk(100500);
// $rootLine == $rootLine2

// get a list of the root node
$node = Treetest::model()
$rootLine = $node->treempGetRootline();

// get the children of the current node
$currentNode = Treetest::model()->findByPk(666);
$childrenNodes = $currentNode->treempGetChildren();

// get the parent of the current node
$currentNode = Treetest::model()->findByPk(666);
$parentNode = $currentNode->treempGetParent();

// load all tree in an operational cache
$currentNode = Treetest::model();
$currentNode->treempLoadAllTreeCache();
$node100500 = $currentNode->treempGetNodeByPk(100500);	// cache hit
$node100501 = $currentNode->treempGetNodeByPk(100501);	// cache hit
$node666 = $currentNode->treempGetNodeByPk(666);	// cache hit

// load a tree branch in an operational cache
// In the database there are threads 1:10:100:100500, 1:10:100:100501, 666
$currentNode = Treetest::model()->findByPk(1);
$currentNode->treempLoadBranchCache();
$node100500 = $currentNode->treempGetNodeByPk(100500);	// cache hit
$node100501 = $currentNode->treempGetNodeByPk(100501);	// cache hit
$node666 = $currentNode->treempGetNodeByPk(666);	// cache miss

// clear the cache-line
$currentNode->treempCleanoutCache();

// to get the path from the root to the current node. This functionality can be used in the breadcrumb
$someNode = Treetest::model()->findByPk(100500);
$pathModels = $someNode->treempGetPathModels();		// path => 1:10:100:100500
$resultArray = array();
foreach ($pathModels as $entry) {
	$resultArray[] = $entry->name;
}
echo implode(' :: ', $resultArray);
// name1 :: name10 :: name100 :: name100500

// You can make it in a loop, all access to the database are cached.
// TargetModel - this model is bound to several branches of the tree across the table many-to-many
$targetModel = TargetModel::model()->findByPk(666);
$result = array();
foreach ($targetModel->treetests as $entry) {
	$pathModels = $entry->treempGetPathModels();
	$resultArray = array();
	
	// because caching provides a sufficiently high speed such design
	foreach ($pathModels as $pathEntry) {
		$resultArray[] = $pathEntry->name;
	}
	
	$result[] = implode(' :: ', $resultArray);
}
return implode("\n ", $result);
// name1 :: name10 :: name100 :: name100500
// name1 :: name10 :: name100 :: name100501
// In the second row name1, name10, name100 was take from cache

// get the root of the current branch
$currentNode = Treetest::model()->findByPk(100500);
$rootNode = $currentNode->treempGetRootParent();

Working with Widget Ready

To expand the available basic set of widgets.
Using the current API, you can write your widget will do the rest for you behavior.

  1. Widget for drawing up a tree

To bind together the vertices can use the drop-down list widget generation with stylized tree.
To do this, add the following code mapping

<? $this->widget('treemp.widgets.TreempDropdownWidget', array(
	'model' => $model,
	'attribute' => 'parent_id',
)) ?>

In the widget, there are additional settings.
You can remove the branch from the selection list is bound to the current vertex.
This would eliminate the opportunity to loop or cycle.
Default branch is bound to editable tree top hidden if for some reason you want to show it,
use setting $deleteHimself = false.
Note in this case, may occur during the preservation cycle error location in the tree.
To adjust the spacing of the variable $spaceMultiplier.

<? $this->widget('treemp.widgets.TreempDropdownWidget', array(
	'model' => $model,
	'attribute' => 'parent_id',
	'deleteHimself' => false, // Show all branches, even those that can potentially cause an error
	'spaceMultiplier' => 1,   // decrease Indent
	'emptyText' => '(My custom empty text)' // change the default text
)) ?>
  1. Widget to bind the tree node with a specific model
<? $this->widget('treemp.widgets.TreempAttachWidget', array(
	'model' => $model,
	'attribute' => 'treetest_id',
	'treempModel' => 'Treetest',
)) ?>

This widget is equal TreempDropdownWidget except that you must specify
the name of the tree model in the variable $treempModel.
This widget is missing $deleteHimself, since the addition is carried out to the external model,
and not between the tree branches.

  1. Widget and behavior for the attach of several branches of the tree to a specific model via an intermediate table

In the model to which you want to make attachment you want to add

// add public variable
public $newAttachIds = array();

// add behavior indicating a variable that has been added above
public function behaviors() {
	return array_merge(parent::behaviors(), array(
		'TreempMultiattachActiveRecordBehavior' => array(
			'class' => 'treemp.behaviors.TreempMultiattachActiveRecordBehavior',
			'multiAttachModelName' => 'Attachtest',
			'multiAttachModelTargetIdField' => 'many_attach_model_id',
			'multiAttachModelTreempIdField' => 'treetest_id',
			'attachField' => 'newAttachIds'
		)
	));
}

// add to validators
public function rules() {
	return array(
		// ...
		array('newAttachIds', 'type', 'type' => 'array'),
		// ...
	);
}
  • multiAttachModelName - indicates the model class that stores a many-to-many
  • multiAttachModelTargetIdField - variable in the model {multiAttachModelName}, pointing to the target model, which will be attached a list of other models
  • multiAttachModelTreempIdField - variable in the model {multiAttachModelName}, indicating the model that you want to attach to the target model. In our case, the tree

In the model, the variable $newAttachIds behavior will be loaded with the current list of linked models,
after saving the model behavior will remain binding that have been changed

In the view must be added the following widget that creates a list of checkboxes with more stylized tree.

<? $this->widget('treemp.widgets.TreempMultiattachWidget', array(
	'model' => $model,
	'attribute' => 'newAttachIds',
	'treempModel' => 'Treetest',
)) ?>

Widget TreempMultiattachWidget has additional customization capabilities. Read the API reference.

Good work!

主要指标

概览
名称与所有者wartur/yii-treemp
主编程语言PHP
编程语言PHP (语言数: 1)
平台
许可证BSD 2-Clause "Simplified" License
所有者活动
创建于2014-09-03 12:36:54
推送于2015-01-08 13:47:27
最后一次提交2015-01-08 16:46:00
发布数3
最新版本名称v2.0.1 (发布于 )
第一版名称v1.0.0 (发布于 )
用户参与
星数9
关注者数2
派生数0
提交数40
已启用问题?
问题数0
打开的问题数0
拉请求数0
打开的拉请求数0
关闭的拉请求数0
项目设置
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?