views:

656

answers:

5

Just a short question :)

I have this code. I wonder if it is possible for a User object constructor to somehow fail so that $this->LoggedUser is assigned a NULL value - object is freed after constructor returns.

$this->LoggedUser = NULL;
if ($_SESSION['verbiste_user'] != false)
  $this->LoggedUser = new User($_SESSION['verbiste_user']);    

Thanks in advance!

+3  A: 

AFAIK this can't be done, new will always return an instance of the object.

What I usually do to work around this is:

  • Adding a ->valid boolean flag to the object that determines whether an object was successfully loaded or not. The constructor will then set the flag

  • Creating a wrapper function that executes the new command, returns the new object on success, or on failure destroys it and returns false

-

function get_car($model)
      {
        $car = new Car($model);
        if ($car->valid === true) return $car; else return false;
     } 

I'd be interested to hear about alternative approaches, but I don't know any.

Pekka
Thanks for clarifying.So basically I could justwrap the new command in try...catch and then raise an exception in a constructor?
Tibor
Good question! I think you *can*, but it doesn't really sound right to me. If I create an object car with model "Ford" it could simply be that no car of that model is in the database. That is not really what *exceptions* were designed for. It's more of an expected condition. I'd be interested to see what other answers come up, what is seen as the "right" way to handle this.
Pekka
+2  A: 

When a constructor fails for some unknown reason, it won't return a NULL value or FALSE but it throws an exception. As with everything with PHP5. If you don't handle the exception then the script will stop executing with an Uncaught Exception error.

TheGrandWazoo
When does a constructor throw an exception? When it returns false? Or do you mean, a constructor should throw an exception if a certain condition could not be met`?
Pekka
+2  A: 

Consider it this way. When you use new, you get a new object. Period. What you're doing is you have a function that searches for an existing user, and returns it when found. The best thing to express this is probably a static class function such as User::findUser(). This is also extensible to when you're deriving your classes from a base class.

Wim
That sounds the most logical, yes. I've only just begun OO programming in PHP so I'm not completely sure how to handle things in a 'proper' way.
Tibor
+1  A: 

maybe something like this:

class CantCreateExeption extend Exception{
}

class SomeClass{
    public function __construct(){
       if(something){
          throw(new CantCreateExeption());
       }
    }
}

try{
  $obj = new SomeClass();
}
catch(CantCreateExeption e){
   $obj = null;
}
if($obj===null) echo "couldn create object";
//jaz303 stole my idea an wrap it into a static method
useless
+5  A: 

Assuming you're using PHP 5, you can throw an exception in the constructor:

class NotFoundException extends Exception {}

class User {
    public function __construct($id) {
        if (!$this->loadById($id)) {
             throw new NotFoundException();
        }
    }
}

$this->LoggedUser = NULL;
if ($_SESSION['verbiste_user'] != false) {
    try {
        $this->LoggedUser = new User($_SESSION['verbiste_user']);
    } catch (NotFoundException $e) {}
}

For clarity, you could wrap this in a static factory method:

class User {
    public static function load($id) {
        try {
            return new User($id);
        } catch (NotFoundException $unfe) {
            return null;
        }
    }
    // class body here...
}

$this->LoggedUser = NULL;
if ($_SESSION['verbiste_user'] != false)
    $this->LoggedUser = User::load($_SESSION['verbiste_user']);

As an aside, some versions of PHP 4 allowed you to set $this to NULL inside the constructor but I don't think was ever officially sanctioned and the 'feature' was eventually removed.

jaz303
+1 IMO, this is the correct OO way of indicating failure to construct an object.
Jon Benedicto
It depends on the nature of the failure. If it was an exception, yes. If a parameter to the constructor did not meet a criterion, in my mind no.
Pekka