Nobuo Kihara
10 years ago
28 changed files with 683 additions and 379 deletions
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
@ -0,0 +1,311 @@
|
||||
ArrayHelper |
||||
=========== |
||||
|
||||
Additionally to [rich set of PHP array functions](http://php.net/manual/en/book.array.php) Yii array helper provides |
||||
extra static methods allowing you to deal with arrays more efficiently. |
||||
|
||||
|
||||
Getting values |
||||
-------------- |
||||
|
||||
### Getting a single value |
||||
|
||||
Retrieving values from an array, an object or a complex structure consisting of both using standard PHP is quite |
||||
repetitive. You have to check if key exists with `isset` first, then if it does you're getting it, if not, |
||||
providing default value: |
||||
|
||||
```php |
||||
class User |
||||
{ |
||||
public $name = 'Alex'; |
||||
} |
||||
|
||||
$array = [ |
||||
'foo' => [ |
||||
'bar' => new User(), |
||||
] |
||||
]; |
||||
|
||||
$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null; |
||||
``` |
||||
|
||||
Yii provides a very convenient method to do it: |
||||
|
||||
```php |
||||
$value = ArrayHelper::getValue($array, 'foo.bar.name'); |
||||
``` |
||||
|
||||
First method argument is where we're getting value from. Second argument specifies how to get the data. It could be one |
||||
of the following: |
||||
|
||||
- Name of array key or object property to retieve value from. |
||||
- Set of dot separated array key or object property names. The one we've used in the example above. |
||||
- A callback returning a value. |
||||
|
||||
The callback should be the following: |
||||
|
||||
```php |
||||
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) { |
||||
return $user->firstName . ' ' . $user->lastName; |
||||
}); |
||||
``` |
||||
|
||||
Third optional argument is default value which is `null` if not specified. Could be used as follows: |
||||
|
||||
```php |
||||
$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown'); |
||||
``` |
||||
|
||||
In case you want to get the value and then immediately remove it from array you can use `remove` method: |
||||
|
||||
```php |
||||
$array = ['type' => 'A', 'options' => [1, 2]]; |
||||
$type = ArrayHelper::remove($array, 'type'); |
||||
``` |
||||
|
||||
After executing the code `$array` will contain `['options' => [1, 2]]` and `$type` will be `A`. Note that unlike |
||||
`getValue` method, `remove` supports simple key names only. |
||||
|
||||
|
||||
### Checking if key exists |
||||
|
||||
`ArrayHelper::keyExists` works the same way as [array_key_exists](http://php.net/manual/en/function.array-key-exists.php) |
||||
except when trird argument is `false`. In this case it checks for a key in case insensitive manner: |
||||
|
||||
```php |
||||
$data1 = [ |
||||
'userName' => 'Alex', |
||||
]; |
||||
|
||||
$data2 = [ |
||||
'username' => 'Carsten', |
||||
]; |
||||
|
||||
if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) { |
||||
echo "Please provide username."; |
||||
} |
||||
``` |
||||
|
||||
### Getting a column |
||||
|
||||
Often you need to get a column of values from array of data rows or objects. Common keys is getting a list of IDs. |
||||
|
||||
```php |
||||
$data = [ |
||||
['id' => '123', 'data' => 'abc'], |
||||
['id' => '345', 'data' => 'def'], |
||||
]; |
||||
$ids = ArrayHelper::getColumn($array, 'id'); |
||||
``` |
||||
|
||||
The result will be `['123', '345']`. |
||||
|
||||
If additional transformations are required or the way of getting value is complex, second argument could be specified |
||||
as an anonymous function: |
||||
|
||||
```php |
||||
$result = ArrayHelper::getColumn($array, function ($element) { |
||||
return $element['id']; |
||||
}); |
||||
``` |
||||
|
||||
Index array by key specified |
||||
---------------------------- |
||||
|
||||
In order to indexes an array according to a specified key `index` method could be used. 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. For example, |
||||
|
||||
```php |
||||
$array = [ |
||||
['id' => '123', 'data' => 'abc'], |
||||
['id' => '345', 'data' => 'def'], |
||||
]; |
||||
$result = ArrayHelper::index($array, 'id'); |
||||
// the result is: |
||||
// [ |
||||
// '123' => ['id' => '123', 'data' => 'abc'], |
||||
// '345' => ['id' => '345', 'data' => 'def'], |
||||
// ] |
||||
|
||||
// using anonymous function |
||||
$result = ArrayHelper::index($array, function ($element) { |
||||
return $element['id']; |
||||
}); |
||||
``` |
||||
|
||||
|
||||
|
||||
Map array |
||||
--------- |
||||
|
||||
In order to build a map (key-value pairs) from a multidimensional array or an array of objects you can use `map` method. |
||||
The `$from` and `$to` parameters specify the key names or property names to set up the map. Optionally, one can further |
||||
group the map according to a grouping field `$group`. For example, |
||||
|
||||
```php |
||||
$array = [ |
||||
['id' => '123', 'name' => 'aaa', 'class' => 'x'], |
||||
['id' => '124', 'name' => 'bbb', 'class' => 'x'], |
||||
['id' => '345', 'name' => 'ccc', 'class' => 'y'], |
||||
); |
||||
|
||||
$result = ArrayHelper::map($array, 'id', 'name'); |
||||
// the result is: |
||||
// [ |
||||
// '123' => 'aaa', |
||||
// '124' => 'bbb', |
||||
// '345' => 'ccc', |
||||
// ] |
||||
|
||||
$result = ArrayHelper::map($array, 'id', 'name', 'class'); |
||||
// the result is: |
||||
// [ |
||||
// 'x' => [ |
||||
// '123' => 'aaa', |
||||
// '124' => 'bbb', |
||||
// ], |
||||
// 'y' => [ |
||||
// '345' => 'ccc', |
||||
// ], |
||||
// ] |
||||
``` |
||||
|
||||
|
||||
Sort array |
||||
---------- |
||||
|
||||
`sort` method helps to sort an array of objects or nested arrays by one or several keys. For example, |
||||
|
||||
```php |
||||
$data = [ |
||||
['age' => 30, 'name' => 'Alexander'], |
||||
['age' => 30, 'name' => 'Brian'], |
||||
['age' => 19, 'name' => 'Barney'], |
||||
]; |
||||
ArrayHelper::multisort($data, ['age', 'name'], [ArrayHelper::SORT_ASC, ArrayHelper::SORT_DESC]); |
||||
``` |
||||
|
||||
After sorting we'll get the following in `$data`: |
||||
|
||||
```php |
||||
[ |
||||
['age' => 19, 'name' => 'Barney'], |
||||
['age' => 30, 'name' => 'Brian'], |
||||
['age' => 30, 'name' => 'Alexander'], |
||||
]; |
||||
``` |
||||
|
||||
Second argument that specifies keys to sort by could be a string if it's a single key, an array in case of multiple keys |
||||
or an anonymous function like the following one: |
||||
|
||||
```php |
||||
ArrayHelper::multisort($data, function($item) { |
||||
return isset($item['age']) ? ['age', 'name'] : 'name'; |
||||
}); |
||||
``` |
||||
|
||||
Third argument is direction. In case of sorting by a single key it could be either `ArrayHelper::SORT_ASC` or |
||||
`ArrayHelper::SORT_DESC`. If sorting by multiple values you can sort each value differently by providing an array of |
||||
sort direction. |
||||
|
||||
Last argument is PHP sort flag that could take the same values as the ones passed to |
||||
PHP [sort()](http://php.net/manual/en/function.sort.php). |
||||
|
||||
|
||||
Finding out the type of array |
||||
----------------------------- |
||||
|
||||
|
||||
It is handy to know whether array is indexed or an associative. Here's an example: |
||||
|
||||
```php |
||||
// no keys specified |
||||
$indexed = ['Qiang', 'Paul']; |
||||
echo ArrayHelper::isIndexed($indexed); |
||||
|
||||
// all keys are strings |
||||
$associative = ['framework' => 'Yii', 'version' => '2.0']; |
||||
echo ArrayHelper::isAssociative($associative); |
||||
``` |
||||
|
||||
|
||||
HTML-encoding and HTML-decoding values |
||||
-------------------------------------- |
||||
|
||||
In order to encode or decode special characters in an array of strings into HTML entities you can use the following: |
||||
|
||||
```php |
||||
$encoded = ArrayHelper::htmlEncode($data); |
||||
$decoded = ArrayHelper::htmlDecode($data); |
||||
``` |
||||
|
||||
Only values will be encoded by default. By passing second argument as `false` you can encode arrays keys as well. |
||||
Encoding will use application charset and could be changed via third argument. |
||||
|
||||
Merging arrays |
||||
-------------- |
||||
|
||||
/** |
||||
* Merges two or more arrays into one recursively. |
||||
* 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 |
||||
* @param array $b array to be merged from. You can specify additional |
||||
* arrays via third argument, fourth argument etc. |
||||
* @return array the merged array (the original arrays are not changed.) |
||||
*/ |
||||
public static function merge($a, $b) |
||||
|
||||
|
||||
Getting array from object |
||||
------------------------- |
||||
|
||||
Often you need to convert an object or an array of objects into array. The most common case is converting active record |
||||
models in order to serve data arrays via REST API or use it otherwise. The following code could be used to do it: |
||||
|
||||
```php |
||||
$posts = Post::find()->limit(10)->all(); |
||||
$data = ArrayHelper::toArray($post, [ |
||||
'app\models\Post' => [ |
||||
'id', |
||||
'title', |
||||
// the key name in array result => property name |
||||
'createTime' => 'created_at', |
||||
// the key name in array result => anonymous function |
||||
'length' => function ($post) { |
||||
return strlen($post->content); |
||||
}, |
||||
], |
||||
]); |
||||
``` |
||||
|
||||
The first argument contains the data we want to convert. In our case we're converting a `Post` AR model. |
||||
|
||||
The second argument is conversion mapping per class. We're setting a mapping for `Post` model. |
||||
Each mapping array contains a set of mappings. Each mapping could be: |
||||
|
||||
- A field name to include as is. |
||||
- A key-value pair of desired array key name and model colum name to take value from. |
||||
- A key-value pair of desired array key name and a callback which return value will be used. |
||||
|
||||
The result of conversion above will be: |
||||
|
||||
|
||||
```php |
||||
[ |
||||
'id' => 123, |
||||
'title' => 'test', |
||||
'createTime' => '2013-01-01 12:00AM', |
||||
'length' => 301, |
||||
] |
||||
``` |
||||
|
||||
It is possible to provide default way of converting object to array for a specific class by implementing |
||||
[[yii\base\Arrayable|Arrayable]] interface in that class. |
@ -0,0 +1,14 @@
|
||||
Design Decisions |
||||
================ |
||||
|
||||
This document lists the design decisions that we have made after extensive discussions. Unless there are very strong |
||||
reasons, these decisions should be kept for consistency. Any change to these decisions should get agreement among |
||||
the core developers. |
||||
|
||||
1. **[When to support path aliases](https://github.com/yiisoft/yii2/pull/3079#issuecomment-40312268)** |
||||
we should support path alias for properties that are configurable because using path aliases in configurations |
||||
are very convenient. In other cases, we should restrict the support for path aliases. |
||||
2. **When to translate messages** |
||||
messages should be translated when these are displayed to non-tech end user and make sense to him. HTTP status messages, |
||||
exceptions about the code etc. should not be translated. Console messages are always in English because of encoding |
||||
and codepage handling difficulties. |
Loading…
Reference in new issue