hotti: Rückgabewert von new()

hi,

die Zeile $pdo = new MySQL_PDO(array('base' => 'gibtsnich')); liefert mir ein

  
// print_r($pdo);  
MySQL_PDO Object  
(  
)  

auch dann, wenn eine PDOException auftritt, die ich in einer globalen Variablen $EVE festhalten möchte (Testfall: Unbekannte Datenbank).

Es ist leider nicht so, dass des Konstruktors return-Value zurückgegeben wird, mein Konstruktor sieht so aus:

  
	public function __construct($cfg = array()){  
		global $EVE;  
		try{  
			$this->dbh($cfg);  
			return 1;  
		}  
		catch(PDOException $e){  
			$EVE = $e->getMessage();  
			return;  
		}  
	}  

Kurzum: Die Frage ist, wie kann ich den Return-Value von new() beeinflussen? Offensichtlich ist der Konstruktor dafür nicht zuständig. Bitte mal um Hinweise.

Horstyrol

--
Mit Polystyrol kann ich prima dichten.
  1. Hallo,

    auch dann, wenn eine PDOException auftritt, die ich in einer globalen Variablen $EVE festhalten möchte (Testfall: Unbekannte Datenbank).

    Es ist leider nicht so, dass des Konstruktors return-Value zurückgegeben wird, mein Konstruktor sieht so aus:

    in den meisten mir bekannten Klassen hat der Konstruktor keinen ReturnValue (java, c++, PHP).

    1. Hallo Ingrid,

      auch dann, wenn eine PDOException auftritt, die ich in einer globalen Variablen $EVE festhalten möchte (Testfall: Unbekannte Datenbank).

      Es ist leider nicht so, dass des Konstruktors return-Value zurückgegeben wird, mein Konstruktor sieht so aus:

      in den meisten mir bekannten Klassen hat der Konstruktor keinen ReturnValue (java, c++, PHP). Sprachen meinte ich, nicht Klassen

    2. hi,

      in den meisten mir bekannten Klassen hat der Konstruktor keinen ReturnValue (java, c++, PHP).

      Idealerweise hätte ich das in PHP genauso wie das in Perl so geht:

        
      package main;  
      my $obj = new myClass() or die("Instanz konnte nicht erstellt werden");  
      
      

      Und siehe da, der Konstruktor heißt hier new() und kann auch was zurückgeben ;)

      Hotti

      1. Hi,

        in den meisten mir bekannten Klassen hat der Konstruktor keinen ReturnValue (java, c++, PHP).

        Idealerweise hätte ich das in PHP genauso wie das in Perl so geht:

        package main;
        my $obj = new myClass() or die("Instanz konnte nicht erstellt werden");

        
        >   
        > Und siehe da, der Konstruktor heißt hier new() und kann auch was zurückgeben ;)  
          
          
        "new" ist nicht der Konstruktor. "new" ist Bestandteil der Syntax den Konstruktor aufzurufen.  
          
        Grüße  
        - Steffen
        
      2. Moin Moin!

        Und siehe da, der Konstruktor heißt hier new() und kann auch was zurückgeben ;)

        Du übersiehst hier etwas Wesentliches:

        Perl hat keinen new-Operator.

        Ein Konstruktor ist in Perl nichts anderes als eine stinknormale Methode, die typischerweise als Klassenmethode aufgerufen wird. Die Methode heißt oft "new", das ist aber reine Konvention, damit Leute, die aus anderen OO-Systemen wie C++ kommen, nicht völlig im Regen stehen.

        Weil der Konstruktor eine Methode wie jede andere ist, steht es in Perl dem Konstruktor natürlich auch frei, statt einer blessed Reference im Fehlerfall schlicht nichts zurückzugeben (return;), was sowohl im Scalar-Kontext als auch im List-Kontext als false gewertet wird. Alternativ kann der Konstruktor natürlich auch eine Exception auslösen, sprich: die, croak oder confess aufrufen.

        package main;
        my $obj = new myClass() or die("Instanz konnte nicht erstellt werden");

          
        Dass "new" (oder nahezu jeder andere Methodenname) dem Klassennamen (oder einem Objekt) vorangestellt werden kann, ist eine Altlast, die [Indirect Object Syntax](http://perldoc.perl.org/perlobj.html#Invoking-Class-Methods), die nur noch für Filehandles benutzt werden sollte. ("Outside of the file handle case, use of this syntax is discouraged, as it can confuse the Perl interpreter.") Vermeide so etwas in neuem Code, entferne es aus altem Code. Diese Syntax macht dem Interpreter wesentlich mehr Arbeit als die folgende.  
          
        Sauber ist `my $obj=My::Class->new(...)`{:.language-perl}. Aber auch das ist noch nicht ganz eindeutig, denn wenn im package My eine Funktion Class existiert, wird diese aufgerufen und deren Rückgabewert wird als Klasse oder Objekt gewertet, mit dem new aufgerufen werden soll. (Solche Konstrukte bastelt man gelegentlich als Notlösung für Legacy-Code.) Zweifelsfrei eindeutig sind `my $obj=My::Class::->new(...)`{:.language-perl} und `my $obj='My::Class'->new(...)`{:.language-perl}, das schreibt aber nahezu niemand.  
          
        Alexander
        
        -- 
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
        
  2. Hallo,

    Kurzum: Die Frage ist, wie kann ich den Return-Value von new() beeinflussen? Offensichtlich ist der Konstruktor dafür nicht zuständig. Bitte mal um Hinweise.

    __construct gibt immer eine neue Instanz der Klasse zurück. Wenn du einen Rückgabewert brauchst, benutze eine Eigenschaft der Klasse.

    vg ichbinich

    --
    Kleiner Tipp:
    Tofu schmeckt am besten, wenn man es kurz vor dem Servieren durch ein saftiges Steak ersetzt...
  3. Hallo hotti,

    verlässt du mal deine sichere perl welt? ;).

    Also in php kannst du den Konstruktor so wie du es willst nicht beeinflussen. Alles was dir bleibt ist die Exception weiter zu leiten oder eine neue zu werfen.

    try
      $objObject = new MySQL_PDO();
    catch
      $objObject = null; //--- oder was auch immer

    alternativ könntest du dir eine Funktion bauen

    function loadClasse( $strClassName )
    {
    try
      $objObject = new MySQL_PDO();
    catch
      $objObject = null; //--- oder was auch immer

    return $objObject;
    }

    Bei dem Codeschnipsel hättest du aber Probleme Parameter beim Initialisieren mit zu geben. Vielleicht kann man eine funktion wie in Javascript überladen. Das hab ich in PHP aber noch nicht gebraucht.

    Der Code ist nicht lauffähig, ich hoffe du kannst trotzdem von der Idee her damit was anfangen.

    Gruß
    __construct(iver)
    T-Rex

    1. hi,

      verlässt du mal deine sichere perl welt? ;).

      Nicht wirklich, ich habe lediglich ein Framework gebaut, was ich zweigleisig fahren kann, d.h., die Responseklassen können wahlweise in Perl oder PHP programmiert sein und da möchte ich mal wieder eine Lok in den Dienst stellen, die das andere Gleis benutzt.

      Wobei ich jahrzehntelange Perl-Erfahrungen beim Programmieren mit PHP natürlich nicht über den Haufen werfe, sondern gezielt und auch einsetze ;)

      Also in php kannst du den Konstruktor so wie du es willst nicht beeinflussen. Alles was dir bleibt ist die Exception weiter zu leiten oder eine neue zu werfen.

      Ja, ist klar, mir kommts jedoch auf kurze Wege und einen überschaubaren Code an: So ist es in Perl durchaus möglich, in einer Zeile zu prüfen, ob die Instanz erstellt werden konnte und wenn nicht, die Ursache dafür aus einer globalen Variablen zu lesen, die immer dann einen Text hat, wenn eine Exception aufgetreten ist (In Perl ist das die Variable $@, die ist mit '' initialisiert).

      Kurz und knapp:

        
      $object = new Class or die $@;  
      
      

      Der 'etwas' längere Weg sieht in Perl so aus:

        
      $object = new Class; # Instanz wird _immer_ erstellt  
      if($@){              # frage Jehova, ob da wer sterben wollte  
         # Exception  
      }  
      else{  
         # Weiter gehts...  
      }  
      
      

      Oder (auch oft gemacht), aufgrunddessen, dass die Instanz in jedem Fall erstellt wurde, wird auf eine mögliche Exception geprüft, indem über die Instanz eine eigene Methode aufgerufen wird, z.B.:

        
      $object = new Class; # Instanz wird _immer_ erstellt  
      if($object->exception_error){  
        # lass es krachen Hugo  
      }  
      
      

      Diese beiden Möglichkeiten gäbe es auch in PHP, für welche ich mich entscheide, hängt von meiner Laune ab, und die lasse ich mit nicht mit Sätzen wie 'globale Variablen sind pfui...' vermiesen, denn globale Variablen sind keine Schande, es kommt nur darauf an, diese zweckmäßig einzusetzen.

      Hotti

      1. Hallo,

        Es ist leider nicht so, dass des Konstruktors return-Value zurückgegeben wird

        Wieso sollte er auch. Ein Konstruktor war niemals designed irgendwelche Werte auszer die Instanz seiner zugrundeliegenden Klasse zurueckzugeben.

        denn globale Variablen sind keine Schande, es kommt nur darauf an, diese zweckmäßig einzusetzen.

        Exakt - und der Zweck deiner Verwendung ist nicht gegeben.

        Wenn fuer eine korrekte Instanziierung benoetigte Bedingungen nicht erfuellt werden, dann kann eine Klasse schlicht und einfach nicht erstellt werden.
        Im Regelfall wird dann eine Exception geschmissen, die dem Aufrufer signalisiert, dass dort etwas falsch gelaufen ist. Und der Aufrufer hat dann zu entscheiden, ob der weitere Programmablauf ohne diese Klasse moeglich ist oder nicht.

        An dieser Stelle mit globalen oder lokalen Variablen rumzuspielen, deren Abfrage des Status dann auch noch dem Aufrufer obliegt, ist nun mal alles andere als "zweckmäßig", man darf auch sagen "Schmarn".

        Justme

        1. hi,

          An dieser Stelle mit globalen oder lokalen Variablen rumzuspielen, deren Abfrage des Status dann auch noch dem Aufrufer obliegt, ist nun mal alles andere als "zweckmäßig", man darf auch sagen "Schmarn".

          Vergiss bitte nicht: Ich komme von Perl, da gibt es eine globale Varable, die im Fall einer Exception den ErrorCode enthält, sofern auf Exception mit eval{} geprüft wurde.

          Indes: Da es eine solche globale Variable in PHP nicht gibt, werde ich auch keine Solche anlegen. Meine PDO-Basisklasse habe ich jetzt soweit fertig, PDO::ERRMODE_EXCEPTION ist gesetzt, etwaige Fehlercodes liegen in einem Attribut und es gibt eine Methode, die das nach draußen weiterreicht ;)

          Hotti

  4. Hi,

      
    
    > 	public function __construct($cfg = array()){  
    > 		global $EVE;  
    > 		[..]  
    > 	}  
    
    

    Igitt, wer macht denn so etwas?
    Wenn es sich bei $EVE um eine externe Abhaengigkeit handelt, dann fuege sie dem Konstrukutor als Parameter hinzu und weise sie einer Membervariablen zu, fuer die Klasse einen Getter bereitstellt.
    Wenn die Variable hingegen nur in einer Methode benoetigt wird, dann uebergebe sie lediglich der entsprechenden Methode als Parameter.
    Globals in OOP ist bereits im Design falsch.

  5. Moin!

    die Zeile $pdo = new MySQL_PDO(array('base' => 'gibtsnich')); liefert mir ein

    // print_r($pdo);
    MySQL_PDO Object
    (
    )

    
    >   
    > auch dann, wenn eine PDOException auftritt, die ich in einer globalen Variablen $EVE festhalten möchte (Testfall: Unbekannte Datenbank).  
    >   
    > Es ist leider nicht so, dass des Konstruktors return-Value zurückgegeben wird, mein Konstruktor sieht so aus:  
      
    Deine OOP-Struktur ist kaputt. Behebe die strukturellen Probleme. Das gesagte gilt für PHP und Perl.  
      
    
    > ~~~php
      
    
    > 	public function __construct($cfg = array()){  
    > 		global $EVE;  
    > 		try{  
    > 			$this->dbh($cfg);  
    > 			return 1;  
    > 		}  
    > 		catch(PDOException $e){  
    > 			$EVE = $e->getMessage();  
    > 			return;  
    > 		}  
    > 	}  
    > 
    
    

    Dein Konstruktor verlangt als Parameter nach einem Array mit Konfigurationsdaten, um damit dann eine Datenbankverbindung zu eröffnen - eventuell tritt dabei eine Exception auf.

    Der Fehler ist, nach etwas zu fragen, was nicht benötigt wird: Ein Array mit Konfigurationsdaten. Was du benötigst, ist an dieser Stelle eine DB-Connection. Frage danach. Die Factory, aus die das Objekt herauskommt, ist dafür zuständig, die Connection herzustellen und funktionsfertig an dieser Stelle zu übergeben.

    Wenn du willst, dass dein Konstruktionsversuch an dieser Stelle scheitert, lass das Try/Catch weg. Die Exception wird zuverlässig verhindern, dass eine Instanz der Klasse MySQL_PDO entsteht.

    - Sven Rautenberg

    1. hi Sven,

      Dein Konstruktor verlangt als Parameter nach einem Array mit Konfigurationsdaten, um damit dann eine Datenbankverbindung zu eröffnen - eventuell tritt dabei eine Exception auf.

      Richtig ;)

      Der Fehler ist, nach etwas zu fragen, was nicht benötigt wird: Ein Array mit Konfigurationsdaten.

      Auf das Vorhandensein der Konfigurationsdaten prüfe ich nicht, geprüft wird bei mir auf eine erfolgreiche Verbindung.

      Was du benötigst, ist an dieser Stelle eine DB-Connection. Frage danach.

      Genau das macht meine Basisklasse ;)

      Viele Grüße,
      Hotti

      1. Moin!

        Dein Konstruktor verlangt als Parameter nach einem Array mit Konfigurationsdaten, um damit dann eine Datenbankverbindung zu eröffnen - eventuell tritt dabei eine Exception auf.

        Richtig ;)

        Dein Konstruktor tut zuviel.

        Der Fehler ist, nach etwas zu fragen, was nicht benötigt wird: Ein Array mit Konfigurationsdaten.

        Auf das Vorhandensein der Konfigurationsdaten prüfe ich nicht, geprüft wird bei mir auf eine erfolgreiche Verbindung.

        Das ist das Problem, und schlechte OOP.

        Was du benötigst, ist an dieser Stelle eine DB-Connection. Frage danach.

        Genau das macht meine Basisklasse ;)

        Schlechte Vererbung noch dazu.

        - Sven Rautenberg

        1. hi,

          Dein Konstruktor verlangt als Parameter nach einem Array mit Konfigurationsdaten, um damit dann eine Datenbankverbindung zu eröffnen - eventuell tritt dabei eine Exception auf.

          Richtig ;)

          Dein Konstruktor tut zuviel.

          Ich verstehe nicht worauf Du hinauswillst, erkläre es mir bitte ohne Polemik.

          Damit wir nicht aneinander vorbeireden:

          Ich baue für DB-Zugriffe flache Hierarchien, nicht erst seit heute. Meine Basisklassen dazu (Perl, PHP) stellen jeweils ein Objekt bereit, das ist im Fall PHP nicht etwa das PDO-Objekt selbst, sondern eine Instanz _meiner_ Klasse. Diese Instanz hat das PDO-Objekt als Attribut. Im Fall Perl mache ich das genauso, die Instanzen meiner Klassen enthalten die DB-Session als Attribut. Sowohl in Perl als auch in PHP heißt dieses Attribut DBH (Data Base Handler) und dieses Attribut ist private.

          Hotti

          1. Moin!

            Dein Konstruktor tut zuviel.

            Ich verstehe nicht worauf Du hinauswillst, erkläre es mir bitte ohne Polemik.

            Ein Konstruktor sollte maximal die per Parameter übergebenen Werte in internen Feldern ablegen, mehr nicht. Die Arbeit kommt, wenn das Objekt instanziiert ist, danach durch Aufrufen von Methoden.

            Dein Konstruktor stellt anscheinend eine Verbindung zur Datenbank her, welche scheitern kann, und übernimmt auch noch das Fehlerhandling in diesem Fall. Ohne die vorgesehene globale Variable abzufragen kriegt der Nutzer dieses Objekts also gar nicht mit, dass er es mit einem nicht funktionsfähigen DB-Objekt zu tun hat - außer er ruft danach irgendeine Methode auf, die dann vermutlich scheitern wird, oder seltsame Dinge tun.

            Klassiker ist, dass PHP, sofern eine MySQL-Connection nicht besteht, implizit bei einem Aufruf von mysql_query() mit dem in der php.ini konfigurierten Standardwerten eine Connection herstellen will.

            Damit wir nicht aneinander vorbeireden:

            Ich baue für DB-Zugriffe flache Hierarchien, nicht erst seit heute. Meine Basisklassen dazu (Perl, PHP) stellen jeweils ein Objekt bereit, das ist im Fall PHP nicht etwa das PDO-Objekt selbst, sondern eine Instanz _meiner_ Klasse. Diese Instanz hat das PDO-Objekt als Attribut. Im Fall Perl mache ich das genauso, die Instanzen meiner Klassen enthalten die DB-Session als Attribut. Sowohl in Perl als auch in PHP heißt dieses Attribut DBH (Data Base Handler) und dieses Attribut ist private.

            Hier ist was zum Gucken, um dich auf den neuesten Stand zu bringen: http://www.youtube.com/playlist?list=PLBDAB2BA83BB6588E

            - Sven Rautenberg

            1. Moin ;)

              Ein Konstruktor sollte maximal die per Parameter übergebenen Werte in internen Feldern ablegen, mehr nicht. Die Arbeit kommt, wenn das Objekt instanziiert ist, danach durch Aufrufen von Methoden.

              In PHP ist der Konstruktor diejenige Methode, welche das Objekt initialisiert. Meine Basisklasse versteht unter Initialisieren das Beleben eines Attributes DBH, dieses Attribut wird vererbt und weitere Attribute wie z.B. Statementhandlers können in abgeleiteten Klassen hinzukommen.

              Das sind die Basics und mein täglich Handwerk ;)

              Dein Konstruktor stellt anscheinend eine Verbindung zur Datenbank her, welche scheitern kann, und übernimmt auch noch das Fehlerhandling in diesem Fall.

              Nicht nur anscheinend ;)

              Ohne die vorgesehene globale Variable abzufragen

              Das hätten wir doch geklärt: In PHP gibt es keine globale Variable, welche Exceptions beeinhaltet. Und ich werde den Teufel tun, eine solche Variable ins Leben zu rufen ;)

              kriegt der Nutzer dieses Objekts also gar nicht mit, dass er es mit einem nicht funktionsfähigen DB-Objekt zu tun hat - außer er ruft danach irgendeine Methode auf, die dann vermutlich scheitern wird, oder seltsame Dinge tun.

              In meinem letzten Post schrieb ich, dass die Instanz meiner Klasse _kein_ DB-Objekt ist. PHP new Class gibt mir in jedem Fall ein funktionsfähiges Objekt zurück, auch dann, wenn die DB-Verbindung scheitert. D.h., über dieses Objekt können Methoden aufgerufen werden und in meinem Fall, da ich das Objekt in jedem Fall bekomme, muss ich als Anwender der Klasse diejenige Methode aufrufen, die mir im Falle des Scheiterns der DB-Verbindung mitteilt, woran es gelegen hat.

              Btw., dies wurde mir weiter unten in diesem Thread als Empfehlung mitgeteilt, hast Du wahrscheinlich nicht gelesen ;)

              Genau das ist aber nüscht Neues, genauso handhabte ich das bis vor Kurzem auch in Perl, aber es geht eben in Perl etwas einfacher und das war der Anlass für mich, ebendiesen Thread aufzumachen.

              Klassiker ist, dass PHP, sofern eine MySQL-Connection nicht besteht, implizit bei einem Aufruf von mysql_query() mit dem in der php.ini konfigurierten Standardwerten eine Connection herstellen will.

              Das ist mir völlig egal, meine Programme sollen gefälligst das tun, was ich will ;P

              Hier ist was zum Gucken, um dich auf den neuesten Stand zu bringen: http://www.youtube.com/playlist?list=PLBDAB2BA83BB6588E

              Nüschd Neues.

              Viele Grüße,
              Horst

              --
              Ein Programm macht immer was es soll, aber es ist nicht immer das, was der Programmierer will.
              1. Hier ist was zum Gucken, um dich auf den neuesten Stand zu bringen: http://www.youtube.com/playlist?list=PLBDAB2BA83BB6588E

                Wie kannst Du das Wissen, ohne es angeschaut zu haben?

              2. Hallo,

                Hier ist was zum Gucken, um dich auf den neuesten Stand zu bringen: http://www.youtube.com/playlist?list=PLBDAB2BA83BB6588E
                Nüschd Neues.

                Das mag ja sein, aber es geht schlieszlich darum den Inhalt auch zu verstehen.

                die Instanzen meiner Klassen enthalten die DB-Session als Attribut. Sowohl in Perl als auch in PHP heißt dieses Attribut DBH (Data Base Handler) und dieses Attribut ist private.

                Meine Basisklasse versteht unter Initialisieren das Beleben eines Attributes DBH, dieses Attribut wird vererbt [..]

                Du hast eine _private_ Variable (DBH), welche _vererbt_ wird?

                Dann erklaere uns doch mal bitte, wie um alles in der Welt das moeglich sein soll.

                Das sind die Basics und mein täglich Handwerk ;)

                [sic]

                Wenn du es mit der OOP ernst mein solltest, dann nimm doch einfach Svens Ratschlag an und schau dir die Videos an und versuche zumindest die Anseatze von OOP zu verstehen. Alternativ kauf dir ein Buch. Oder nehme einen Kurs an der VHS, oder bezahle einen professionellen Entwickler, der dir das alles einmal naeher bringt.

                Ansonsten kann dir hier auch keiner helfen.

                1. Hallo,

                  Du hast eine _private_ Variable (DBH), welche _vererbt_ wird?
                  Dann erklaere uns doch mal bitte, wie um alles in der Welt das moeglich sein soll.

                  Gerne erkläre ich Dir das, Schlüsselwort 'protected' (PHP) ;)
                  (da hättest du aber auch selber draufkommen können)

                  Wenn du es mit der OOP ernst mein solltest, dann nimm doch einfach Svens Ratschlag an und schau dir die Videos an [..]
                  Ansonsten kann dir hier auch keiner helfen.

                  Bei der Stinkwut, die ich manchmal kriege, wenn ich sehe, wie Leute über OOP referieren, so als hätten sie's erfunden, kann mir wirklich keiner helfen.

                  Hotti

                  1. Hi,

                    Du hast eine _private_ Variable (DBH), welche _vererbt_ wird?
                    Dann erklaere uns doch mal bitte, wie um alles in der Welt das moeglich sein soll.

                    Gerne erkläre ich Dir das, Schlüsselwort 'protected' (PHP) ;)

                    Ach, du hast mal wieder Scheiße erzählt. Und von private gesprochen, obwohl protected gemeint ist.

                    Bei der Stinkwut, die ich manchmal kriege, wenn ich sehe, wie Leute über OOP referieren, so als hätten sie's erfunden, kann mir wirklich keiner helfen.

                    Daß Dir keiner helfen kann bei Deinem seltsamen Verständnis von OOP, ist mir klar ...

                    cu,
                    Andreas

                    --
                    Warum nennt sich Andreas hier MudGuard?
                    O o ostern ...
                    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
                  2. Hallo,

                    Du hast eine _private_ Variable (DBH), welche _vererbt_ wird?
                    Gerne erkläre ich Dir das, Schlüsselwort 'protected' (PHP) ;)

                    Mir war ja bereits bewusst, dass du wieder eine wilde und vor allem unlogische Antwort von dir geben wirst. Aber mit diesem Post hast du echt den Darwin-Award verdient! Selbstdemontage par excellence.

                    Man hast du ein Glueck, dass Dummheit nicht bestraft wird.

                    MudGuard hat deine Auffassungsgabe hinsichtlich OOP eigentlich am besten auf den Punkt gebracht:
                    Obviously Outstanding Poppycock.