2010-02-06 2 views
47

Ich habe diesen Code. Ist es möglich, dass ein User Objektkonstruktor irgendwie fehlschlägt, so dass $this->LoggedUser einen NULL Wert zugewiesen wird und das Objekt nach dem Zurückgeben des Konstruktors freigegeben wird?PHP-Konstruktor zum Zurückgeben einer Null

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

Große erste Frage des Art und Weise. –

+0

Ich habe einen bestimmten populären CMS gesehen, der FALSE in einem Konstruktor zurückgibt. Was ist damit?!?! – loungerdork

+1

Ich dachte nur, ich würde hier aus Gründen der Dokumentation reinhören. Da das Datum so weit zurück ist, ist es möglich, dass das CMS, das Sie sehen, für PHP4 gebaut wurde. PHP4 ermöglichte eine Menge schlechter Dinge, von denen nicht zuletzt der Benutzer es erlaubte, $ this im benannten Konstruktor zu überschreiben (zum Beispiel $ this = false). – techdude

Antwort

62

Angenommen, Sie sind mit PHP 5, können Sie eine Ausnahme im Konstruktor werfen:

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

Aus Gründen der Klarheit Sie diese in einem statischen wickeln könnte Factory-Methode:

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

Als beiseite, einige Versionen von PHP 4 erlaubt Ihnen $ dieses zu NUL setzen L innerhalb des Konstruktors, aber ich glaube nicht, dass jemals offiziell sanktioniert wurde und das "Feature" schließlich entfernt wurde.

+4

+1 IMO, dies ist die korrekte OO-Methode zur Anzeige von Fehlern beim Erstellen eines Objekts. –

+1

Es hängt von der Art des Fehlers ab. Wenn es eine Ausnahme war, ja. Wenn ein Parameter für den Konstruktor ein Kriterium nicht erfüllt, denke ich nicht. –

+5

Pekka, ich bin mir nicht sicher, welche Art von "schlechten Parametern" wäre keine Ausnahme? Wenn Sie ein gültiges Objekt mit einer bestimmten Menge von Parametern sicher nicht erstellen können, ist das eine Ausnahme und sollte eine Ausnahme auslösen? Können Sie ein Beispiel geben, um den Unterschied zu verdeutlichen, an den Sie denken? (Ich sehe, Sie tun in der Antwort unten, das wäre hier oben nützlich, aber ich kann Ihren Kommentar nicht bearbeiten!) –

11

AFAIK kann dies nicht geschehen, new wird immer eine Instanz des Objekts zurück.

Was ich in der Regel tun, dies zu umgehen ist:

  • einen ->valid boolean-Flag zu dem Objekt hinzufügen, die ein Objekt bestimmt, ob erfolgreich geladen wurde oder nicht. Der Konstruktor setzt dann das Flag

  • eine Wrapper-Funktion erstellen, die den new Befehl ausführt, gibt das neue Objekt auf Erfolg, oder bei Ausfall zerstört und gibt false

-

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

Ich würde gerne über alternative Ansätze hören, aber ich kenne keine.

+0

Danke für die Klärung. Also im Grunde könnte ich einfach den neuen Befehl in Versuch ...fangen und dann eine Ausnahme in einem Konstruktor auslösen? – Tibor

+1

Gute Frage! Ich denke du * kannst *, aber es klingt nicht richtig für mich. Wenn ich ein Objektauto mit Modell "Ford" erstelle, könnte es einfach sein, dass kein Auto dieses Modells in der Datenbank ist. Das ist nicht wirklich das, wofür * Ausnahmen * entworfen wurden. Es ist eher eine zu erwartende Bedingung. Es würde mich interessieren zu sehen, welche anderen Antworten aufkommen, was als der "richtige" Weg angesehen wird, damit umzugehen. –

+0

Das macht etwas auf die schmutzige Art, check @ jaz303's Antwort – minhajul

3

Wenn ein Konstruktor aus einem unbekannten Grund fehlschlägt, gibt es keinen NULL-Wert oder FALSE zurück, aber es löst eine Ausnahme aus. Wie bei allem mit PHP5. Wenn Sie die Ausnahme nicht behandeln, wird das Skript nicht mehr mit einem Uncaught Exception-Fehler ausgeführt.

+1

Wann wirft ein Konstruktor eine Ausnahme? Wenn es falsch zurückgibt? Oder meinst du, ein Konstruktor sollte eine Ausnahme auslösen, wenn eine bestimmte Bedingung nicht erfüllt werden kann? –

+1

Ihr Konstruktor sollte die Ausnahme auslösen. – Tom

5

Betrachten Sie es so. Wenn Sie new verwenden, erhalten Sie ein neues Objekt. Zeitraum. Sie haben eine Funktion, die nach einem vorhandenen Benutzer sucht und ihn zurückgibt, wenn er gefunden wird. Das Beste, um dies auszudrücken, ist wahrscheinlich eine statische Klassenfunktion wie User :: findUser(). Dies ist auch erweiterbar, wenn Sie Ihre Klassen von einer Basisklasse ableiten.

+0

Das klingt am logischsten, ja. Ich habe gerade erst mit der OO-Programmierung in PHP begonnen, deshalb bin ich mir nicht ganz sicher, wie ich mit den Dingen auf eine "richtige" Weise umgehen soll. – Tibor

3

vielleicht so etwas wie folgt aus:

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 
4

Eine Fabrik könnte hier nützlich sein:

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