When should I use stdClass and when should I use an array in php oo code?
Asked Answered
A

7

73

In the middle of a period of big refactoring at work, I wish to introduce stdClass ***** as a way to return data from functions and I'm trying to find non-subjective arguments to support my decision.

Are there any situations when would it be best to use one instead of the other ??

What benefits would I get to use stdClass instead of arrays ??


Some would say that functions have to be as little and specific to be able to return one single value. My decision to use stdClass is temporal, as I hope to find the right Value Objects for each process on the long run.

Alcaide answered 7/7, 2010 at 10:8 Comment(5)
see : #2057431 It does not answer my question. He says that a "real" class would be the best approach, which (I think) we all agree. I would still like to know "when" the use of stdClass returns values is better than arrays.Alcaide
you might want to clearify your concept of Value Objects. In DDD a Value Object is immutable and the purpose is quite different from VOs in Java.Mundford
@Mundford What I meant was, a "VO-like" return guideline from functions. Having a VO as a (preferably) small object, where only his attributs are important, not his identity. About your links, were you trying to find out if for me (my question) the discussion about "VO should be immutable Vs VO can be mutable" was important ? Btw, nowadays VO's are TO (Transfer Objects) for sun. java.sun.com/blueprints/corej2eepatterns/Patterns/…Alcaide
what I am not sure about yet is whether you simply want to solve the problem that PHP does not support multiple return values or something else. And yes, is mutability important? Maybe you are looking for Tuples (like in Python)?Mundford
@Mundford Thank you for your interest. As you just said, I guess my question is mainly focused on finding a 'good' way (in OOP) to pass multiple values as a return of a function call. Do you think I should edit my question or this comments will do the job ?Alcaide
A
63

The usual approach is

  • Use objects when returning a defined data structure with fixed branches:

     $person
       -> name = "John"
       -> surname = "Miller"
       -> address = "123 Fake St"
    
  • Use arrays when returning a list:

      "John Miller"
      "Peter Miller"
      "Josh Swanson"
      "Harry Miller"
    
  • Use an array of objects when returning a list of structured information:

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

Objects are not suitable to hold lists of data, because you always need a key to address them. Arrays can fulfill both functions - hold arbitrary lists, and a data structure.

Therefore, you can use associative arrays over objects for the first and third examples if you want to. I'd say that's really just a question of style and preference.

@Deceze makes a number of good points on when to use an object (Validation, type checking and future methods).

