diff --git a/CHANGELOG.md b/CHANGELOG.md index b3a90ac..74d0686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # (MODX)EvolutionCMS.libraries.ddTools changelog +## Version 0.57 (2023-03-09) +* \+ `\DDTools\ObjectTools::getPropValue` → Parameters → `$params->propName`: The method can now get the value of an object property or an array element in any nesting level. Just use `'.'` to get nested properties. + Several examples (see full examples in README): + * \* `somePlainProp` — get first-level property. + * \* `someObjectProp.secondLevelProp` — get property of the `someObjectProp` object|array. + * \* `someArrayProp.0.thirdLevelProp` — get property of the zero element of the `someArrayProp` array. + + ## Version 0.56 (2023-01-29) * \+ `\ddTools::sort2dArray` → Parameters → `$array[$i]`: Can also be set as object. * \* `\DDTools\Base\Base`: diff --git a/CHANGELOG_ru.md b/CHANGELOG_ru.md index cb625b7..5488a54 100644 --- a/CHANGELOG_ru.md +++ b/CHANGELOG_ru.md @@ -1,6 +1,14 @@ # (MODX)EvolutionCMS.libraries.ddTools changelog +## Версия 0.57 (2023-03-09) +* \+ `\DDTools\ObjectTools::getPropValue` → Параметры → `$params->propName`: Теперь метод умеет получать значение свойства объекта или элемента массива на любом уровне вложенности. Просто используйте `'.'` в параметре для получения свойств вложенных элементов. + Несколько примеров (см. полные примеры в README): + * \* `somePlainProp` — получить свойство первого уровня. + * \* `someObjectProp.secondLevelProp` — получить свойство объекта|массива `someObjectProp`. + * \* `someArrayProp.0.thirdLevelProp` — получить свойство нулевого элемента массива `someArrayProp`. + + ## Версия 0.56 (2023-01-29) * \+ `\ddTools::sort2dArray` → Параметры → `$array[$i]`: Также может быть задан, как объект. * \* `\DDTools\Base\Base`: diff --git a/README.md b/README.md index 308ad4c..1776a9d 100644 --- a/README.md +++ b/README.md @@ -336,8 +336,7 @@ Second, the different order of parameters in the native PHP functions makes us c #### `\DDTools\ObjectTools::getPropValue($params)` -Get the value of an object property or an array element. -This is a “syntactic sugar” for getting an element in one way regardless of the “object” type. +Get the value of an object property or an array element in any nesting level in one way regardless of the “object” type. * `$params` * Desctription: Parameters, the pass-by-name style is used. @@ -347,14 +346,19 @@ This is a “syntactic sugar” for getting an element in one way regardless of * **Required** * `$params->object` - * Desctription: Source object or array. + * Desctription: Source object or array. + It can be nested, and elements of all levels can be mix of objects and arrays (see Examples below). * Valid values: * `stdClass` * `array` * **Required** * `$params->propName` - * Desctription: Object property name or array key. + * Desctription: Object property name or array key. + You can also use `'.'` to get nested properties. Several examples (see also full Examples below): + * `somePlainProp` — get first-level property + * `someObjectProp.secondLevelProp` — get property of the `someObjectProp` object|array + * `someArrayProp.0.thirdLevelProp` — get property of the zero element of the `someArrayProp` array * Valid values: * `string` * `integer` @@ -1566,7 +1570,8 @@ Both calls return `true`. #### `\DDTools\ObjectTools::getPropValue($params)` -Get the value of an object property or an array element using the same syntax. + +##### Get the value of an object property or an array element using the same syntax You can pass an object: @@ -1595,6 +1600,142 @@ var_export(\DDTools\ObjectTools::getPropValue([ Both calls return `'Floyd'`. +##### Get the value of an object property or an array element in any nesting level + +Source object can be nested, and elements of all levels can be mix of objects and arrays. + +```php +//For example let the first level be stdClass +$sourceObject = (object) [ + //Let the second level be an indexed array + 'PinkFloyd' => [ + //Let the third level be an associative array + [ + 'name' => 'Syd Barrett', + 'role' => 'lead and rhythm guitars, vocals' + ], + [ + 'name' => 'David Gilmour', + 'role' => 'lead and rhythm guitars, vocals, bass, keyboards, synthesisers' + ], + //Let Roger be a little bit special ;) + (object) [ + 'name' => 'Roger Waters', + 'role' => 'bass, vocals, rhythm guitar, synthesisers' + ], + [ + 'name' => 'Richard Wright', + 'role' => 'keyboards, piano, organ, synthesisers, vocals' + ], + [ + 'name' => 'Nick Mason', + 'role' => 'drums, percussion' + ] + ] +]; +``` + + +###### Get a first-level property + +There's nothing special, just look at this example for the full picture. + +```php +var_export(\DDTools\ObjectTools::getPropValue([ + 'object' => $sourceObject, + 'propName' => 'PinkFloyd' +])); +``` + +Returns: + +```php +array ( + 0 => array ( + 'name' => 'Syd Barrett', + 'role' => 'lead and rhythm guitars, vocals', + ), + 1 => array ( + 'name' => 'David Gilmour', + 'role' => 'lead and rhythm guitars, vocals, bass, keyboards, synthesisers', + ), + 2 => stdClass::__set_state(array( + 'name' => 'Roger Waters', + 'role' => 'bass, vocals, rhythm guitar, synthesisers', + )), + 3 => array ( + 'name' => 'Richard Wright', + 'role' => 'keyboards, piano, organ, synthesisers, vocals', + ), + 4 => array ( + 'name' => 'Nick Mason', + 'role' => 'drums, percussion', + ), +) +``` + + +###### Get a second-level property + +Let's make it a little more interesting: let's get the 4th element of the second-level indexed array. + +```php +var_export(\DDTools\ObjectTools::getPropValue([ + 'object' => $sourceObject, + 'propName' => 'PinkFloyd.4' +])); +``` + +Returns: + +```php +array ( + 'name' => 'Nick Mason', + 'role' => 'drums, percussion', +) +``` + + +###### Get a third-level property + +Any level of nesting is supported. + +No matter what type of element is used in any nesting level, the method will work fine. +So let's get Roger's name. As you remember, he is stdClass as opposed to the other members who are associative arrays. + +```php +var_export(\DDTools\ObjectTools::getPropValue([ + 'object' => $sourceObject, + 'propName' => 'PinkFloyd.2.name' +])); +``` + +Returns: + +```php +'Roger Waters' +``` + + +###### Of course, it works fine with single-level objects that contain `'.'` in their property names + +```php +var_export(\DDTools\ObjectTools::getPropValue([ + 'object' => [ + '1973.03.01' => 'The Dark Side of the Moon', + '1975.09.12' => 'Wish You Were Here' + ], + 'propName' => '1975.09.12' +])); +``` + +Returns: + +```php +'Wish You Were Here' +``` + + ### `\DDTools\ObjectCollection` diff --git a/composer.json b/composer.json index 2bb3bd4..abda380 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "dd/evolutioncms-libraries-ddtools", "type": "modxevo-library-ddtools", - "version": "0.56.0", + "version": "0.57.0", "description": "A library with various tools facilitating your work.", "keywords": [ "modx", diff --git a/modx.ddtools.class.php b/modx.ddtools.class.php index 87ada1b..6580be9 100644 --- a/modx.ddtools.class.php +++ b/modx.ddtools.class.php @@ -1,7 +1,7 @@ object {stdClass|array} — Source object or array.. @required + * @param $params->propName {string|integer} — Object property name or array key. @required * - * @return {mixed} + * @return {mixed|null} */ - public static function getPropValue($params){ + private static function getSingleLevelPropValue($params){ $params = (object) $params; return !self::isPropExists($params) ? //Non-existing properties - NULL : + null : //Existing properties ( is_object($params->object) ? @@ -69,6 +71,60 @@ public static function getPropValue($params){ ; } + /** + * getPropValue + * @version 1.1 (2023-03-09) + * + * @see README.md + * + * @return {mixed|null} + */ + public static function getPropValue($params){ + $params = (object) $params; + + //First try to get value by original propName + $result = self::getSingleLevelPropValue($params); + + if (is_null($result)){ + //Unfolding support (e. g. `parentKey.someKey.0`) + $propNames = explode( + '.', + $params->propName + ); + + //If first-level exists + if ( + \DDTools\ObjectTools::isPropExists([ + 'object' => $params->object, + 'propName' => $propNames[0] + ]) + ){ + $result = $params->object; + + //Find needed value + foreach ( + $propNames as + $propName + ){ + //If need to see deeper + if (self::isObjectOrArray($result)){ + $result = self::getSingleLevelPropValue([ + 'object' => $result, + 'propName' => $propName + ]); + }else{ + //We need to look deeper, but we can't + $result = null; + + break; + } + } + } + } + + return $result; + } + /** * convertType * @version 1.2 (2021-11-08) @@ -195,7 +251,7 @@ public static function convertType($params){ /** * extend - * @version 1.3.9 (2021-04-27) + * @version 1.3.10 (2023-03-09) * * @see README.md * @@ -239,7 +295,7 @@ public static function extend($params){ if ($isSourcePropExists){ //Source property value - $sourcePropValue = self::getPropValue([ + $sourcePropValue = self::getSingleLevelPropValue([ 'object' => $result, 'propName' => $additionalPropName ]);