/** * Tanphp framework * * * @ Category Tanphp * @ Package Data_structure * @ Copyright Copyright (c) 2012 Tan Bo tanbo. name * @ Version $ Id: Tree. php 25024 22:22:22 tanbo $ */
/** * Tree structure data access class * * Quick access to tree data * * @ Param array $ arr the parameter must be a standard two-dimensional array that contains the index Field (id) and the field (path) representing the tree structure, as shown in example * * @ Example * $arr = array( * array( 'id' => 1, 'name' => 'php', 'path' => '1' ), * array( 'id' => 3, 'name' => 'php1', 'path' => '1-3' ), * array( 'id' => 2, 'name' => 'mysql', 'path' => '2' ), * array( 'id' => 6, 'name' => 'mysql1', 'path' => '2-6' ), * array( 'id' => 7, 'name' => 'mysql2', 'path' => '2-7' ), * array( 'id' => 5, 'name' => 'php11', 'path' => '1-3-5' ), * array( 'id' => 4, 'name' => 'php2', 'path' => '1-4' ), * ); * $cate = new Tree($arr); * * $data = $cate->getChild(2); * * print_r($data->toArray()); *
* */
Class Tree { Public $ _ info; // Node Information Public $ _ child = array (); // subnode Private $ _ parent; // parent node Private $ _ data; // temporary data of the current operation Private static $ _ indexs = array (); // index of all nodes Private static $ _ index_key = 'id'; // Index Key Private static $ _ tree_key = 'path'; // tree expression key Private static $ _ tree_delimiter = '-'; // attribute structure expression delimiter /** * Constructor * * @ Param array $ arr * @ Param boole $ force_sort if true, $ arr is forcibly ordered. * @ Return void */ Public function _ construct (array $ arr = array (), $ force_sort = true) { If ($ force_sort === true ){ $ Arr = $ this-> _ array_sort ($ arr, self: $ _ tree_key ); } If (! Empty ($ arr )){ $ This-> _ init ($ arr ); } } /** * Initial storage of tree data * * @ Param array $ arr * @ Return void */ Private function _ init (array $ arr) { Foreach ($ arr as $ item ){ $ Path = $ item [self: $ _ tree_key]; $ Paths = explode (self: $ _ tree_delimiter, $ path ); $ Count_paths = count ($ paths ); $ Parent_id = isset ($ paths [$ count_paths-2])? $ Paths [$ count_paths-2]: NULL; If ($ count_paths> 1 // if there is a parent & Array_key_exists ($ parent_id, self: $ _ indexs) // The parent database has been stored in the index. & Self: $ _ indexs [$ parent_id] instanceof Tree // the parent class is a Tree object. ){ Self: $ _ indexs [$ parent_id]-> addChild ($ item ); } Elseif ($ count_paths = 1 ){ $ This-> addChild ($ item ); } Else { Throw new Exception ("path data error". var_export ($ item, true )); } } // Print_r (self: $ _ indexs ); } /** * Add a subnode * * @ Param array $ item * @ Return void */ Public function addChild (array $ item, $ parent = NULL) { $ Child = new Tree (); $ Child-> _ info = $ item; $ Child-> _ parent = $ parent = NULL? $ This: $ parent; $ Child-> _ parent-> _ child [] = $ child; $ This-> _ addIndex ($ item, $ child-> _ getSelf ()); } /** * Add a node to the index * * @ Param array $ item * @ Param mix $ value * @ Return void */ Private function _ addIndex (array $ item, $ value) { If (array_key_exists (self: $ _ index_key, $ item) & is_int ($ item [self: $ _ index_key]) { Self: $ _ indexs [$ item [self: $ _ index_key] = $ value; } Else { Throw new Exception ("The id field does not exist or is not a string "); } } /** * Obtain your own references. * * @ Return Tree object quote */ Private function _ getSelf () { Return $ this; } /** * Obtain the subnode of the node with the specified id * * @ Param int $ id * @ Return Tree object */ Public function getChild ($ id) { $ Data = self: $ _ indexs [$ id]-> _ child; $ This-> _ data = $ data; Return $ this; } /** * Obtain the parent node of the node with the specified id * * @ Param int $ id * @ Return Tree object */ Public function getParent ($ id) { $ Data = self ::$ _ indexs [$ id]-> _ parent; $ This-> _ data = $ data; Return $ this; } /** * Get the same-level node of the node with the specified id * * @ Param int $ id * @ Return Tree object */ Public function getBrother ($ id) { $ Data = self ::$ _ indexs [$ id]-> _ parent-> _ child; $ This-> _ data = $ data; Return $ this; } /** * Convert a Tree object to an array * * @ Param object $ object * @ Return array */ Public function toArray ($ obj = NULL) { $ Obj = ($ obj = NULL )? $ This-> _ data: $ obj; $ Arr = array (); $ _ Arr = is_object ($ obj )? $ This-> _ getBaseInfo ($ obj): $ obj; If (is_array ($ _ arr )){ Foreach ($ _ arr as $ key => $ val ){ $ Val = (is_array ($ val) | is_object ($ val ))? $ This-> toArray ($ val): $ val; $ Arr [$ key] = $ val; } } Else { Throw new Exception ("_ arr is not an array "); } Return $ arr; } /** * Filter fields such as _ parent to avoid infinite loops. * * @ Param object $ obj * @ Return void */ Private function _ getBaseInfo ($ obj) { $ Vars = get_object_vars ($ obj ); $ BaseInfo ['_ info'] = $ vars [' _ info']; $ BaseInfo ['_ child'] = $ vars ['_ child']; Return $ baseInfo; } /** * Two-dimensional array sorting * * Sort two-dimensional arrays in ascending or descending order based on the specified key name * * @ Param array $ arr two-dimensional array * @ Param string $ keys * @ Param string $ type must be asc or desc * @ Throws an exception when the parameter is invalid. * @ Return returns the sorted array. */ Private function _ array_sort (array $ arr, $ keys, $ type = 'asc '){ If (! Is_string ($ keys )){ Throw new Exception ("Invalid parameter keys: the type of the parameter keys must be a string "); } $ Keysvalue = $ new_array = array (); Foreach ($ arr as $ k =>$ v ){ If (! Is_array ($ v) |! Isset ($ v [$ keys]) { Throw new Exception ("The arr parameter is not a two-dimensional array or the arr sub-element does not contain the key '{$ keys }'"); } $ Keysvalue [$ k] = $ v [$ keys]; } Switch ($ type ){ Case 'asc ': Asort ($ keysvalue ); Break; Case 'desc ': Arsort ($ keysvalue ); Break; Default: Throw new Exception ("Invalid parameter type: the value of the parameter type must be 'asc 'or 'desc '"); } Reset ($ keysvalue ); Foreach ($ keysvalue as $ k => $ v ){ $ New_array [$ k] = $ arr [$ k]; } Return $ new_array; } } ?> |