Animation answered 7/7, 2010 at 10:12 Comment(6)
I really like/agree on arguments number 1 & 2.Alcaide
I asked for "non-subjectives" arguments. Sadly, none was given. I stick with your answer (following other's votes) as it shows what I'll continue to follow from now on : Arrays are for lists; stdClass for "multi-value"/properties.Alcaide
I strongly disagree with this. If all you have is data, even structured data, then you should be using arrays. An object is a package of data and associated behaviour. Using stdClass as an array is simply abuse of stdClass.Torrey
Agree with GordonM, the illusion of a proper object by using stdClass causes more harm then good. Almost all cases where I see stdClass used it's always abusing dynamic attributes—it's very confusing what structure the class has, and even if that structure is respected since almost every use of it involves filling attributes "on the fly." If you're potentially going to miss out attributes or cant be bothered to create an actual class, might as well use an array.Paries
Not an objective answer.Erst
+1 to @srcspider. Also, all the times I've seen a stdClass a being used by a developer, that developer was using it in the illusion that the code was "object oriented", which was not. In my opinion the only use a stdclass might have would be in a test case. And I don't remember having ever used it this way. I think it should be abolished from the PHP language.Ariew
A
46

Using stdClass to fulfill the same function as an array is not very useful IMHO, it just adds the overhead of an object without any real benefit. You're also missing out on many useful array functions (e.g. array_intersect). You should at least create your own class to enable type checking, or add methods to the object to make it worth using an object.

Alenaalene answered 7/7, 2010 at 10:13 Comment(2)
I specially like/agree on what you say about "adding methods to the object to make it worth using".Alcaide
This answer seems to imply that it is never worth using stdClassIronworker
M
18

I don't think there is any reasonable advantage of using a stdClass over an array as long as your sole intention is to return multiple arbitrary datatypes from a function call.

Since you cannot technically return multiple values natively, you have to use a container that can hold all other datatypes available in PHP. That would be either an object or an array.

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

All of the above would work. The array is a tiny negligible fraction faster and less work to type. It also has a clearly defined purpose in contrast to the generic stdClass (which is a bit wishywashy, isnt it). Both only have an implicit interface, so you will have to look at the docs or the function body to know what they will contain.

If you want to use objects at any cost, you could use ArrayObject or SplFixedArray, but if you look at their APIs would you say you need their functionality for the simple task of returning random multiple values? I don't think so. Don't get me wrong though: if you want to use stdClass, then use it. It's not like it would break anything. But you also would not gain anything. To add at least some benefit, you could create a separate class named ReturnValues for this.

Could be a simple tagging class

class ReturnValues {}

or something more functional

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

Granted, it doesn't do much and getting the values out of it is still done through an implict interface, but at least the class has a more clearly defined responsibility now. You could extend from this class to create ReturnValue objects for particular operations and give those an explicit interface:

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

Now the developer just has to look at the API to know which multiple values foo() will return. Of course, having to write concrete ReturnValue classes for each and every operation that might return multiple values could become tedious quickly. And personally, I find this overengineered for the initial purpose.

Anyway, hope that makes any sense.

Mundford answered 9/7, 2010 at 21:6 Comment(4)
interesting your "ReturnValues" proposal.Alcaide
@Alcaide Thanks. I guess my two main points for it are: making the returned object semantically clearer and making the interface to it explicit. If none of that matters, then it's really no use to go that route imo.Mundford
I like this idea of a class that is generic, but generic within a particular domain / purpose. It has the potential to actually add power, whereas stdClass is little more than an alternative representation of an associative array.Earth
I think the slightly more readable syntax is the primary benefit for most developers. However, using $options = ['a'=>'str', 'b'=>'str']; is almost as elegant and allows for the many native/powerful functions built for arrays. So I'm sticking with arrays unless I need to match a JSON structure.Emissary
S
4

Well, there are 3 differences:

  • they have an identity. which is why the default for passing array arguments is call by value and for objects call by sharing.
  • there is a semantical difference. If you use an object, anyone who reads the code understand, that the value represents the model some sort of entitity, while an array is supposed to act as a collection or a map
  • And last but not least, refactoring becomes signifficantly easier. If you want to use a concrete class rather than stdClass, all you have to do is to instantiate another class. Which also allows you to add methods.

greetz
back2dos

Sessile answered 7/7, 2010 at 13:4 Comment(0)
E
2

The only OBJECTIVE vote of confidence I can find is:

json_decode uses stdClass by default so us mortals in userland should use stdClass for similar situations.

Erst answered 24/4, 2014 at 16:14 Comment(2)
you can just use json_decode($json, true); if you want to get arrays instead objectsSelfdenial
we mortals in userland do not 'just' override default param values.Inflect
O
1

I find stdClass objects over arrays useful when I need to keep my code clean and somewhat sentence-like readable. Take for example function getProperties() which returns a set of properties, say data about a person (name, age, sex). If getProperties() would return an associative array, when you want to use one of the returned properties, you would write two instructions:

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

On the other hand, if getProperties() returns a stdClass then you could write that in just one instruction:

echo getProperties()->name;
Oviduct answered 15/9, 2012 at 14:51 Comment(3)
Note that this no longer applies if you are using PHP 5.4 or later, as it was just a short-coming of PHP's parser. You can now write echo getProperties()['name']; 3v4l.org/t6i0rEarth
@IMSoP, you can, except a lot of systems still use PHP 5.3, which will throw an error that will baffle some developers :).Harbinger
@Harbinger Yep, hence the "if" in my comment :) Note also that 5.3 is now officially unsupported, so people should be pestering their hosts/admins to upgrade: php.net/eol.phpEarth
A
1

In tests of array vs stdclass they way php handles dynamic properties is slower then associative arrays. I'm not saying this to argue micro optimization but rather if your going to do this your better off defining a dataclass with no methods and set public properties. Esp if you are using php 5.4+. Under the hood defined properties are mapped directly to a c array with no hashtable where as dynamic ones need to use a hash table.

This has the added bonus of later becoming a full class without any major interface reworking.

Archon answered 10/8, 2014 at 19:17 Comment(1)
The performance characteristics of PHP change with every version.Erst

© 2022 - 2024 — McMap. All rights reserved.