Linuchs: php-functions in einer function?

Moin,

in einem Programm möchte ich zusätzlich zur lokalen Datenbank eine DB auf fremdem Server zugreifen. Für jede Datenbank habe ich eine db_connect.php mit einem Array der vorhandenen Tabellen und einigen zugehörigen Funktionen.

Natürlich "hakt" es, wenn ich zur bereits include( "db_connect.php" ) noch eine include( "db_connect2.php" ) mit denselben Funktionen hinzufüge. An der Stelle bricht das PHP-Programm ohne Fehlermeldung ab.

Wenn ich nur das Array der vorhandenen Tabellen einfüge (ohne Funktionen), kann ich mit den von db_connect.php vorhandenen Funkionen die entfernte DB öffnen und lesen.

Na, gut, dann mache ich include( "db_connect2.php" ) eben innerhalb einer Funktion. Dachte ich. Wieder bricht das Programm an dieser Stelle ab. Es bricht auch ab, wenn ich die schon vorhandene und vollkommen fehlerfreie db_connect.php in der Funktion include.

Kann es sein, dass PHP keine Funktionen in einer Funktion duldet und dafür keine Fehlermeldung hat? Nee, eigentlich nicht. Dies hier läuft bis zum include:

function connectFerneDB() {
  function sagWas() {
    echo "<p>Funktion in der Funktion</p>";
  }
  sagWas();
  echo "<p>vor dem include</p>";
  include( "db/_db_connect.php" );
  echo "<p>nach dem include</p>";
...
}

Was kann der Fehler sein?

