Когда я должен использовать stdClass и когда я должен использовать массив в PHP-коде? - PullRequest
68 голосов
/ 07 июля 2010

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

Существуют ли ситуации, когда лучше использовать одно вместо другого ??

Какие преимущества я получу, используя stdClass вместо массивов ??


Кто-то скажет, что функции должны быть настолько малы и конкретны, чтобы иметь возможность возвращать одно-единственное значение. Мое решение использовать stdClass является временным, так как я надеюсь найти подходящие объекты значения для каждого процесса в долгосрочной перспективе.

Ответы [ 7 ]

59 голосов
/ 07 июля 2010

Обычный подход

  • Использовать объекты при возврате определенной структуры данных с фиксированными ветвями:

     $person
       -> name = "John"
       -> surname = "Miller"
       -> address = "123 Fake St"
    
  • Использовать массивы при возврате списка:

      "John Miller"
      "Peter Miller"
      "Josh Swanson"
      "Harry Miller"
    
  • Использовать массив объектов при возврате списка структурированной информации:

      $person[0]
        -> name = "John"
        -> surname = "Miller"
        -> address = "123 Fake St"
    
      $person[1]
        -> name = "Peter"
        -> surname = "Miller"
        -> address = "345 High St"
    

Объекты не подходят для хранения списков данных, потому что вам всегда нужен ключ для их адресации. Массивы могут выполнять как функции - хранить произвольные списки, так и структуру данных.

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

@ Deceze делает несколько хороших замечаний о том, когда использовать объект (проверка, проверка типов и будущие методы).

41 голосов
/ 07 июля 2010

Использование stdClass для выполнения той же функции, что и для массива, не очень полезно, IMHO, оно просто добавляет издержки объекта без какой-либо реальной выгоды.Вам также не хватает многих полезных функций массива (например, array_intersect).Вы должны по крайней мере создать свой собственный класс для включения проверки типов или добавить методы к объекту, чтобы оправдать использование объекта.

18 голосов
/ 10 июля 2010

Я не думаю, что есть разумное преимущество использования stdClass над массивом, если ваше единственное намерение - вернуть несколько произвольных типов данных из вызова функции .

Поскольку технически вы не можете вернуть несколько значений изначально, вы должны использовать контейнер, который может содержать все другие типы данных, доступные в PHP. Это будет либо объект, либо массив.

function fn1() { return array(1,2); }
function fn2() { return array('one' => 1, 'two' => 2); }
function fn3() { return (object) array(1,2); }
function fn4() { return (object) array('one' => 1, 'two' => 2); }

Все вышеперечисленное будет работать. Массив - это ничтожно малая доля быстрее и требует меньше работы для ввода. Он также имеет четко определенную цель в отличие от универсального stdClass (который не очень удобен, не так ли). Оба имеют только неявный интерфейс, поэтому вам нужно посмотреть на документы или тело функции, чтобы узнать, что они будут содержать.

Если вы хотите использовать объекты любой ценой, вы можете использовать ArrayObject или SplFixedArray , но если вы посмотрите на их API, вы бы сказали, что вам нужны их функциональные возможности для простой задачи вернуть случайные множественные значения? Я так не думаю. Не поймите меня неправильно: если вы хотите использовать stdClass, используйте его. Это не так, как будто бы что-нибудь сломалось. Но вы тоже ничего не получите. Чтобы добавить хоть какое-то преимущество, вы можете создать для этого отдельный класс с именем ReturnValues.

Может быть простой класс тегирования

class ReturnValues {}

или что-то более функциональное

class ReturnValues implements Countable
{
    protected $values;
    public function __construct() { $this->values = func_get_args(); }
    public function __get($key) return $this->values[$key]; }
    public function count() { return count($this->values); }
}

Конечно, это не так уж и много, и получение значений из него по-прежнему осуществляется через интерфейс Implict, но, по крайней мере, теперь класс имеет более четко определенную ответственность. Вы можете расширить этот класс для создания объектов ReturnValue для определенных операций и дать им явный интерфейс:

class FooReturnValues extends ReturnValues
{
    public function getFoo() { return $this->values['foo']; }
    public function getBar() { return $this->values['foo']; }
}

Теперь разработчику просто нужно взглянуть на API, чтобы узнать, какие множественные значения вернет foo (). Конечно, необходимость писать конкретные классы ReturnValue для каждой операции, которая может возвращать несколько значений, может быстро стать утомительной. И лично я нахожу это слишком сильным для первоначальной цели.

Во всяком случае, надеюсь, что это имеет какой-то смысл.

4 голосов
/ 07 июля 2010

Ну, есть 3 различия:

  • у них есть личность. вот почему по умолчанию для передачи аргументов массива используется вызов по значению , а для объектов вызов по совместному использованию .
  • есть семантическая разница. Если вы используете объект, любой, кто читает код, поймет, что значение представляет модель своего рода права, в то время как массив должен действовать как коллекция или карта
  • И, наконец, что не менее важно, рефакторинг становится значительно проще. Если вы хотите использовать конкретный класс, а не stdClass, все, что вам нужно сделать, это создать экземпляр другого класса. Который также позволяет добавлять методы.

Greetz
back2dos

2 голосов
/ 24 апреля 2014

Единственный ЦЕЛЕВОЙ вотум доверия, который я могу найти:

json_decode по умолчанию использует stdClass, поэтому нам, смертным в пользовательском пространстве, следует использовать stdClass для подобных ситуаций.

1 голос
/ 10 августа 2014

В тестах массив vs stdclass они обрабатывают динамические свойства php медленнее, чем ассоциативные массивы.Я не говорю это, чтобы спорить о микрооптимизации, но если вы собираетесь это сделать, вам лучше определить класс данных без методов и установить публичные свойства.Esp если вы используете php 5.4+.Под капотом определенные свойства отображаются непосредственно в массив ac без хеш-таблицы, где в качестве динамических необходимо использовать хеш-таблицу.

Это дает дополнительный бонус, заключающийся в последующем превращении в полный класс без какой-либо существенной переделки интерфейса.

1 голос
/ 15 сентября 2012

Я считаю, что объекты stdClass над массивами полезны, когда мне нужно, чтобы мой код был чистым и читабельным.Возьмем, к примеру, функцию getProperties(), которая возвращает набор свойств, например, данные о человеке (имя, возраст, пол).Если getProperties() вернет ассоциативный массив, когда вы захотите использовать одно из возвращаемых свойств, вы бы написали две инструкции:

$data = getProperties();
echo $data['name'];

С другой стороны, если getProperties() возвращает stdClass, тогда вымог написать это всего за одну инструкцию:

echo getProperties()->name;
...