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

есть ли способ преобразовать многомерное array до

13 ответов


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

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;
} 

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

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

/**
 * 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;
}

надеюсь, это может быть полезно


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

/**
 * 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;
} 

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

на json_decode(json_encode($x)) метод обработки два типа правильно, но это не самое быстрое решение. Это все еще прилично, хотя, в общей сложности 25µs за пробег по моим данным образца (усредненный над 1M пробегами, минус накладные расходы цикла.)

Я сравнил несколько вариантов рекурсивного преобразователя и получил следующее. Он перестраивает все массивы и объекты (выполняя глубокую копию), но, похоже, быстрее, чем альтернативные решения, которые изменяют массивы на месте. Это часы на 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()


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

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

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


самый простой способ преобразовать ассоциативный массив в объект:

сначала Закодируйте его в json,затем декодируйте.

как $objectArray = json_decode(json_encode($associtiveArray));


public static function _arrayToObject($array) {
    $json = json_encode($array);
    $object = json_decode($json);
    return $object
}

вот функция для преобразования глубокого массива в объект на месте, которая использует механизм приведения внутреннего (мелкого) массива в объект PHP. Он создает новые объекты только при необходимости, минимизируя дублирование данных.

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

Предупреждение - Не используйте этот код, если существует риск наличия циклических ссылок.


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

    <?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 );

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

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

поздно, но просто хотел упомянуть, что вы можете использовать кодировку/декодирование 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


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;
}