ArrayHelper.php 7.38 KB
Newer Older
Qiang Xue committed
1 2 3 4 5 6 7 8 9 10 11 12
<?php
/**
 * ArrayHelper class file.
 *
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2012 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\util;

/**
13 14
 * ArrayHelper provides additional array functionality you can use in your
 * application.
Qiang Xue committed
15 16 17 18
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
Qiang Xue committed
19
class ArrayHelper
Qiang Xue committed
20 21
{
	/**
Qiang Xue committed
22
	 * Merges two or more arrays into one recursively.
Qiang Xue committed
23 24 25 26 27 28 29
	 * If each array has an element with the same string key value, the latter
	 * will overwrite the former (different from array_merge_recursive).
	 * Recursive merging will be conducted if both arrays have an element of array
	 * type and are having the same key.
	 * For integer-keyed elements, the elements from the latter array will
	 * be appended to the former array.
	 * @param array $a array to be merged to
Qiang Xue committed
30 31
	 * @param array $b array to be merged from. You can specify additional
	 * arrays via third argument, fourth argument etc.
Qiang Xue committed
32 33 34 35
	 * @return array the merged array (the original arrays are not changed.)
	 */
	public static function merge($a, $b)
	{
Qiang Xue committed
36 37 38 39 40 41 42 43 44 45 46 47
		$args = func_get_args();
		$res = array_shift($args);
		while ($args !== array()) {
			$next = array_shift($args);
			foreach ($next as $k => $v) {
				if (is_integer($k)) {
					isset($res[$k]) ? $res[] = $v : $res[$k] = $v;
				} elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
					$res[$k] = self::merge($res[$k], $v);
				} else {
					$res[$k] = $v;
				}
Qiang Xue committed
48 49
			}
		}
Qiang Xue committed
50
		return $res;
Qiang Xue committed
51 52 53
	}

	/**
Qiang Xue committed
54
	 * Retrieves the value of an array element or object property with the given key or property name.
Qiang Xue committed
55
	 * If the key does not exist in the array, the default value will be returned instead.
Qiang Xue committed
56 57
	 *
	 * Below are some usage examples,
Qiang Xue committed
58 59
	 *
	 * ~~~
Qiang Xue committed
60
	 * // working with array
Qiang Xue committed
61
	 * $username = \yii\util\ArrayHelper::get($_POST, 'username');
Qiang Xue committed
62 63 64 65 66 67
	 * // working with object
	 * $username = \yii\util\ArrayHelper::get($user, 'username');
	 * // working with anonymous function
	 * $fullName = \yii\util\ArrayHelper::get($user, function($user, $defaultValue) {
	 *     return $user->firstName . ' ' . $user->lastName;
	 * });
Qiang Xue committed
68 69
	 * ~~~
	 *
Qiang Xue committed
70 71 72 73
	 * @param array|object $array array or object to extract value from
	 * @param string|\Closure $key key name of the array element, or property name of the object,
	 * or an anonymous function returning the value. The anonymous function signature should be:
	 * `function($array, $defaultValue)`.
Qiang Xue committed
74
	 * @param mixed $default the default value to be returned if the specified key does not exist
Qiang Xue committed
75
	 * @return mixed the value of the
Qiang Xue committed
76 77 78
	 */
	public static function get($array, $key, $default = null)
	{
Qiang Xue committed
79
		if ($key instanceof \Closure) {
Qiang Xue committed
80
			return $key($array, $default);
Qiang Xue committed
81 82 83 84 85
		} elseif (is_array($array)) {
			return isset($array[$key]) || array_key_exists($key, $array) ? $array[$key] : $default;
		} else {
			return $array->$key;
		}
Qiang Xue committed
86
	}
