PHP constructor to return a NULL

2019-01-08 08:33发布

问题:

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

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

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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.



回答5:

A factory might be useful here:

class UserFactory
{
    static public function create( $id )
    {
        return (
            filter_var( 
                $id,
                FILTER_VALIDATE_INT, 
                [ 'options' => [ 'min_range' => 1, ] ]
            )
                ? new User( $id )
                : null
        );
  }
}


回答6:

maybe something like this:

class CantCreateException extends Exception{
}

class SomeClass {
    public function __construct() {
       if (something_bad_happens) {
          throw ( new CantCreateException());
       }
    }
}

try{
  $obj = new SomeClass();
}
catch(CantCreateException $e){
   $obj = null;
}
if($obj===null) echo "couldn't create object";
//jaz303 stole my idea an wrap it into a static method