MB: Repository Objekte aus DB abspeichern

moin,

wenn ich einen User-Objekt aus der Database über ein UserRepository haben möchte, jedoch findet die Database einfach keinen angeforderten Record, dann wird zwangsläufig ein Fehler auftreten, weil das System keinen TUser fetcht sondern null zurück gibt. Und Ich möchte sehr gern mit Return-Type arbeiten können.

class UserRepository {
  
  public function findByPseudo( string $pseudo ) : TUser {
    $this->_database->fetchAssoc(); // FETCH_CLASS TUser wird noch kommen
    
    $items = $this->_database->get(
      "SELECT * FROM {$this->_table}"
      ." WHERE pseudo = '{$pseudo}';",
      [ $pseudo ]
    );
    
    return new TUser(
      $items[ 'first' ],
      $items[ 'last' ],
      $items[ 'email' ],
      $items[ 'pseudo' ],
      $items[ 'role' ],
      $items[ 'hash' ]
    );
  }
}

$user_repo = new UserRepository;
$user = $user_repo->findByPseudo( 'mb' ); // Error fals nicht existiert

Um dem Problem Herr zu werden könnte ich eine Existenz-Abfrage vorher machen was ich gemacht habe…

class UserRepository {
  
  public function existPseudo( string $pseudo ) : bool {
    $this->_database->fetchAssoc();
    
    return !empty( $this->_database->getAll(
      "SELECT pseudo FROM {$this->_context}"
      ." WHERE pseudo = ?;",
      [ $pseudo ]
    ) );
  }
  
  public function findByPseudo( string $pseudo ) : TUser {
    // ...
  }
}

$user_repo = new UserRepository;
if( $user_repo->existPseudo( 'mb' ) ) {
  $user = $user_repo->findByPseudo( 'mb' );
}

…aber das frisst denke ich mal Systemzeit zweimal eine Verbindung zur Database aufzubauen und Anfragen anzustrengen. Wäre eine Art TUser Property im Repository möglich sodass diese Existns-Abfrage überflüssig wird? wie…

class UserRepository {
  
  private $user = null;
  
  public function findByPseudo( string $pseudo ) : void {
    $this->_database->fetchAssoc(); // FETCH_CLASS TUser wird noch kommen
    
    $items = $this->_database->get(
      "SELECT * FROM {$this->_table}"
      ." WHERE pseudo = '{$pseudo}';",
      [ $pseudo ]
    );
    
    $this->_user = is_null( $items )
      ? new TUser(
        $items[ 'first' ],
        $items[ 'last' ],
        $items[ 'email' ],
        $items[ 'pseudo' ],
        $items[ 'role' ],
        $items[ 'hash' ]
      )
      : null;
  }
}

