1

Consider the following, simple class constructor. (note that I am obviously not including all methods that are referenced.

// Initialize User class.
public function __construct($user_id = NULL)
{
    // If user is loaded (and a user ID is provided)
    if ($user_id)
    {
        // If user is authorized.
        if ($this->authorized($user_id))
        {
            // Load user information.
            $this->info = $this->load($user_id);
        }
        else
        {
            // Return an empty (nonexistent) user.
            return NULL;
        }
    }

    // If user is loaded (and no user ID is provided)
    else
    {
        // Create a new user.
        $new_user = create_user();

        // Return the new user's ID.
        return $new_user;
    }
}

My question is this: is my method of returning values here wrong? My friend insists that a constructor should ALWAYS return an object NO MATTER WHAT. However, the way I have it laid out here seems much simpler, and is much easier to work with. (If I am making a new user, then I get his ID right off the bat. If I am loading an existing user, I immediately have access to her/his information)

If it IS wrong, why? Why is this bad?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Nathanael
  • 6,893
  • 5
  • 33
  • 54

3 Answers3

8

What you're trying to do simply doesn't work, the constructor will return the new instance of User anyway, even when you try to return null.

For example, this:

class User {
  function __construct() {
    return null;
  }
}
var_dump(new User());

will print:

object(User)#1 (0) {
}

http://codepad.org/0IdJydkY

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • The object is already created at this point, and `__construct()` is intended ONLY to modify the object's properties on creation. When called on `new`, the return value of this constructor is simply ignored. You can however do `$obj->__construct($user_id)` which will return `$new_user` value in OP's case. But attempting `$obj->__construct($user_id)` is just bad though. Very, very bad. Never call a constructor method directly. – bob-the-destroyer May 12 '12 at 22:11
  • @bob-the-destroyer I never thought of using `$obj->__construct($user_id)` directly. Very, very bad indeed! For starters, if one calls that, `__construct` will be running for a second time (since it already ran once on `new ClassName()`). – bfavaretto May 12 '12 at 22:15
  • Right. Although you can typically call PHP "magic methods" from outside a class, it's neither commonly used nor productive. Even worse than an "anti-pattern". In OP's case, this is very much "wrong". A better fix for OP is to call a handler/wrapper function which either returns an object or null. – bob-the-destroyer May 12 '12 at 22:27
2

You could add a static method to your class to create the user or to return null

public static function createUser() {
    // do your checks
    // if valid return instance
    // return null;
}

$user = User::createUser();

Note: You may have to make your authorized() method static - depends on the rest of your class.

tigrang
  • 6,767
  • 1
  • 20
  • 22
0

Your __construct() function shouldn't return any value at all, it always automatically returns the object - it should be used to initiate certain things.

I would recommend putting the code in a different function.

More on this can be read here: Echo Return construct method;

Community
  • 1
  • 1
Jeroen
  • 13,056
  • 4
  • 42
  • 63