Как преобразовать массив в объект в PHP?
Как я могу преобразовать такой массив в объект?
[128] => Array ( [status] => Figure A. Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution. ) [129] => Array ( [status] => The other day at work, I had some spare time ) )
30 answers
В простейшем случае, вероятно, достаточно "привести" массив в качестве объекта:
$object = (object) $array;
Другим вариантом было бы создать экземпляр стандартного класса в качестве переменной и выполнить цикл по вашему массиву, переназначая значения:
$object = new stdClass();
foreach ($array as $key => $value)
{
$object->$key = $value;
}
Как указал Эдсон Медина, действительно чистое решение - использовать встроенные функции json_
:
$object = json_decode(json_encode($array), FALSE);
Это также (рекурсивно) преобразует все ваши вложенные массивы в объекты, которые вам могут понадобиться, а могут и не понадобиться. К несчастью он имеет 2-3-кратное снижение производительности по сравнению с циклическим подходом.
Внимание! (спасибо Ultra за комментарий):
Json_decode в разных средах преобразует данные UTF-8 по-разному. В итоге я получаю значения "240.00" на местном уровне и "240" на производстве - массовый диссернет. Более того, если преобразование завершается неудачно, строка get возвращается как NULL
Вы можете просто использовать приведение типов для преобразования массива в объект.
// *convert array to object* Array([id]=> 321313[username]=>shahbaz)
$object = (object) $array_name;
//now it is converted to object and you can access it.
echo $object->username;
Вот три способа:
-
Подделка реального объекта:
class convert { public $varible; public function __construct($array) { $this = $array; } public static function toObject($array) { $array = new convert($array); return $array; } }
-
Преобразуйте массив в объект, приведя его к объекту:
$array = array( // ... ); $object = (object) $array;
-
Вручную преобразуйте массив в объект:
$object = object; foreach ($arr as $key => $value) { $object->{$key} = $value; }
Быстрый взлом:
// assuming $var is a multidimensional array
$obj = json_decode (json_encode ($var), FALSE);
Не очень красиво, но работает.
Самым простым способом было бы
$object = (object)$array;
Но это не то, чего ты хочешь. Если вам нужны объекты, вы хотите чего-то достичь, но в этом вопросе этого не хватает. Использование объектов только по причине использования объектов не имеет смысла.
Его способ прост, это также создаст объект для рекурсивных массивов:
$object = json_decode(json_encode((object) $yourArray), FALSE);
В зависимости от того, где вам это нужно и как получить доступ к объекту, существуют различные способы сделать это.
Например: просто введите его
$object = (object) $yourArray;
Однако наиболее совместимым является использование служебного метода (еще не являющегося частью PHP), который реализует стандартное приведение PHP на основе строки, указывающей тип (или игнорируя его, просто удаляя ссылку на значение):
/**
* dereference a value and optionally setting its type
*
* @param mixed $mixed
* @param null $type (optional)
*
* @return mixed $mixed set as $type
*/
function rettype($mixed, $type = NULL) {
$type === NULL || settype($mixed, $type);
return $mixed;
}
Пример использования в вашем случае (Онлайн-демонстрация):
$yourArray = Array('status' => 'Figure A. ...');
echo rettype($yourArray, 'object')->status; // prints "Figure A. ..."
Это сработало для меня
function array_to_obj($array, &$obj)
{
foreach ($array as $key => $value)
{
if (is_array($value))
{
$obj->$key = new stdClass();
array_to_obj($value, $obj->$key);
}
else
{
$obj->$key = $value;
}
}
return $obj;
}
function arrayToObject($array)
{
$object= new stdClass();
return array_to_obj($array,$object);
}
Использование :
$myobject = arrayToObject($array);
print_r($myobject);
Возвращает :
[127] => stdClass Object
(
[status] => Have you ever created a really great looking website design
)
[128] => stdClass Object
(
[status] => Figure A.
Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
)
[129] => stdClass Object
(
[status] => The other day at work, I had some spare time
)
Как обычно, вы можете зациклить его, как:
foreach($myobject as $obj)
{
echo $obj->status;
}
Насколько мне известно, для этого нет встроенного метода, но это так же просто, как простой цикл:
$obj= new stdClass();
foreach ($array as $k=> $v) {
$obj->{$k} = $v;
}
Вы можете подробно рассказать об этом, если вам это нужно для рекурсивного построения вашего объекта.
На самом деле, если вы хотите использовать это с многомерными массивами, вы бы хотели использовать некоторую рекурсию.
static public function array_to_object(array $array)
{
foreach($array as $key => $value)
{
if(is_array($value))
{
$array[$key] = self::array_to_object($value);
}
}
return (object)$array;
}
Я бы определенно выбрал такой чистый путь:
<?php
class Person {
private $name;
private $age;
private $sexe;
function __construct ($payload)
{
if (is_array($payload))
$this->from_array($payload);
}
public function from_array($array)
{
foreach(get_object_vars($this) as $attrName => $attrValue)
$this->{$attrName} = $array[$attrName];
}
public function say_hi ()
{
print "hi my name is {$this->name}";
}
}
print_r($_POST);
$mike = new Person($_POST);
$mike->say_hi();
?>
Если вы отправите:
Вы получите это:
Я нашел это более логичным, сравнивая приведенные выше ответы от объектов, которые следует использовать для той цели, для которой они были созданы (инкапсулированные милые маленькие объекты).
Также с помощью get_object_vars убедитесь, что в управляемом объекте не создаются дополнительные атрибуты (вы не хотите, чтобы автомобиль имел фамилию или человека ведущие себя 4 колеса).
Рекурсия - ваш друг:
function __toObject(Array $arr) {
$obj = new stdClass();
foreach($arr as $key=>$val) {
if (is_array($val)) {
$val = __toObject($val);
}
$obj->$key = $val;
}
return $obj;
}
Легко:
$object = json_decode(json_encode($array));
Пример:
$array = array(
'key' => array(
'k' => 'value',
),
'group' => array('a', 'b', 'c')
);
$object = json_decode(json_encode($array));
Тогда верно следующее:
$object->key->k === 'value';
$object->group === array('a', 'b', 'c')
Вы также можете использовать объект ArrayObject, например:
<?php
$arr = array("test",
array("one"=>1,"two"=>2,"three"=>3),
array("one"=>1,"two"=>2,"three"=>3)
);
$o = new ArrayObject($arr);
echo $o->offsetGet(2)["two"],"\n";
foreach ($o as $key=>$val){
if (is_array($val)) {
foreach($val as $k => $v) {
echo $k . ' => ' . $v,"\n";
}
}
else
{
echo $val,"\n";
}
}
?>
//Output:
2
test
one => 1
two => 2
three => 3
one => 1
two => 2
three => 3
Тот, который я использую (это член класса):
const MAX_LEVEL = 5; // change it as needed
public function arrayToObject($a, $level=0)
{
if(!is_array($a)) {
throw new InvalidArgumentException(sprintf('Type %s cannot be cast, array expected', gettype($a)));
}
if($level > self::MAX_LEVEL) {
throw new OverflowException(sprintf('%s stack overflow: %d exceeds max recursion level', __METHOD__, $level));
}
$o = new stdClass();
foreach($a as $key => $value) {
if(is_array($value)) { // convert value recursively
$value = $this->arrayToObject($value, $level+1);
}
$o->{$key} = $value;
}
return $o;
}
Используйте эту функцию, которую я создал:
function buildObject($class,$data){
$object = new $class;
foreach($data as $key=>$value){
if(property_exists($class,$key)){
$object->{'set'.ucfirst($key)}($value);
}
}
return $object;
}
Использование:
$myObject = buildObject('MyClassName',$myArray);
Немного сложная, но простая в расширении техника:
Предположим, у вас есть массив
$a = [
'name' => 'ankit',
'age' => '33',
'dob' => '1984-04-12'
];
Предположим, у вас есть класс person, который может иметь больше или меньше атрибутов из этого массива. например
class Person
{
private $name;
private $dob;
private $age;
private $company;
private $city;
}
Если вы все еще хотите изменить свой массив на объект person. Вы можете использовать класс ArrayIterator.
$arrayIterator = new \ArrayIterator($a); // Pass your array in the argument.
Теперь у вас есть объект итератора.
Создайте класс, расширяющий класс FilterIterator; где вы должны определить абстрактный метод accept. Следовать пример
class PersonIterator extends \FilterIterator
{
public function accept()
{
return property_exits('Person', parent::current());
}
}
Приведенное выше побуждение свяжет свойство только в том случае, если оно существует в классе.
Добавьте еще один метод в класс PersonIterator
public function getObject(Person $object)
{
foreach ($this as $key => $value)
{
$object->{'set' . underscoreToCamelCase($key)}($value);
}
return $object;
}
Убедитесь, что в вашем классе определены мутаторы. Теперь вы готовы вызвать эти функции там, где вы хотите создать объект.
$arrayiterator = new \ArrayIterator($a);
$personIterator = new \PersonIterator($arrayiterator);
$personIterator->getObject(); // this will return your Person Object.
Вы также можете сделать это, добавив (объект) слева от переменной, чтобы создать новый объект.
<?php
$a = Array
( 'status' => " text" );
var_dump($a);
$b = (object)$a;
var_dump($b);
var_dump($b->status);
Использование json_encode
проблематично из-за способа обработки данных, отличных от UTF-8. Стоит отметить, что json_encode
/json_encode
метод также оставляет неассоциативные массивы в виде массивов. Это может быть или не быть тем, чего вы хотите. Недавно мне понадобилось воссоздать функциональность этого решения, но без использования функций json_
. Вот что я придумал:
/**
* Returns true if the array has only integer keys
*/
function isArrayAssociative(array $array) {
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
/**
* Converts an array to an object, but leaves non-associative arrays as arrays.
* This is the same logic that `json_decode(json_encode($arr), false)` uses.
*/
function arrayToObject(array $array, $maxDepth = 10) {
if($maxDepth == 0) {
return $array;
}
if(isArrayAssociative($array)) {
$newObject = new \stdClass;
foreach ($array as $key => $value) {
if(is_array($value)) {
$newObject->{$key} = arrayToObject($value, $maxDepth - 1);
} else {
$newObject->{$key} = $value;
}
}
return $newObject;
} else {
$newArray = array();
foreach ($array as $value) {
if(is_array($value)) {
$newArray[] = arrayToObject($value, $maxDepth - 1);
} else {
$newArray[] = $value;
}
}
return $newArray;
}
}
Лучший метод в МИРЕ:)
function arrayToObject($conArray)
{
if(is_array($conArray)){
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return (object) array_map(__FUNCTION__, $conArray);
}else{
// Return object
return $conArray;
}
}
Если вы используете другие методы, у вас возникнут проблемы. Это лучший метод. Вы когда-либо видели.
Один лайнер
$object= json_decode(json_encode($result_array, JSON_FORCE_OBJECT));
Для этого требуется PHP7, потому что я решил использовать лямбда-функцию для блокировки "внутренней функции" в основной функции. Лямбда-функция вызывается рекурсивно, следовательно, необходимо: "использовать (&$innerfunc)". Вы могли бы сделать это в PHP5, но не смогли скрыть внутреннюю функцию.
function convertArray2Object($defs) {
$innerfunc = function ($a) use ( &$innerfunc ) {
return (is_array($a)) ? (object) array_map($innerfunc, $a) : $a;
};
return (object) array_map($innerfunc, $defs);
}
Очевидно, что это просто экстраполяция ответов некоторых других людей, но вот рекурсивная функция, которая преобразует любой многомерный массив в объект:
function convert_array_to_object($array){
$obj= new stdClass();
foreach ($array as $k=> $v) {
if (is_array($v)){
$v = convert_array_to_object($v);
}
$obj->{strtolower($k)} = $v;
}
return $obj;
}
И помните, что если в массиве были цифровые ключи, на них все равно можно ссылаться в результирующем объекте с помощью {}
(например: $obj->prop->{4}->prop
)
Вдохновленный всеми этими кодами, я попытался создать расширенную версию с поддержкой: определенного имени класса, метода конструктора, шаблона "бобов" и строгого режима (установите только существующие свойства):
class Util {
static function arrayToObject($array, $class = 'stdClass', $strict = false) {
if (!is_array($array)) {
return $array;
}
//create an instance of an class without calling class's constructor
$object = unserialize(
sprintf(
'O:%d:"%s":0:{}', strlen($class), $class
)
);
if (is_array($array) && count($array) > 0) {
foreach ($array as $name => $value) {
$name = strtolower(trim($name));
if (!empty($name)) {
if(method_exists($object, 'set'.$name)){
$object->{'set'.$name}(Util::arrayToObject($value));
}else{
if(($strict)){
if(property_exists($class, $name)){
$object->$name = Util::arrayToObject($value);
}
}else{
$object->$name = Util::arrayToObject($value);
}
}
}
}
return $object;
} else {
return FALSE;
}
}
}
Код
Эта функция работает так же, как json_decode(json_encode($arr), false)
.
function arrayToObject(array $arr)
{
$flat = array_keys($arr) === range(0, count($arr) - 1);
$out = $flat ? [] : new \stdClass();
foreach ($arr as $key => $value) {
$temp = is_array($value) ? $this->arrayToObject($value) : $value;
if ($flat) {
$out[] = $temp;
} else {
$out->{$key} = $temp;
}
}
return $out;
}
Тестирование
Тест 1: Плоский массив
$arr = ["a", "b", "c"];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));
Вывод:
array(
0 => 'a',
1 => 'b',
2 => 'c',
)
array(
0 => 'a',
1 => 'b',
2 => 'c',
)
Тест 2: Массив объектов
$arr = [["a" => 1], ["a" => 1], ["a" => 1]];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));
Вывод:
array(
0 => stdClass::__set_state(array('a' => 1,)),
1 => stdClass::__set_state(array('a' => 1,)),
2 => stdClass::__set_state(array('a' => 1,)),
)
array(
0 => stdClass::__set_state(array('a' => 1,)),
1 => stdClass::__set_state(array('a' => 1,)),
2 => stdClass::__set_state(array('a' => 1,)),
)
Тест 3: Объект
$arr = ["a" => 1];
var_export(json_decode($arr));
var_export($this->arrayToObject($arr));
Вывод:
stdClass::__set_state(array('a' => 1,))
stdClass::__set_state(array('a' => 1,))
CakePHP имеет рекурсивный класс Set::map, который в основном отображает массив в объект. Возможно, вам потребуется изменить внешний вид массива, чтобы объект выглядел так, как вы хотите.
Http://api.cakephp.org/view_source/set/#line-158
В худшем случае вы можете получить несколько идей от этой функции.
Я сделал это довольно простым способом,
$list_years = array();
$object = new stdClass();
$object->year_id = 1 ;
$object->year_name = 2001 ;
$list_years[] = $object;
function object_to_array($data)
{
if (is_array($data) || is_object($data))
{
$result = array();
foreach ($data as $key => $value)
{
$result[$key] = object_to_array($value);
}
return $result;
}
return $data;
}
function array_to_object($data)
{
if (is_array($data) || is_object($data))
{
$result= new stdClass();
foreach ($data as $key => $value)
{
$result->$key = array_to_object($value);
}
return $result;
}
return $data;
}
Используя (массив) и (объект) в качестве префикса, вы можете просто преобразовать массив объектов в стандартный массив и наоборот
<?php
//defining an array
$a = array('a'=>'1','b'=>'2','c'=>'3','d'=>'4');
//defining an object array
$obj = new stdClass();
$obj->a = '1';
$obj->b = '2';
$obj->c = '3';
$obj->d = '4';
print_r($a);echo '<br>';
print_r($obj);echo '<br>';
//converting object array to array
$b = (array) $obj;
print_r($b);echo '<br>';
//converting array to object
$c = (object) $a;
print_r($c);echo '<br>';
?>
Я использую следующее для анализа ассоциативных массивов файлов Yaml в состояние объекта.
Это проверяет все предоставленные массивы, если там скрываются объекты, и превращает их также в объекты.
/**
* Makes a config object from an array, making the first level keys properties a new object.
* Property values are converted to camelCase and are not set if one already exists.
* @param array $configArray Config array.
* @param boolean $strict To return an empty object if $configArray is not an array
* @return stdObject The config object
*/
public function makeConfigFromArray($configArray = [],$strict = true)
{
$object = new stdClass();
if (!is_array($configArray)) {
if(!$strict && !is_null($configArray)) {
return $configArray;
}
return $object;
}
foreach ($configArray as $name => $value) {
$_name = camel_case($name);
if(is_array($value)) {
$makeobject = true;
foreach($value as $key => $val) {
if(is_numeric(substr($key,0,1))) {
$makeobject = false;
}
if(is_array($val)) {
$value[$key] = $this->makeConfigFromArray($val,false);
}
}
if($makeobject) {
$object->{$name} = $object->{$_name} = $this->makeConfigFromArray($value,false);
}
else {
$object->{$name} = $object->{$_name} = $value;
}
}
else {
$object->{$name} = $object->{$_name} = $value;
}
}
return $object;
}
Это превращает yaml, настроенный как
fields:
abc:
type: formfield
something:
- a
- b
- c
- d:
foo:
bar
В массив, состоящий из:
array:1 [
"fields" => array:1 [
"abc" => array:2 [
"type" => "formfield"
"something" => array:4 [
0 => "a"
1 => "b"
2 => "c"
3 => array:1 [
"d" => array:1 [
"foo" => "bar"
]
]
]
]
]
]
К объекту:
{#325
+"fields": {#326
+"abc": {#324
+"type": "formfield"
+"something": array:4 [
0 => "a"
1 => "b"
2 => "c"
3 => {#328
+"d": {#327
+"foo": "bar"
}
}
]
}
}
}