Linuchs

  1. Tach!

    Natürlich "hakt" es, wenn ich zur bereits include( "db_connect.php" ) noch eine include( "db_connect2.php" ) mit denselben Funktionen hinzufüge. An der Stelle bricht das PHP-Programm ohne Fehlermeldung ab.

    Das glaube ich nicht, dass da keine Meldung produziert wird. Du wirst sie nur nicht angezeigt bekommen. In der php.ini (nicht im Code mit Funktionen) braucht es dazu die Erlaubnis, Fehlermeldungen anzuzeigen. Natürlich ist das nur die Einstellung für das Entwicklungssystem, das produktive soll keine Meldungen anzeigen. Schau dir die Konfigurationswerte für das Error Handling an und was sie tun, vergleiche mit den aktuellen Werten laut phpinfo()-Ausgabe und stell sie dann auf größtmögliche Gesprächigkeit ein. Die üblichen Logfiles, vor allem auch das ErrorLog vom Webserver können ebenfalls Meldungen enthalten.

    Zum eigentlichen Problem: Funktionen sind generell global und ihr Name einmalig. Man kann sie zwar geschachtelt definieren, aber dann darf man die äußere Funktion nur ein einziges Mal aufrufen, weil bei diesem Aufruf die "innere" Funktion erstellt wird und beim nächsten Aufruf bereits vorhanden ist.

    Kann es sein, dass PHP keine Funktionen in einer Funktion duldet und dafür keine Fehlermeldung hat?

    Doch und doch. Es ist möglich, aber die innere wird nicht als lokal begrenzte Funktion angelegt. Und es gibt selbstverständlich eine Meldung.

    dedlfix.

    1. Moin

      Natürlich "hakt" es, wenn ich zur bereits include( "db_connect.php" ) noch eine include( "db_connect2.php" ) mit denselben Funktionen hinzufüge. An der Stelle bricht das PHP-Programm ohne Fehlermeldung ab.

      Das glaube ich nicht, dass da keine Meldung produziert wird. Du wirst sie nur nicht angezeigt bekommen.

      Mit dem System arbeite ich seit Jahren. Habe extra noch mal getestet und eine unbekannte Datei includieren wollen. Da kommt Mecker.

      Zum eigentlichen Problem: Funktionen sind generell global und ihr Name einmalig. Man kann sie zwar geschachtelt definieren, aber dann darf man die äußere Funktion nur ein einziges Mal aufrufen, weil bei diesem Aufruf die "innere" Funktion erstellt wird und beim nächsten Aufruf bereits vorhanden ist.

      Naja, testen wir mal:

      function sagWas() {
        echo "<p>Ich zähle: 1</p>";
      }
      sagWas();
      
      function connectFerneDB() {
        function sagWas() {
          echo "<p>Ich zähle: 2</p>";
        }
        sagWas();
      }
      connectFerneDB();
      

      Prompt kommt Mecker:

      Ich zähle: 1
      Fatal error: Cannot redeclare sagWas() (previously declared in .../p091.php:20) in .../p091.php on line 25 
      

      Jetzt packe ich den Fünfzeiler

      <?
      function sagWas() {
        echo "<p>Ich zähle: 1</p>";
      }
      ?>
      

      in die Datei mist_sagWas.php und mache

      // Variante 2:
      include( "mist_sagWas.php" );
      sagWas();
      
      function connectFerneDB() {
        include( "mist_sagWas.php" );
        sagWas();
      }
      connectFerneDB();
      
      echo "<p>Ich höre auf zu zählen</p>";
      

      Antwort:

      Ich zähle: 1
      

      Abbruch und keine Fehlermeldung.

      Linuchs

      1. Hallo

        Naja, testen wir mal:

        function sagWas() {
          echo "<p>Ich zähle: 1</p>";
        }
        sagWas();
        
        function connectFerneDB() {
          function sagWas() {
            echo "<p>Ich zähle: 2</p>";
          }
          sagWas();
        }
        connectFerneDB();
        

        Prompt kommt Mecker:

        Ich zähle: 1
        Fatal error: Cannot redeclare sagWas() (previously declared in .../p091.php:20) in .../p091.php on line 25 
        

        Wie die Fehlermeldung schon sagt, deklarierst du die Funktion ein zweites Mal (innerhalb von connectFerneDB()), was der PHP-Parser nicht erlaubt.

        Jetzt packe ich den Fünfzeiler

        <?
        function sagWas() {
          echo "<p>Ich zähle: 1</p>";
        }
        ?>
        

        in die Datei mist_sagWas.php und mache

        // Variante 2:
        include( "mist_sagWas.php" );
        sagWas();
        
        function connectFerneDB() {
          include( "mist_sagWas.php" );
          sagWas();
        }
        connectFerneDB();
        
        echo "<p>Ich höre auf zu zählen</p>";
        

        Antwort:

        Ich zähle: 1
        

        Abbruch und keine Fehlermeldung.

        Aus dem PHP-Handbuch zu include (Hervorhebungen von mir):

        „Wenn in der eingebundenen Datei Funktionen definiert werden, können sie in der einbindenden Datei genutzt werden, unabhängig davon, ob sie vor oder nach return definiert werden. Wenn eine Datei zweimal eingebunden wird, erzeugt PHP 5 einen fatalen Fehler, weil Funktionen bereits definiert wurden, während PHP 4 Funktionen, die nach return definiert werden, ignoriert.“

        Frage: Welche PHP-Version läuft bei dir?

        Tschö, Auge

        --
        Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
        Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
        1. Aus dem PHP-Handbuch zu include (Hervorhebungen von mir):

          „Wenn in der eingebundenen Datei Funktionen definiert werden, können sie in der einbindenden Datei genutzt werden, unabhängig davon, ob sie vor oder nach return definiert werden. Wenn eine Datei zweimal eingebunden wird, erzeugt PHP 5 einen fatalen Fehler, weil Funktionen bereits definiert wurden, während PHP 4 Funktionen, die nach return definiert werden, ignoriert.“

          Frage: Welche PHP-Version läuft bei dir?

          PHP-Vers.=[5.3.3-7+squeeze15]

          Gut, es kann mit meiner Idee nicht funktionieren. Mir wären vier Stunden Suche und dieser Faden erspart geblieben, wenn eine Fehlermeldung gezeigt würde.

          Linuchs

          1. Tach,

            PHP-Vers.=[5.3.3-7+squeeze15]

            der Support für Squueze ist endgültig ausgelaufen (https://wiki.debian.org/LTS/), da ist ein Update dringend nötig.

            mfg
            Woodfighter

      2. Tach!

        Naja, testen wir mal:

        [erster Versuch]

        Prompt kommt Mecker:

        Ich zähle: 1
        Fatal error: Cannot redeclare sagWas() (previously declared in .../p091.php:20) in .../p091.php on line 25 
        

        [zweiter Versuch]

        Abbruch und keine Fehlermeldung.

        Da hast du wohl die Fehlermeldungsanzeige ausgeschaltet. Ich bekomme nämlich für den Fall genau die gleiche Fehlermeldung.

        dedlfix.

  2. Hallo

    in einem Programm möchte ich zusätzlich zur lokalen Datenbank eine DB auf fremdem Server zugreifen. Für jede Datenbank habe ich eine db_connect.php mit einem Array der vorhandenen Tabellen und einigen zugehörigen Funktionen.

    Was kann der Fehler sein?

    Deine gewählte Struktur?

    Warum nutzt du zur Verbindungsaufnahme nicht die von PHP zur Verfügung gestellten Funktionen und arbeitest, jenachdem, welchen Server du gerade belästigen willst, mit dem Handler, den du als Ergebnis der Verbindungsaufnahme zurückerhalten hast? Die Liste(n) der Tabellen oder Spezialfunktionen (zu welchem Zweck die auch immer da sein werden) hast du so natürlich noch nicht da, aber du brauchst keine – mit Verlaub – komischen Kostrukte zur Verbindungsaufnahme.

    Tschö, Auge

    --
    Wir hören immer wieder, dass Regierungscomputer gehackt wurden. Ich denke, man sollte die Sicherheit seiner Daten nicht Regierungen anvertrauen.
    Jan Koum, Mitgründer von WhatsApp, im Heise.de-Interview
    1. Moin,

      ... und arbeitest, jenachdem, welchen Server du gerade belästigen willst, mit dem Handler, den du als Ergebnis der Verbindungsaufnahme zurückerhalten hast?

      Ich brauche die entfernte DB zusätzlich, weil dorthin kopiert werden muss. Brauche also zwei Händler. Die Idee, das mit zwei vorhandenen objektorientierten "Baukasten" - include Dateien zu machen, geht also nicht.

      Linuchs