$user_repo = new UserRepository;
$user = $user_repo->findByPseudo( 'mb' );
if( !is_null( $user ) {
  // Code
}

Bevor ich was wirklich dämliches mache möchte und den ganzen Codew umstruktuieren möchte ich erstmal Fragen.

lgmb

  1. moin,

    wenn ich einen User-Objekt aus der Database über ein UserRepository haben möchte, jedoch findet die Database einfach keinen angeforderten Record, dann wird zwangsläufig ein Fehler auftreten, weil das System keinen TUser fetcht sondern null zurück gibt.

    Es liegt doch an Dir ob das zwangsläufig zu einem Fehler führt oder ob Du dem Anwender schonend beibringst daß es den gesuchten Eintrag nicht gibt.

    .

    1. moin,

      wenn ich einen User-Objekt aus der Database über ein UserRepository haben möchte, jedoch findet die Database einfach keinen angeforderten Record, dann wird zwangsläufig ein Fehler auftreten, weil das System keinen TUser fetcht sondern null zurück gibt.

      Es liegt doch an Dir ob das zwangsläufig zu einem Fehler führt oder ob Du dem Anwender schonend beibringst daß es den gesuchten Eintrag nicht gibt.

      Ich verstehe nicht sry. Wie den wenn nicht so? Was hast du für eine Lösung?

      lgmb

      1. Es liegt doch in Deinem Ermessen! Also, wenn ich eine Person suche und die wird nicht gefunden, sehe ich das nicht als meinen Fehler an. Vielmehr würde ich dann schon wissen wollen warum die Person nicht gefunden wurde.

        .

        1. moin,

          Es liegt doch in Deinem Ermessen! Also, wenn ich eine Person suche und die wird nicht gefunden, sehe ich das nicht als meinen Fehler an. Vielmehr würde ich dann schon wissen wollen warum die Person nicht gefunden wurde.

          Hmm ich vermute das du das abstrakt mit deiner AW siehst. Meine Frage ist programmiertechnisch - fals ich dich richtig verstanden habe versteht sich. Wenn z.B. sich ein "Hans Peter Müller" mit seinem Pseudonym "hpm" einloggt und das System in seiner DB User-Tabelle keinen "hpm" kennt, muss das System diesen Fall behandeln oder nicht. Wenn nicht wird ein Error passieren. Wie gesagt fals ich deinen AW richtig interpretiert habe.

          lgmb

          1. Ja klar, was da unter der Haube läuft ist dem Anwender völlig wurst. Unterm Blech jedoch kannst Du da ziemlich alles machen, egal wie falsch, hauptsache einheitlich!

            Unterscheide programmiertechnisch den Rückgabewert einer Funktion. Sobald ein Solcher undefiniert ist, gab es einen Fehler. Also Fehlerspeicher auslesen.

            Wenn der RV jedoch definiert ist, ist es kein Fehler. Aber er kann auch leer sein.

            MfG

            PS: Perls Exception Modell ist für solche Dinge besonders gut geignet weil es gewisse Freizügigkeiten im Umgang bietet. In PHP ist das eher unschön und macht den CODE nur komplizierter als ihn zu vereinfachen.

            1. moin,

              Unterscheide programmiertechnisch den Rückgabewert einer Funktion. Sobald ein Solcher undefiniert ist, gab es einen Fehler. Also Fehlerspeicher auslesen.

              Wenn der RV jedoch definiert ist, ist es kein Fehler. Aber er kann auch leer sein.

              public function getByPseudo( string $pseudo ) : TUser {}
              

              …ist ja defeniert und es kommt eine Exception wenn null zurück gegeben wird. Wenn der Return-Wert undefiniert wäre, gäbe es keinen TypeError.

              aber ich werd das wohl unhandlich mit existUser( string $pseudo ) vorab anstellen. Später überarbeite ich den wisch und mache das den unhandlichen Code sauberer 😉.

              PS: Perls Exception Modell ist für solche Dinge besonders gut geignet weil es gewisse Freizügigkeiten im Umgang bietet. In PHP ist das eher unschön und macht den CODE nur komplizierter als ihn zu vereinfachen.

              klingt interessant aber wie gesagt ich hab mich vor langem auf PHP eingschossen und möchte weiter mit C# oder Java arbeiten. Auf bald.

              lgmb

              1. Tach!

                public function getByPseudo( string $pseudo ) : TUser {}
                

                …ist ja defeniert und es kommt eine Exception wenn null zurück gegeben wird. Wenn der Return-Wert undefiniert wäre, gäbe es keinen TypeError.

                Diese Exception ist doch keine unumgängliche Gesetzmäßigkeit. So zumindest, habe ich den Eindruck, argumentierst du hier. Es ist die Verantwortung deines Codes, zu prüfen, ob der Rückgabewert null ist, bevor du damit irgendwas anstellst, das ein Objekt diesen Types voraussetzt, damit es eben keine Exception wegen ungültigen Zugriffs gibt. - Wenn die Exception bereits in deiner Funktion geworfen wird, dann musst du eben dort entsprechenden if-else-Code einbauen, damit dort nicht sehenden Auges in ungültige Zugriffe gerannt wird.

                dedlfix.

              2. Hallo MB,

                klingt interessant

                Isses aber nicht (danke Copacabana 😀)

                Es kommt darauf an, technische und fachliche Fehler zu unterscheiden. Ein fachlicher Fehler ist: Den User gibt's nicht. Dann kannst Du null zurückgeben und das als gültige Rückgabe für "not found" betrachten. Eine separate existUser Abfrage ist aus meiner Sicht sinnlos und belästigt nur unnötig die DB.

                Technischer Fehler gibt's reichlich: Die Datenbank ist störrisch (Timeout), das Passwort ist falsch, man hat kein Leserecht auf die User-Table, der DB-Server ist platt - also all das, was keinen sinnvollen Programmbetrieb zulässt. In dem Fall solltest Du eine Exception werfen, sofern mysqli oder PDO das nicht schon tut, und relativ hoch oben in deiner Logik mit try/catch abfangen. Der Exception Handler loggt die Exception und gibt dem User dann bekannt dass es technische Probleme gab. Gibt es im Callstack Stellen, wo Du bei einer Exception aufräumen musst, gehört da ebenfalls ein try-Block hin, ggf. ohne catch, es kann reichen nur ein finally zu verwenden. Wenn Du bei einem zwischengelagerten Exceptionhandler wirklich catch brauchst, muss die Exception normalerweise weitergeworfen werden. Exceptions wegzufangen und gegenüber dem Aufrufer so zu tun als wäre alles gut ist normalerweise falsch - es sei denn, du kannst aus der Exception-Situation heraus das Programm sinnvoll fortsetzen.

                Die grundsätzlichen Erklärungen zum Exception Handling auf php.net finde ich sehr dürftig, wenn Du da Fragen hast, gerne.

                Rolf

                --
                sumpsi - posui - clusi
              3. hi,

                …ist ja defeniert und es kommt eine Exception wenn null zurück gegeben wird. Wenn der Return-Wert undefiniert wäre, gäbe es keinen TypeError.

                Das passt aber nicht wirklich zusammen. Weil null erstens gleichbedeutend mit undefiniert ist und zweitens von daher mitnichten von irgendeines Types sein kann.

                Und drittens ist die Logik eine andere nämlich die, daß null zurückkommt eben weil eine Exception gefallen ist.

                MfG

                1. Tach!

                  …ist ja defeniert und es kommt eine Exception wenn null zurück gegeben wird. Wenn der Return-Wert undefiniert wäre, gäbe es keinen TypeError.

                  Das passt aber nicht wirklich zusammen. Weil null erstens gleichbedeutend mit undefiniert ist und zweitens von daher mitnichten von irgendeines Types sein kann.

                  Er meint, die return type declaration.

                  Und jetzt ist mir auch grad klar geworden, was er da für eine Exception meint. Die kommt nämlich, wenn man dort eine Klasse angibt, aber als Wert null zurückgibt. Anderenorts kann man bei sämtlichen Referenztypen auch null als Wert liefern. Wenn man jedoch bei PHP einen nullable Typen haben möchte, muss man das explizit mit einem Fragezeichen vor dem Typnamen kennzeichnen.

                  Leider steht das noch nicht auf den entsprechenden Seiten der PHP-Dokumentation, nur im Migrationsanhang.

                  dedlfix.

                  1. Hallo dedlfix,

                    ui, danke für diesen Hinweis. Das Problem war mir nicht klar und das Feature nicht bekannt.

                    Rolf

                    --
                    sumpsi - posui - clusi
                  2. Danke Dich!

            2. Hallo pl,

              Perls Exception Modell ist für solche Dinge besonders gut geignet - In PHP ist das eher unschön

              In Perl 5 gibt's ab Werk nur eval, die und $@ - und der Rest ist der Sorgfalt des Programmierers überlassen. error.pm formalisiert das zu einem try/catch/finally Modell mit Exception-Objekten, und das ist sicherlich eine prima Sache, aber ich sehe jetzt nicht, wo PHP ab Version 5 dem nachsteht.

              Rolf

              --
              sumpsi - posui - clusi
              1. @Rolf B

                Perls Exception Modell ist für solche Dinge besonders gut geignet - In PHP ist das eher unschön

                In Perl 5 gibt's ab Werk nur eval, die und $@

                Genau das meinte ich. Und eben weil man, in $@ infolge eines angehängten \n einen Backtrace unterdrücken kann, eignen sich Exceptions auch dafür Benutzerfehler abzufangen und wie das Beispiel zeigt, vereinfacht sich dadurch der Code.

                Konkret wirft Scaliger->new( date => $Benutzereingabe ) eine Ex und weil es sehr viele Möglichkeiten gibt, ein falsches Datum einzugeben, nutzt diese Klasse anstelle endloser Kontrollstrukturen eben das Exceptionmodell als Abkürzung.

                error.pm formalisiert das zu einem try/catch/finally Modell mit Exception-Objekten, und das ist sicherlich eine prima Sache,

                Nun, es macht ja die Sache nicht besser! Es führt lediglich dazu, daß try/catch/finally als atomarer Block geschrieben werden muss. Und damit bringt des Exceptionmodell hinsichtlich Fehlerbehandlung von Benutzerfehlern keinen Vorteil.

                Eine Fehlerbehandlung wie hier die an Einfachheit nicht zu übertreffen ist, ist mit error.pm nicht machbar.

                .

                1. Hallo pl,

                  vielleicht verstehe ich error.pm ja nicht und was ein atomarer Block ist weiß ich auch nicht (bin ja ein Perl-Blinder), aber wäre damit nicht dies machbar:

                  try 
                  {
                     my $sca = Scaliger->new( date => $self->{STASH}{date});
                     # Platzhalter fürs HTML Template befüllen        
                     $self->{STASH}{result} = 'Das Datum ist gültig!';
                     # code gekürzt
                     $self->{STASH}{isleap} = $sca->leap eq 'Y' ? 'Ja' : 'Nein';
                  }
                  catch Error::Simple with {
                     # Eingegebenes Datum ungültig
                     my err = shift;
                     $self->{STASH}{result} = $err->{message};
                  }
                  

                  oder so ähnlich, das habe ich im catch vermutlich falsch geschrieben.

                  Was mir beim Perl-Errorhandling aber fehlt, ist ein Exception-Wurf über mehrere Aufrufebenen hinweg. Wenn ich in C# oder PHP einen try/catch Block mache und im try eine Funktion X gerufen wird, die eine Funktion Y ruft, die eine Funktion Z ruft wo eine Exception geworfen wird, dann kann ich das im catch fangen, ohne dass X und Y was von der Exception wissen müssen. Geht das in Perl auch?

                  Zugegeben, solche Exception-Weitwürfe haben ihre eigenen Probleme, was man in Java löst, dass man deklarativ beichten muss, dass man jemand aufruft der eine Exception wirft und man sie nicht zu fangen gedenkt...

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. Wenn ich in C# oder PHP einen try/catch Block mache und im try eine Funktion X gerufen wird, die eine Funktion Y ruft, die eine Funktion Z ruft wo eine Exception geworfen wird, dann kann ich das im catch fangen, ohne dass X und Y was von der Exception wissen müssen. Geht das in Perl auch?

                    # instanz der main
                    my $m = bless{};
                    
                    # eine statische Variable
                    my $y = 0;
                    sub x{return shift}
                    sub y{$y++; return shift}
                    sub z{die "seufz"}
                    
                    print eval{
                        $m->x()->y()->z();
                    } || "$y $@";
                    
                    

                    1 seufz at .. wird ausgegeben, y() wurde also ausgeführt. $@ zeigt auf die Zeile wo sub z definiert ist, also wo die ex gefallen ist.

                    .

                    1. Hallo pl,

                      vielleicht verstehe ich perl nicht aber ich glaube das ist nicht das was ich meinte.

                      Gedacht war: main ruft x, in x wird y gerufen, in y wird z gerufen, und z macht den letzten Seufzer.

                      Rolf

                      --
                      sumpsi - posui - clusi
                      1. Gedacht war: main ruft x, in x wird y gerufen, in y wird z gerufen, und z macht den letzten Seufzer.

                        Ok dann eben so:

                        # instanz der main
                        my $m = bless{};
                        
                        # eine statische Variable
                        my $y = 0;
                        sub x{shift->y}
                        sub y{shift->z}
                        sub z{die "seufz"}
                        
                        print eval{
                            $m->x;
                            $y = 99;
                        } || "$y $@";
                        

                        Das Ergebnis ist dasselbe. eval fängt die in z() gefallene Ex auf. $y = 99 wird nicht mehr ausgeführt weil im eval{}Block eine ex gefallen ist. Der print zeigt $y mit dem Wert 0 und $@ weist die Zeile aus wo die Ex geworfen wurde.

                        Was hast Du denn erwartet?

                        PS: Eine Verkettung von Funktionen like $m->x()->y()->z() wird möglich wenn jede Funktion die aufrufende Instanz zurückgibt, das geht auch in PHP zu machen. In Perl jedoch ist die aufrufende Instanz das erste einer Funktion übergebene Argument. Desegen ist das Ergebnis dasselbe.

                        1. Hallo pl,

                          Was hast Du denn erwartet?

                          Weiß nicht. Ich kann ja kein Perl 😀

                          Also jedenfalls geht es - ein try-catch ähnliches Konstrukt analog PHP oder anderer Sprachen.

                          Die besonderen Schönheit von Perl im Vergleich zu PHP - da kommen wir ja her - habe ich aber noch nicht gefunden. Ich finde auch keine Exceptions in deinem Estash-Beispiel, außer einem $@ im else-Teil von if ($sca). Verwendet Scaliger->new intern Exceptions und $@ ist davon noch gesetzt?

                          Rolf

                          --
                          sumpsi - posui - clusi
                          1. @Rolf B

                            richtig, meine Klasse Scaliger in der Anwendung estash nutzt Exceptions zur Fehlerbehandlung von Eingabefehlern.

                            Sowas kann man machen, wenn man davon ausgehen kann, daß die entsprechenden Funktionen, also auch der Konstruktor, sämtliche Argumente aus Benutzereingaben bekommen. So wird einfach eine EX geworfen und an den dazugehörigen Text ein \n gehängt um den Backtrace zu unterdrücken. Schließlich will der Benutzer ja nur wissen woran das Problem lag und nicht in welcher Zeile es geknallt hat.

                            In mit Carp::croak() geworfenen Exceptions hingegen lässt sich der Backtrace nicht unterdrücken. Denn der soll ja den Programmierer stets auf seine eigene fehlerhaft Zeile führen.

                            use strict;
                            use warnings;
                            use Carp;
                            
                            sub new{
                                my $class = shift;
                                my $initnr = shift;
                                return eval{
                                    croak "Nr required!" unless $initnr;
                                    bless{ NR => $initnr}, $class;
                                };
                            }
                            
                            my $m = main->new() or die $@;
                            

                            Wenn die Instanz nicht erstellt werden konnte, zeigt der Backtrace auf die Zeile wo der Konstruktor fehlerbehaftet aufgerufen wurde.

                            MfG

                            1. Hallo pl,

                              das ist der Vorteil von Exception-Objekten. Da sind Error und Stacktrace getrennt. Das geht in Perl nicht?

                              Die besonderen Schönheit von Perl im Vergleich zu PHP - da kommen wir ja her - wird mir langsam klarer. Manche Schönheit ist so speziell, dass sie nur von speziellen Menschen geliebt werden kann 😉

                              Rolf

                              --
                              sumpsi - posui - clusi
                              1. @Rolf B

                                das ist der Vorteil von Exception-Objekten. Da sind Error und Stacktrace getrennt. Das geht in Perl nicht?

                                Ich habe Dir doch geschrieben wie man damit in Perl umgeht, also auch wie man das ganz einfach trennen kann. Und dafür muss man in Perl nicht einmal ein Objekt erstellen, wozu auch!

                                MfG

  2. Hallo MB,

    es ist völlig ok, wenn Du bei einer fehlgeschlagenen Suche null zurückgibst. Das machen viele so.

    Alternativen gibt es mannigfaltig:

    • eine Exception in den Himmel schießen und darauf hoffen, dass irgendwo ein try-catch darauf wartet, sie einzufangen. Aber Exceptions sollten nicht für fachliche Fehlersituationen eingesetzt werden, sondern für technische.

    • FALSE zurückgeben. Viele PHP APIs machen das so. Mich schaudert es jedesmal, ich halte das für eine der schlechteren Entscheidungen von good ol' Rasmus.

    • Ein Array mit zwei Elementen zurückgeben: return [ $success, $result ]; und als list() emfangen:
      list($success, $user) = $user_repo->findByPseudo( 'mb' );
      Das war ein Scherz, lass das sein.

    • Zwei getrennte Werte zurückzugeben macht man aus meiner Sicht besser mit einem Objekt. Du kannst eine Klasse QueryResult erfinden und ihr zwei Eigenschaften geben: Success und Result. Success ist der Erfolg der Abfrage, und Result ist nur gefüllt wenn Success auf true steht.
      $userResult = $user_repo->findByPseudo( 'mb' );
      if ($userResult->Success) { ...code, verwende $userResult->Result... }

    Nichts davon ist so kompakt und simpel wie eine einfache null-Rückgabe. Auch wenn Tony H. das für den Milliarden-Dollar Fehler seines Lebens hält...

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo,

      oder ein Optional zurückgeben? Ist m.E. besser als ein null, weil bei einem Optional dem Leser der API sofort klar ist, dass der Rückgabewert null sein kann.

      Viele Grüße Matti

      1. Hallo Matti,

        die Wikipedia sagt:

        Outside of functional programming, these are termed nullable types.

        Ich kenne als Beispiel eines Nullable Type nur Nullable<T> aus C#, das ist aber primär eine Eierschale um geboxte Skalare, bzw. bei neueren C# Versionen Syntaxzucker um ausdrücklich sagen zu können: Ja, ich weiß dass diese Objektreferenz Null werden darf.

        In PHP gibt es die dafür nötige Sprach-Infrastruktur nur ansatzweise (Type Declarations für Parameter und Return-Werte), aber Nullable / NotNullable ist da völlig fremd.

        Von daher: schöne Idee, müsste in PHP aber ähnlich meines Alternativvorschlags 3 oder 4 gebaut werden. Der Vorteil der Optionals - dass man nämlich vom Compiler mit der Nase auf die mögliche Rückgabe von Null gestoßen wird bzw. dass Hoares Billion Dollar Mistake nur auf ausdrücklichen Anforderung hin verfügbar ist - ist in PHP mit der aktuellen Version mMn nicht erreichbar. Und da PHP keine Sprache für functional programming ist, sondern für Leute, die froh sind wenn sie ihre Bits und Bytes halbwegs originalgetreu aus der DB in den Browser bekommen, glaube ich auch nicht daran, dass Rasmus und Co das einbauen werden :)

        Rolf

        --
        sumpsi - posui - clusi
  3. Tach!

    wenn ich einen User-Objekt aus der Database über ein UserRepository haben möchte, jedoch findet die Database einfach keinen angeforderten Record, dann wird zwangsläufig ein Fehler auftreten, weil das System keinen TUser fetcht sondern null zurück gibt.

    Dann musst du diesen Fall berücksichtigen.

    Und Ich möchte sehr gern mit Return-Type arbeiten können.

    Kann man. null ist auch ein möglicher Wert, wenn man eine Klasse als Rückgabe definiert hat. Was sonst würdest du denn zurückgeben wollen, also was für Werte soll dein User-Objekt haben, wenn es den User nicht gibt? Das wäre dann ein Widerspruch, denn ein User, den es nicht gibt, kann keine Werte haben.

    Die Frage ist noch, ob das Repository eine Exception wirft, aber dann von dir gesteuert (wenn null, dann throw), oder ob es in dem Fall null zurückgibt.

    Ob die Abfrage eines nicht existenten Users ein Fehler ist, kann das Repository nicht entscheiden. Es sollte da neutral mit null bekanntgeben, dass es kein Ergebnis gibt.

    Um dem Problem Herr zu werden könnte ich eine Existenz-Abfrage vorher machen was ich gemacht habe…

    Nö, es reicht die Ergebnismenge dahingehend zu untersuchen, ob sie leer oder mit Inhalt ist, und dann entweder ein User-Objekt erzeugen oder null zurückgeben.

    dedlfix.

    1. moin,

      Was sonst würdest du denn zurückgeben wollen, also was für Werte soll dein User-Objekt haben, wenn es den User nicht gibt? Das wäre dann ein Widerspruch, denn ein User, den es nicht gibt, kann keine Werte haben.

      Naja, wenn es den User nicht gibt wonach das UserRepository mit der Methode findUserByPsseudo( string $pseudo ) : TUser fragt, hagelt es nen Error wenn nicht eine Fehler behandlung existiert. Das Programm erwartet einen TUser-Objekt und keinen primitiv null. Ich glaube aber, ich hab dich falsch verstanden 😟.

      Ob die Abfrage eines nicht existenten Users ein Fehler ist, kann das Repository nicht entscheiden. Es sollte da neutral mit null bekanntgeben, dass es kein Ergebnis gibt.

      Gut gut aber wenn ich nicht mit existPseudo() : bool, einer Property $this->_user arbeite oder eben wie du sagtest mit Exceptions, wird ein nicht existierender User einen Fehler werfen. Aber ich glaube ich hab dich wieder anders verstanden 😕.

      Bitte kläre auf. Anwendungsbeispiele die den Sachverhalt der Frage konkretisieren sehe ich gern, müssen aber nicht sein.

      lgmb

      1. Tach!

        Was sonst würdest du denn zurückgeben wollen, also was für Werte soll dein User-Objekt haben, wenn es den User nicht gibt? Das wäre dann ein Widerspruch, denn ein User, den es nicht gibt, kann keine Werte haben.

        Naja, wenn es den User nicht gibt wonach das UserRepository mit der Methode findUserByPsseudo( string $pseudo ) : TUser fragt, hagelt es nen Error wenn nicht eine Fehler behandlung existiert. Das Programm erwartet einen TUser-Objekt und keinen primitiv null. Ich glaube aber, ich hab dich falsch verstanden 😟.

        Ja, wenn du den Fall null nicht berücksichtigst, dann gibts einen Folgefehler, wenn du versuchst auf Eigenschaften zuzugreifen. Das ist aber deine Verantwortung als Verwender, auf diesen speziellen Rückgabewert zu reagieren, damit es eben keine Fehler gibt.

        Bei einer herkömmlichen Datenbankabfrage kann es (abgesehen von Fehlern) eine Ergebnismenge geben, in der kein Datensatz, einer oder mehrere enthalten sind. Wenn du davon ausgehst, es ist immer einer, aber die Abfrage eine leere Menge liefert, dann grift ein Zugriff auf das erste Element ins Leere. Das muss man berücksichtigen, dass die Menge leer sein kann.

        Und genauso ist es, wenn du eine Ebene weiter nach oben gehst. Das Repository kann entweder einen User liefern, oder es kann es nicht. Dann gibts eben null (oder eine der anderen von RolfB aufgeführten Möglichkeiten). Und dieses null muss der Verwender berücksichtigen, wenn er keinen Fehler haben möchte. Er muss doch sowieso den Fall, dass es den Unser nicht gibt, berücksichtigen, selbst wenn du ein leeres User-Objekt generierst und zurückgibst.

        dedlfix.