Подтвердить что ты не робот

PHP - рекурсивный массив для объекта?

Есть ли способ конвертировать многомерный объект array в объект stdClass в PHP?

Кастинг как (object) не работает рекурсивно. json_decode(json_encode($array)) дает результат, который я ищу, но должен быть лучший способ...

4b9b3361

Ответ 1

Насколько я могу судить, для этого нет заранее подготовленного решения, поэтому вы можете просто сворачивать свой собственный:

function array_to_object($array) {
  $obj = new stdClass;
  foreach($array as $k => $v) {
     if(strlen($k)) {
        if(is_array($v)) {
           $obj->{$k} = array_to_object($v); //RECURSION
        } else {
           $obj->{$k} = $v;
        }
     }
  }
  return $obj;
} 

Ответ 2

Я знаю, что этот ответ приходит поздно, но я отправлю его всем, кто ищет решение.

Вместо всего этого цикла и т.д. вы можете использовать функцию PHP json_ *. У меня есть несколько удобных функций, которые я использую много.

/**
 * Convert an array into a stdClass()
 * 
 * @param   array   $array  The array we want to convert
 * 
 * @return  object
 */
function arrayToObject($array)
{
    // First we convert the array to a json string
    $json = json_encode($array);

    // The we convert the json string to a stdClass()
    $object = json_decode($json);

    return $object;
}


/**
 * Convert a object to an array
 * 
 * @param   object  $object The object we want to convert
 * 
 * @return  array
 */
function objectToArray($object)
{
    // First we convert the object into a json string
    $json = json_encode($object);

    // Then we convert the json string to an array
    $array = json_decode($json, true);

    return $array;
}

Надеюсь, это будет полезно

Ответ 3

function toObject($array) {
    $obj = new stdClass();
    foreach ($array as $key => $val) {
        $obj->$key = is_array($val) ? toObject($val) : $val;
    }
    return $obj;
}

Ответ 4

/**
 * Recursively converts associative arrays to stdClass while keeping integer keys subarrays as arrays
 * (lists of scalar values or collection of objects).
 */
function a2o( array $array ) {
    $resultObj = new \stdClass;
    $resultArr = array();
    $hasIntKeys = false;
    $hasStrKeys = false;
    foreach ( $array as $k => $v ) {
        if ( !$hasIntKeys ) {
            $hasIntKeys = is_int( $k );
        }
        if ( !$hasStrKeys ) {
            $hasStrKeys = is_string( $k );
        }
        if ( $hasIntKeys && $hasStrKeys ) {
            $e = new \Exception( 'Current level has both integer and string keys, thus it is impossible to keep array or convert to object' );
            $e->vars = array( 'level' => $array );
            throw $e;
        }
        if ( $hasStrKeys ) {
            $resultObj->{$k} = is_array( $v ) ? a2o( $v ) : $v;
        } else {
            $resultArr[$k] = is_array( $v ) ? a2o( $v ) : $v;
        }
    }
    return ($hasStrKeys) ? $resultObj : $resultArr;
} 

Ответ 5

Некоторые из других решений, размещенных здесь, не могут отличить последовательные массивы (что было бы [] в JS) от карт ({} в JS.) Для многих случаев использования важно рассказать обо всех PHP-массивах, которые имеют все последовательные числовые ключи, которые должны быть оставлены как таковые, из массивов PHP, которые не имеют числовых ключей, которые должны быть преобразованы в объекты. (Мои решения ниже undefined для массивов, которые не попадают в две вышеуказанные категории.)

Метод json_decode(json_encode($x)) корректно обрабатывает два типа, но не является самым быстрым решением. Тем не менее, он по-прежнему приличный, всего 25 мкс за каждый прогон на мои данные образца (усредненный за 1М пробегов, минус накладные расходы цикла).

Я сравнил пару вариаций рекурсивного конвертера и получил следующее. Он восстанавливает все массивы и объекты (выполняет глубокую копию), но, кажется, быстрее, чем альтернативные решения, которые изменяют массивы на месте. Он синхронизируется с 11μs за выполнение по моим данным образца:

function array_to_object($x) {
    if (!is_array($x)) {
        return $x;
    } elseif (is_numeric(key($x))) {
        return array_map(__FUNCTION__, $x);
    } else {
        return (object) array_map(__FUNCTION__, $x);
    }
}

Вот версия на месте. Это может быть быстрее на некоторых больших входных данных, где нужно преобразовать только мелкие части, но по моим образцам данных он выполнял 15 мкс за выполнение:

function array_to_object_inplace(&$x) {
    if (!is_array($x)) {
        return;
    }
    array_walk($x, __FUNCTION__);
    reset($x);
    if (!is_numeric(key($x))) {
        $x = (object) $x;
    }
}

Я не тестировал решения, используя array_walk_recursive()

Ответ 6

Поздно, но просто хотелось упомянуть, что вы можете использовать кодировку/декодирование JSON для полного преобразования из/в массив:

//convert object $object into array
$array = json_decode(json_encode($object), true);
//convert array $array into object
$object = json_decode(json_encode($array));

Функции json_encode и json_decode доступны начиная с php 5.2

Ответ 7

Здесь вы можете выполнить преобразование массива в место на месте, использующее внутренний (неглубокий) внутренний механизм ввода-вывода типа "массив-объект". Он создает новые объекты только при необходимости, сводя к минимуму дублирование данных.

function toObject($array) {
    foreach ($array as $key=>$value)
        if (is_array($value))
            $array[$key] = toObject($value);
    return (object)$array;
}

Предупреждение - не используйте этот код, если существует риск иметь круглые ссылки.

Ответ 8

EDIT: Эта функция является преобразованием из объекта в массив.

От https://forrst.com/posts/PHP_Recursive_Object_to_Array_good_for_handling-0ka

protected function object_to_array($obj)
{
    $arrObj = is_object($obj) ? get_object_vars($obj) : $obj;
    foreach ($arrObj as $key => $val) {
            $val = (is_array($val) || is_object($val)) ? $this->object_to_array($val) : $val;
            $arr[$key] = $val;
    }
    return $arr;
}

Ответ 9

Вот гладкий способ сделать это, который может обрабатывать ассоциативный массив с большой глубиной и не перезаписывать свойства объекта, которые не находятся в массиве.

    <?php

    function setPropsViaArray( $a, $o )
    {
        foreach ( $a as $k => $v )
        {
            if ( is_array( $v ) )
            {
                $o->{$k} = setPropsViaArray( $v, ! empty ( $o->{$k} ) ? $o->{$k} : new stdClass() );
            }
            else
            {
                $o->{$k} = $v;
            }
        }
        return $o;
    };

    setPropsViaArray( $newArrayData, $existingObject );

Ответ 10

Самое короткое, что я мог бы придумать:

array_walk_recursive($obj, function (&$val) { if (is_object($val)) $val = get_object_vars($val); });

Ответ 11

Вы можете использовать array_map рекурсивно:

public static function _arrayToObject($array) {
    return is_array($array) ? (object) array_map([__CLASS__, __METHOD__], $array) : $array;
}

Прекрасно подходит для меня, поскольку он не отображает, например, углеродные объекты в базовый stdClass (который кодируется/декодирует json)