1<?php 2/** 3 * Created by PhpStorm. 4 * User: yf 5 * Date: 2018/5/22 6 * Time: 下午2:52 7 */ 8 9namespace EasySwoole\Spl; 10 11 12class SplArray extends \ArrayObject 13{ 14 function __get($name) 15 { 16 if (isset($this[$name])) { 17 return $this[$name]; 18 } else { 19 return null; 20 } 21 } 22 23 function __set($name, $value): void 24 { 25 $this[$name] = $value; 26 } 27 28 function __toString(): string 29 { 30 return json_encode($this, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); 31 } 32 33 function getArrayCopy(): array 34 { 35 return (array)$this; 36 } 37 38 function set($path, $value): void 39 { 40 $path = explode(".", $path); 41 $temp = $this; 42 while ($key = array_shift($path)) { 43 $temp = &$temp[$key]; 44 } 45 $temp = $value; 46 } 47 48 function unset($path) 49 { 50 $finalKey = null; 51 $path = explode(".", $path); 52 $temp = $this; 53 while (count($path) > 1 && $key = array_shift($path)) { 54 $temp = &$temp[$key]; 55 } 56 $finalKey = array_shift($path); 57 if (isset($temp[$finalKey])) { 58 unset($temp[$finalKey]); 59 } 60 } 61 62 function get($path) 63 { 64 $paths = explode(".", $path); 65 $data = $this->getArrayCopy(); 66 while ($key = array_shift($paths)) { 67 if (isset($data[$key])) { 68 $data = $data[$key]; 69 } else { 70 if ($key == '*') { 71 $temp = []; 72 if (is_array($data)) { 73 if (!empty($paths)) { 74 $path = implode("/", $paths); 75 } else { 76 $path = null; 77 } 78 foreach ($data as $key => $datum) { 79 if (is_array($datum)) { 80 $ctemp = (new SplArray($datum))->get($path); 81 if ($ctemp !== null) { 82 $temp[][$path] = $ctemp; 83 } 84 } else if ($datum !== null) { 85 $temp[$key] = $datum; 86 } 87 88 } 89 } 90 return $temp; 91 } else { 92 return null; 93 } 94 } 95 } 96 return $data; 97 } 98 99 public function delete($key): void 100 { 101 $this->unset($key); 102 } 103 104 /** 105 * 数组去重取唯一的值 106 * @return SplArray 107 */ 108 public function unique(): SplArray 109 { 110 return new SplArray(array_unique($this->getArrayCopy(), SORT_REGULAR)); 111 } 112 113 /** 114 * 获取数组中重复的值 115 * @return SplArray 116 */ 117 public function multiple(): SplArray 118 { 119 $unique_arr = array_unique($this->getArrayCopy(), SORT_REGULAR); 120 return new SplArray(array_udiff_uassoc($this->getArrayCopy(), $unique_arr, function ($key1, $key2) { 121 if ($key1 === $key2) { 122 return 0; 123 } 124 return 1; 125 }, function ($value1, $value2) { 126 if ($value1 === $value2) { 127 return 0; 128 } 129 return 1; 130 })); 131 } 132 133 /** 134 * 按照键值升序 135 * @return SplArray 136 */ 137 public function asort(): SplArray 138 { 139 parent::asort(); 140 return $this; 141 } 142 143 /** 144 * 按照键升序 145 * @return SplArray 146 */ 147 public function ksort(): SplArray 148 { 149 parent::ksort(); 150 return $this; 151 } 152 153 /** 154 * 自定义排序 155 * @param int $sort_flags 156 * @return SplArray 157 */ 158 public function sort($sort_flags = SORT_REGULAR): SplArray 159 { 160 $temp = $this->getArrayCopy(); 161 sort($temp, $sort_flags); 162 return new SplArray($temp); 163 } 164 165 /** 166 * 取得某一列 167 * @param string $column 168 * @param null|string $index_key 169 * @return SplArray 170 */ 171 public function column($column, $index_key = null): SplArray 172 { 173 return new SplArray(array_column($this->getArrayCopy(), $column, $index_key)); 174 } 175 176 /** 177 * 交换数组中的键和值 178 * @return SplArray 179 */ 180 public function flip(): SplArray 181 { 182 return new SplArray(array_flip($this->getArrayCopy())); 183 } 184 185 /** 186 * 过滤本数组 187 * @param string|array $keys 需要取得/排除的键 188 * @param bool $exclude true则排除设置的键名 false则仅获取设置的键名 189 * @return SplArray 190 */ 191 public function filter($keys, $exclude = false): SplArray 192 { 193 if (is_string($keys)) { 194 $keys = explode(',', $keys); 195 } 196 $new = array(); 197 foreach ($this->getArrayCopy() as $name => $value) { 198 if (!$exclude) { 199 in_array($name, $keys) ? $new[$name] = $value : null; 200 } else { 201 in_array($name, $keys) ? null : $new[$name] = $value; 202 } 203 } 204 return new SplArray($new); 205 } 206 207 208 public function keys($path = null): array 209 { 210 if (!empty($path)) { 211 $temp = $this->get($path); 212 if (is_array($temp)) { 213 return array_keys($temp); 214 } else { 215 return []; 216 } 217 } 218 return array_keys((array)$this); 219 } 220 221 /** 222 * 提取数组中的值 223 * @return SplArray 224 */ 225 public function values(): SplArray 226 { 227 return new SplArray(array_values($this->getArrayCopy())); 228 } 229 230 public function flush(): SplArray 231 { 232 foreach ($this->getArrayCopy() as $key => $item) { 233 unset($this[$key]); 234 } 235 return $this; 236 } 237 238 public function loadArray(array $data) 239 { 240 parent::__construct($data); 241 return $this; 242 } 243 244 function merge(array $data) 245 { 246 return $this->loadArray($data + $this->getArrayCopy()); 247 } 248 249 /* 250 $test = new \EasySwoole\Spl\SplArray([ 251 'title'=>'title', 252 'items'=>[ 253 ['title'=>'Some string', 'number' => 1], 254 ['title'=>'Some string', 'number' => 2], 255 ['title'=>'Some string', 'number' => 3] 256 ] 257 ]); 258 */ 259 public function toXML($CD_DATA = false, $rootName = 'xml', $encoding = 'UTF-8', $item = 'item') 260 { 261 $data = $this->getArrayCopy(); 262 if ($CD_DATA) { 263 /* 264 * 默认制定 265 */ 266 $xml = new class('<?xml version="1.0" encoding="' . $encoding . '" ?>' . "<{$rootName}></{$rootName}>") extends \SimpleXMLElement 267 { 268 public function addCData($cdata_text) 269 { 270 $dom = dom_import_simplexml($this); 271 $cdata = $dom->ownerDocument->createCDATASection($cdata_text); 272 $dom->appendChild($cdata); 273 } 274 }; 275 } else { 276 $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="' . $encoding . '" ?>' . "<{$rootName} ></{$rootName}>"); 277 } 278 $parser = function ($xml, $data) use (&$parser, $CD_DATA, $item) { 279 foreach ($data as $k => $v) { 280 if (is_array($v)) { 281 if (!is_numeric($k)) { 282 $ch = $xml->addChild($k); 283 } else { 284 $ch = $xml->addChild($item); 285 } 286 $parser($ch, $v); 287 } else { 288 if (is_numeric($k)) { 289 $xml->addChild($k, $v); 290 } else { 291 if ($CD_DATA) { 292 $n = $xml->addChild($k); 293 $n->addCData($v); 294 } else { 295 $xml->addChild($k, $v); 296 } 297 } 298 } 299 } 300 }; 301 $parser($xml, $data); 302 unset($parser); 303 $str = $xml->asXML(); 304 return substr($str, strpos($str, "\n") + 1); 305 } 306 307} 308