Литерал объекта PHP

В PHP я могу довольно легко указать литералы массива:

array(
    array("name" => "John", "hobby" => "hiking"),
    array("name" => "Jane", "hobby" => "dancing"),
    ...
)

Но что, если мне нужен массив объектов? Как я могу указать литерал объекта в PHP? т.е. в javascript это будет:

[
    {name: "John", hobby: "hiking"},
    {name: "Jane", hobby: "dancing"}
]

person Tomas    schedule 10.03.2012    source источник
comment
В PHP нет объектного литерала.   -  person BoltClock    schedule 10.03.2012
comment
@ŠimeVidas, я не понимаю твоего комментария. Объекты JS — это ассоциативные массивы, но ассоциативные массивы PHP не являются объектами. Также PHP не является языком ECMAScript, и PHP даже не является JS.   -  person Dima Zorin    schedule 24.12.2012
comment
@DmitryZorin Понятно. Я думал, что ассоциативные массивы PHP являются объектами (как в JavaScript).   -  person Šime Vidas    schedule 24.12.2012
comment
@ŠimeVidas Я понимаю, что вы говорите, но вы должны понимать, как интерпретируются два разных языка, что очень отличается.   -  person GriffLab    schedule 27.07.2013
comment
@ŠimeVidas Я думаю, что TMS показывала, как это сделать в JavaScript, в качестве иллюстрации. Итак, вопрос в том, как мне сделать то же самое в PHP?   -  person Stewart    schedule 27.08.2016
comment
Возможный дубликат Есть ли в PHP краткий синтаксис для объектов?   -  person faintsignal    schedule 22.11.2016


Ответы (10)


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

$testArray = array(
    (object)array("name" => "John", "hobby" => "hiking"),
    (object)array("name" => "Jane", "hobby" => "dancing")
);

echo "Person 1 Name: ".$testArray[0]->name;
echo "Person 2 Hobby: ".$testArray[1]->hobby;
person Tim    schedule 10.03.2012
comment
Обратите внимание, что объекты всегда передаются по ссылке, а массивы — нет. Таким образом, изменение атрибута объекта изменяет его везде, где объект был назначен. Это не относится к массивам; они остаются независимыми. - person Gregory Cosmo Haun; 19.03.2014
comment
@GregoryCosmoHaun Объекты не передаются по ссылке. Им передается числовое значение, называемое идентификатором объекта. Что позволяет средствам доступа к объектам находить фактический объект. - person Rain; 14.11.2020
comment
@Дождь В чем разница? Идентификатор объекта, который ссылается на конкретный объект, является ссылкой на объект, не так ли? - person Stack Underflow; 06.01.2021
comment
@Stack-Underflow Вы можете увидеть, чем отличаются эти методы, здесь 3v4l.org/hkOcA - person Rain; 06.01.2021
comment
@Rain Отличное понимание, спасибо. - person Stack Underflow; 06.01.2021

Начиная с PHP 5.4 вы также можете использовать синтаксис короткого массива:

$json = [
    (object) ['name' => 'John', 'hobby' => 'hiking'],
    (object) ['name' => 'Jane', 'hobby' => 'dancing'],
];
person mipaaa    schedule 27.02.2013
comment
отлично, это делает скрипты намного чище - person David V; 20.09.2014

Как отмечали другие, в PHP нет объектного литерала, но вы можете "подделать" его, приведя массив к объекту.

В PHP 5.4 это еще более лаконично, потому что массивы могут быть объявлены в квадратных скобках< /а>. Например:

$obj = (object)[
    "foo" => "bar",
    "bar" => "foo",
];

Это даст вам объект со свойствами "foo" и "bar". Однако я не думаю, что это действительно дает большое преимущество по сравнению с использованием ассоциативных массивов. Это просто разница в синтаксисе.

Подумайте о том, чтобы принять уникальность и «изюминку» всех языков, которые вы используете. В JavaScript объектные литералы повсюду. В PHP ассоциативные массивы функционально аналогичны литералам объектов JavaScript, их легко создавать, и они хорошо понятны другим PHP-программистам. Я думаю, что вам лучше принять этот «аромат», чем пытаться сделать его похожим на синтаксис объектного литерала JavaScript.

person Josh    schedule 14.08.2013

Другой способ — использовать __set_state()магический метод:

$object = stdClass::__set_state (array (
    'height'   => -10924,
    'color'    => 'purple',
    'happy'    => false,
    'video-yt' => 'AgcnU74Ld8Q'
));

Еще немного о методе __set_state(), откуда он взялся и как его предполагается использовать.

person Septagram    schedule 21.02.2013
comment
-1, Было бы круто, если бы работало. Однако у stdClass нет определенного метода __set_state. - person Shad; 19.03.2013

