web-dev-qa-db-fra.com

PHP constructeur pour retourner un NULL

J'ai ce code. Est-il possible qu'un constructeur d'objet User échoue d'une manière ou d'une autre afin que $this->LoggedUser reçoit une valeur NULL et l'objet est libéré après le retour du constructeur?

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

En supposant que vous utilisez PHP 5, vous pouvez lever une exception dans le constructeur:

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

Pour plus de clarté, vous pouvez envelopper cela dans une méthode d'usine statique:

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']);

En passant, certaines versions de PHP 4 vous ont permis de mettre $ this à NULL dans le constructeur mais je ne pense pas que cela ait jamais été officiellement sanctionné et la 'fonctionnalité' a finalement été supprimée.

65
jaz303

AFAIK cela ne peut pas être fait, new retournera toujours une instance de l'objet.

Ce que je fais habituellement pour contourner ce problème est:

  • Ajout d'un ->valid indicateur booléen à l'objet qui détermine si un objet a été chargé avec succès ou non. Le constructeur mettra alors le drapeau

  • La création d'une fonction wrapper qui exécute la commande new, retourne le nouvel objet en cas de succès ou en cas d'échec le détruit et retourne false

-

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

Je serais intéressé d'entendre parler d'autres approches, mais je n'en connais aucune.

12
Pekka 웃

Considérez-le de cette façon. Lorsque vous utilisez new, vous obtenez un nouvel objet. Période. Ce que vous faites, c'est que vous disposez d'une fonction qui recherche un utilisateur existant et la renvoie lorsqu'elle est trouvée. La meilleure chose à exprimer est probablement une fonction de classe statique telle que User :: findUser (). Ceci est également extensible lorsque vous dérivez vos classes d'une classe de base.

5
Wim

Une usine pourrait être utile ici:

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

Lorsqu'un constructeur échoue pour une raison inconnue, il ne renvoie pas de valeur NULL ou FALSE mais il lève une exception. Comme avec tout avec PHP5. Si vous ne gérez pas l'exception, le script cessera de s'exécuter avec une erreur d'exception non capturée.

4
TheGrandWazoo

peut-être quelque chose comme ça:

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
3
useless