Qiang Xue committed
87 88

	/**
89 90 91 92 93 94 95 96
	 * Indexes an array according to a specified key.
	 * The input array should be multidimensional or an array of objects.
	 *
	 * The key can be a key name of the sub-array, a property name of object, or an anonymous
	 * function which returns the key value given an array element.
	 *
	 * If a key value is null, the corresponding array element will be discarded and not put in the result.
	 *
Qiang Xue committed
97 98 99 100 101 102 103 104 105 106 107
	 * For example,
	 *
	 * ~~~
	 * $array = array(
	 *     array('id' => '123', 'data' => 'abc'),
	 *     array('id' => '345', 'data' => 'def'),
	 * );
	 * $result = ArrayHelper::index($array, 'id');
	 * // the result is:
	 * // array(
	 * //     '123' => array('id' => '123', 'data' => 'abc'),
108
	 * //     '345' => array('id' => '345', 'data' => 'def'),
Qiang Xue committed
109 110 111 112 113 114
	 * // )
	 *
	 * // using anonymous function
	 * $result = ArrayHelper::index($array, function(element) {
	 *     return $element['id'];
	 * });
115
	 * ~~~
Qiang Xue committed
116
	 *
117 118
	 * @param array $array the array that needs to be indexed
	 * @param string|\Closure $key the column name or anonymous function whose result will be used to index the array
Qiang Xue committed
119
	 * @return array the indexed array
Qiang Xue committed
120 121 122 123
	 */
	public static function index($array, $key)
	{
		$result = array();
Qiang Xue committed
124 125 126
		foreach ($array as $element) {
			$value = static::get($element, $key);
			$result[$value] = $element;
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
		}
		return $result;
	}

	/**
	 * Returns the values of a specified column in an array.
	 * The input array should be multidimensional or an array of objects.
	 *
	 * For example,
	 *
	 * ~~~
	 * $array = array(
	 *     array('id' => '123', 'data' => 'abc'),
	 *     array('id' => '345', 'data' => 'def'),
	 * );
	 * $result = ArrayHelper::column($array, 'id');
	 * // the result is: array( '123', '345')
	 *
	 * // using anonymous function
	 * $result = ArrayHelper::column($array, function(element) {
	 *     return $element['id'];
	 * });
	 * ~~~
	 *
	 * @param array $array
	 * @param string|\Closure $key
	 * @return array the list of column values
	 */
	public static function column($array, $key)
	{
		$result = array();
Qiang Xue committed
158 159
		foreach ($array as $element) {
			$result[] = static::get($element, $key);
Qiang Xue committed
160 161 162
		}
		return $result;
	}
163 164 165 166

	/**
	 * Builds a map (key-value pairs) from a multidimensional array or an array of objects.
	 * The `$from` and `$to` parameters specify the key names or property names to set up the map.
Qiang Xue committed
167
	 * Optionally, one can further group the map according to a grouping field `$group`.
168 169 170 171 172
	 *
	 * For example,
	 *
	 * ~~~
	 * $array = array(
Qiang Xue committed
173 174 175
	 *     array('id' => '123', 'name' => 'aaa', 'class' => 'x'),
	 *     array('id' => '124', 'name' => 'bbb', 'class' => 'x'),
	 *     array('id' => '345', 'name' => 'ccc', 'class' => 'y'),
176
	 * );
Qiang Xue committed
177 178 179 180 181 182 183 184 185 186
	 *
	 * $result = ArrayHelper::map($array, 'id', 'name');
	 * // the result is:
	 * // array(
	 * //     '123' => 'aaa',
	 * //     '124' => 'bbb',
	 * //     '345' => 'ccc',
	 * // )
	 *
	 * $result = ArrayHelper::map($array, 'id', 'name', 'class');
187 188
	 * // the result is:
	 * // array(
Qiang Xue committed
189 190 191 192 193 194 195
	 * //     'x' => array(
	 * //         '123' => 'aaa',
	 * //         '124' => 'bbb',
	 * //     ),
	 * //     'y' => array(
	 * //         '345' => 'ccc',
	 * //     ),
196 197 198
	 * // )
	 * ~~~
	 *
Qiang Xue committed
199
	 * @param array $array
Qiang Xue committed
200 201 202
	 * @param string|\Closure $from
	 * @param string|\Closure $to
	 * @param string|\Closure $group
203 204
	 * @return array
	 */
Qiang Xue committed
205
	public static function map($array, $from, $to, $group = null)
206 207 208
	{
		$result = array();
		foreach ($array as $element) {
Qiang Xue committed
209 210 211 212 213 214
			$key = static::get($element, $from);
			$value = static::get($element, $to);
			if ($group !== null) {
				$result[static::get($element, $group)][$key] = $value;
			} else {
				$result[$key] = $value;
215 216 217 218
			}
		}
		return $result;
	}
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

	/**
	 * Searches the array for a given value and returns the corresponding key if found.
	 * This method is similar to array_search() with the enhancement that it can also
	 * search for strings in a case-insensitive manner.
	 * @param mixed $needle the value being searched for
	 * @param array $haystack the array to be searched through
	 * @param boolean $caseSensitive whether to perform a case-sensitive search
	 * @param boolean $strict whether to perform a type-strict search
	 * @return boolean|mixed the key of the value if it matches $needle. False if the value is not found.
	 */
	public static function search($needle, array $haystack, $caseSensitive = true, $strict = true)
	{
		if ($caseSensitive || !is_string($needle)) {
			return array_search($needle, $haystack, $strict);
		}
		foreach ($haystack as $key => $value) {
			if (is_string($value)) {
				if (strcasecmp($value, $needle) === 0) {
					return true;
				}
			} elseif ($strict && $key === $value || !$strict && $key == $value) {
				return true;
			}
		}
		return false;
	}
Qiang Xue committed
246
}