Хотя приведение в качестве (объекта) прекрасно работает на одном иерархическом уровне, оно не углубляется. Другими словами, если нам нужны объекты на каждом уровне, нам нужно сделать что-то вроде:

$foods = (object)[
  "fruits" => (object)["apple" => 1, "banana" => 2, "cherry" => 3],
  "vegetables" => (object)["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
];

Однако вместо многократного приведения в качестве объектов мы можем обернуть все это в json_encode и json_decode следующим образом:

$foods = json_decode(json_encode([
  "fruits" => ["apple" => 1, "banana" => 2, "cherry" => 3],
  "vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6]
]));

Это гарантирует, что это объект на самом глубоком уровне.

Чтобы ответить на klewis, вы можете получить доступ к этому, например:

echo $foods->vegetables->broccoli;

В этом примере выводится число 5.

person Dave Lampert    schedule 08.06.2016
comment
Хорошие решения, можете ли вы привести простой пример со вторым вариантом ссылки на значение брокколи в операторе эха? - person klewis; 29.01.2020
comment
<?php $foods = json_decode(json_encode([ "fruits" => ["apple" => 1, "banana" => 2, "cherry" => 3], "vegetables" => ["asparagus" => 4, "broccoli" => 5, "carrot" => 6] ])); echo $foods->vegetables->broccoli; ?> должен вывести число 5 - person Dave Lampert; 30.01.2020
comment
безусловно, лучший ответ в этой теме, хотя он исходит из фона javascript и хочет либо одноуровневого, либо глубокого уровня. - person klewis; 30.01.2020

Мой способ объектных литералов в стиле JavaScript в PHP выглядит следующим образом:

Сначала я создаю ассоциативный массив следующим образом:

$test = array(
  'name' => "test",
  'exists' => true
);

Затем я легко делаю это таким объектом:

$test = (object)$test;

Теперь вы можете протестировать его:

echo gettype($test); // "object"
echo $test->name; // "test"
person Reza Baradaran Gazorisangi    schedule 18.07.2015

В PHP вы должны создать экземпляр, прежде чем сможете использовать класс. Конечно, вы можете поместить экземпляры в массив позже.

person pgampe    schedule 10.03.2012

Если вы хотите определить модули в литеральном шаблоне объекта «как в JavaScript», вы можете сделать что-то вроде этого:

$object = (object) [
    'config' => (object) [
        'username' => 'Rob Bennet',
        'email' => '[email protected]'
    ],

    'hello' => function() use(&$object) {
        return "Hello " . $object->config->username . ". ";
    },

    'emailDisplay' => function() use(&$object) {
        return "Your email address is " . $object->config->email;
    },

    'init' => function($options) use(&$object) {
        $object->config = $options;
        $doUsername = $object->hello;
        $doEmail = $object->emailDisplay;
        return $doUsername() . $doEmail();
    }
];

$sayMyInfo = $object->init;

echo $sayMyInfo((object) [
    'username' => 'Logan',
        'email' => '[email protected]'
]);

В этом типе модульного сценария я обычно выбираю шаблон фасада, мне просто нравится писать свои вызовы таким образом:

Module::action()->item;

or

Post::get()->title;

Ни один из этих шаблонов не упрощает (а иногда даже делает возможным) тестирование. Но это всего лишь доказательство концепции. Технически «нет» в PHP нет литерала объекта, но если вы привыкли к синтаксису JavaScript (а я больше, чем PHP), вы можете подделать его и сделать это. Как видите, в PHP все намного сложнее, чем в JavaScript.

person Rob Bennet    schedule 01.06.2013

Если json_decode(json_encode( $array )) вам не подходит, вы можете использовать некоторые подобные функции, подобные этим. Какой из них быстрее, я не знаю.

function deep_cast_object( $o ){
  return deep_cast_object_ref( $o );
}

function deep_cast_object_ref( & $o ){

  if( is_array( $o ))
    $o = (object)$o;

  if( is_object( $o ))
    foreach( $o as & $v )
      deep_cast_object_ref( $v );

  return $o;
}

$obj = deep_cast_object(array(
  'Fractal' => array(
    'of'    => array(
      'bad' => 'design',
    ),
  ),
));

var_dump( $obj );
person biziclop    schedule 10.07.2018

Простое решение

$obj = json_decode('{"ape":"kwyjibo"}');
echo $obj->ape;

[output:]
kwyjibo

Затем вы можете обернуть его в функцию и вернуть свой литеральный объект

$obj = literal_object(['key1','val1','key2','val2']);
person vincent thorpe    schedule 09.06.2021