Jörg: php, Funktionen, Klassen und Fehlersuche

Hallo,

ich lasse in einer Schleife ien Script durchlaufen, bei dem der 1. Schleifendurchgang noch funktioniert, der 2. aber nicht mehr.

Die entscheidende Stelle im Script ist ein Funktionen-Klassen-Konstrukt, das ich bisher auch in einer Schleife genutzt hatte, aber indem sich die Seite selber neu aufrief. Nun habe ich es umgeschrieben und eine while-Schleife macht diesen job.

Warum stockt das Script an dieser Stelle?

Hinweis: Die Query im ersten Durchlauf wird geschrieben, die zweite nicht mehr. Möglicherweise darf ich hier die Funktion nicht mehrfach aufrufen? Mein error_reporting ist eingeschaltet, zeigt mir aber nichts an.

Jörg

function Blablub {    
....
require_once('../fpdf/mc_table_turn1.php');

session_start();
$_SESSION['ID'] = $ID;

 class PDF_Table_Header extends PDF_MC_Table_TURN1
     {

//Kopfzeile
function Header()
{
global $con;
global $ID; 
                 

function foo($bar)
{
global $con;
global usw...;


$query_namen="select ... ";

 echo "$query_namen";

 .....
  1. Hi,

    Die entscheidende Stelle im Script ist ein Funktionen-Klassen-Konstrukt, das ich bisher auch in einer Schleife genutzt hatte, aber indem sich die Seite selber neu aufrief. Nun habe ich es umgeschrieben und eine while-Schleife macht diesen job.

    Warum stockt das Script an dieser Stelle?

    Das Problem liegt vermutlich in den Teilen des Scripts, die Du verheimlichst.

    Wo ist denn die Schleife, um die es geht?

    Was versteckt sich hinter "..."?

    cu,
    Andreas a/k/a MudGuard

  2. Tach!

    Warum stockt das Script an dieser Stelle?

    Dein gezeigter Code ist syntaktisch unvollständig, so dass nicht zu sehen ist, was worin geschachtelt ist. Deshalb hier nur der allgmeine Tipp: betreibe Debugging. Wenn Wunsch und Wirklichkeit voneinander abweichen, muss man herausfinden, wo das geschieht. An irgendeiner Stelle ist vielleicht ein Variableninhalt oder Funktionsergebnis oder Ergebnis eines Ausdrucks anders als erwartet. Zudem können Kontrollausgaben an strategisch wichtigen Punkten aufzeigen, welche Wege die Ausführung geht, oder auch nicht geht.

    dedlfix.

    1. Wenn Wunsch und Wirklichkeit voneinander abweichen, muss man herausfinden, wo das geschieht.

      Na, die habe ich gefunden:

      class PDF_Table_Header extends PDF_MC_Table_TURN1
      

      Genau an dieser Stelle bricht das script bei Durchlauf 2 ab.

      Jörg

      1. Hallo,

        class PDF_Table_Header extends PDF_MC_Table_TURN1
        

        Genau an dieser Stelle bricht das script bei Durchlauf 2 ab.

        kaufst du dir jedes Mal ein neues Auto, wenn du einkaufen fahren möchtest?

        Gruß
        Kalk

        1. Hallo Kalk,

          class PDF_Table_Header extends PDF_MC_Table_TURN1
          

          Genau an dieser Stelle bricht das script bei Durchlauf 2 ab.

          kaufst du dir jedes Mal ein neues Auto, wenn du einkaufen fahren möchtest?

          Normalerweise schon. 😉

          Problem ist, ich weiß nicht, wie ich aus der Nummer raus komme. Und ich weiß auch nicht, warum mein error_reporting nicht meckert.

          Jörg

      2. Tach!

        Genau an dieser Stelle bricht das script bei Durchlauf 2 ab.

        Ist das eine Rätselaufgabe? Wenn nicht, gibt bitte nachvollziehbaren Code. Am besten ist dazu ein auf das Problem reduzierter Prototyp.

        Vielleicht schachtelst du Dinge ungünstig. Wenn zum Beispiel eine Funktion in einer anderen steht, muss man dafür sorgen, dass die Deklaration der inneren Funktion nur einmal ausgeführt wird. Ansonsten bricht PHP ab, weil es keine zwei Funktionen mit demselben Namen anlegen kann.

        dedlfix.

        1. Hi,

          Genau an dieser Stelle bricht das script bei Durchlauf 2 ab.

          Ist das eine Rätselaufgabe? Wenn nicht, gibt bitte nachvollziehbaren Code. Am besten ist dazu ein auf das Problem reduzierter Prototyp.

          Genau das habe ich doch gemacht. Oder nicht?

          Vielleicht schachtelst du Dinge ungünstig.

          Neuer Versuch:

          <?php
          $i=0;
          while ($i < 3) {
              function Blablub()
              {
                  //....
                  require_once('../fpdf/mc_table_turn1.php');
          
                  session_start();
                  $_SESSION['ID'] = $ID;
          
                  class PDF_Table_Header extends PDF_MC_Table_TURN1
                  {
          
                      //Kopfzeile
                      function Header()
                      {
                          global $con;
                          global $ID; 
                      }
          
                      function foo($bar)
                      {
                          global $con;
          
          
                          $query_namen = "select ... ";
                          echo "$query_namen";
          
                          //.....
          
                      }
                  }
              }
              $i++;
          }
          

          So ich mein Beispiel selber correct verstanden habe, sollte diese Schleife auch im 2. Duchlauf an der Stelle "class PDF_Table_Header extends PDF_MC_Table_TURN1" abbrechen.

          Jörg

          1. Hallo Jörg,

            da hast Du Funktionen und Klassen vermutlich komplett mistverstanden.

            So nicht:

            $i=1;
            while ($i < 3) {
                function Blablub()
                {
                   class PDF_Dings
                   {
                   }
                }
            }
            

            Wenn der nicht käme:

            <b>Fatal error</b>:  Cannot redeclare Blablub() (previously declared in [...]
            

            Käme unweigerlich beim zweiten Aufruf von Blablub der hier:

            <b>Fatal error</b>:  Cannot declare class PDF_Dings, because the name is already in use 
            

            Wenn Du das nicht zu sehen bekommen hast, ist dein Error-Reporting nicht korrekt eingeschaltet.

            Genau darauf bezog sich die Frage, ob Du Dir für jedes Einkaufen ein neues Auto kaufst. Bei Dir ist es noch schlimmer: Du baust jedesmal eine neue Straße (Blablub), um mit den neugekauften Auto (PDF_Dings) darauf einkaufen zu fahren

            Das willst Du nicht. Du kaufst einmal ein Auto, du baust einmal eine Straße und fährst munter einkaufen:

            $i=1;
            while ($i < 3) {
               Blablub($i);
               $i++;
            }
            
            function Blablub($i)
            {
               // do sth with $i
            }
            
            class PDF_Dings extends ...
            {
            }
            

            Eine Funktion ist ein Stück Code mit einem Namen, das Du wiederverwendest. Eine Klasse ist ein Klumpen aus Variablen und Funktionen, die Du wiederverwendest. Deswegen wird beides separat definiert (am Anfang oder am Ende). PHP ist die Reihenfolge egal; du kannst Funktionen auch am Ende definieren, er findest sie trotzdem, weil er den Code zweimal durchliest. Zuerst um ihn in Bytecode zu compilieren, und dann, um ihn auszuführen.

            Wenn PHP die Definition antrifft, wird das nur gespeichert, aber nicht ausgeführt. Die Ausführung erfolgt, wenn Du die Funktion aufrufst.

            Das gilt auch für Klassen. Du kannst eine Klasse nur einmal definieren, danach ist der Name belegt.

            ALLERDINGS gilt das nur, wenn Klasse oder Funktion auf dem Top-Level definiert werden. Du kannst eine Funktion oder Klasse auch irgendwo zwischen geschweiften Klammern definieren, dann entsteht sie erst, wenn diese Codestelle ausgeführt wird. Sie ist danach aber global verfügbar (anders als in JavaScript, wo lokale Funktionen lokal bleiben):

            blablub(99);   // scheitert
            
            MakeBlub();
            blablub(1);    // funktioniert
            
            function MakeBlub() 
            {
               function blablub($n)
               {
                  echo "Der Blub ist auf Stufe $n\n";
               }
            }
            

            Für dein Beispiel heißt das: Definiere die Funktion und die Klasse separat. Schachtele sie nicht ineinander. Du hast dann drei Bereiche:

            • Hauptprogramm
            • Funktion Blablub
            • Klasse PDF_Table_Header und ihre Methoden

            Der Datenaustausch zwischen diesen Bereichen erfolgt rein über Parameter.

            Du solltest die Session auch nicht in Blablub starten. Sowas tut man nur einmal zu Programmbeginn, oder man definiert einen Autostart für die Session.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo Rolf,

              da hast Du Funktionen und Klassen vermutlich komplett mistverstanden.

              Funktionen sicher nicht, aber Klasse wohl.

              Wenn Du das nicht zu sehen bekommen hast, ist dein Error-Reporting nicht korrekt eingeschaltet.

              Was soll ich denn machen?

              error_reporting(E_ALL);
              ini_set('display_errors','ON');
              

              Das blöde ist, dass man das bei meinem Provider auch noch im Konfigurationsmenü einstellen kann, dann aber global, was ich nicht will.

              Ok, habs mittlerweile gefunden. Man muss im Konfigmenü des Providers erstmal freigeben, dass Scripte die globalen Einstellungen überschreiben dürfen arghs

              Eine Funktion ist ein Stück Code mit einem Namen, das Du wiederverwendest. Eine Klasse ist ein Klumpen aus Variablen und Funktionen, die Du wiederverwendest. Deswegen wird beides separat definiert (am Anfang oder am Ende).

              Habe jetzt alle Klassen und Funktionen an den Scriptanfang geschrieben, Scriptende hatte zuvor nicht funktioniert. Keine Ahnung, warum. Jedenfalls schlug eine Query fehl, was sie nicht tut, wenn ich alle Funktionen und Klassen an den Scriptanfang stelle. Und ich bin grad zu entnervt, diesem Phänomen auf den Grund zu gehen.

              PHP ist die Reihenfolge egal; du kannst Funktionen auch am Ende definieren, er findest sie trotzdem, weil er den Code zweimal durchliest. Zuerst um ihn in Bytecode zu compilieren, und dann, um ihn auszuführen.

              Trotzdem schön, zu wissen, ich habe mich immer gefragt, ob das einen unterschied macht.

              Für dein Beispiel heißt das: Definiere die Funktion und die Klasse separat. Schachtele sie nicht ineinander. Du hast dann drei Bereiche:

              • Hauptprogramm
              • Funktion Blablub
              • Klasse PDF_Table_Header und ihre Methoden

              Habe ich gemacht und siehe da: Es funkt. 👍😊

              Du solltest die Session auch nicht in Blablub starten. Sowas tut man nur einmal zu Programmbeginn, oder man definiert einen Autostart für die Session.

              Mache ich auch normalerweise. Hatte das jetzt hier mit reingenommen wegen der Verständlichkeit.

              Danke, Rolf! Jetzt läuft "der Kas" und ich bin echt froh drum. Das ist ein Riesenscript mit fast 5000 Codezeilen, darin finde ich mich nicht so ganz easy zurecht 😉 Entsprechend entnervt bin ich gerade. Aber meine Nerven finde ich wieder und dann läuft das Teil ja immer noch lol

              Jörg

          2. Tach!

            Am besten ist dazu ein auf das Problem reduzierter Prototyp.

            Genau das habe ich doch gemacht. Oder nicht?

            Nein. Ein Prototyp ist ein Programm, das laufen kann, an dem man die prinzipielle Funktionsweise einer Lösung nachweisen kann.

            Du hast Codefragmente gezeigt. Darin waren Funktionen und Klassen angefangen, und dann kamen Punkte. Es gab keine schließenden Klammern, anhand derer man sehen konnte, wo sie enden. Der Code war auch nicht besonders gut eingerückt, um die Struktur zu erkennen.

            Neuer Versuch:

            Schon besser. Das Problem lässt sich nun erkennen und wurde ja auch schon in anderen Postings erklärt. Deswegen beschränke ich mich hier nur auf eine kleine Anmerkung: Da kann noch viel mehr gekürzt werden. Die Session hat keine Bewandnis, ebensowenig braucht es die nicht weiter verwendeten Variablen.

            Wenn man solche Probleme hat, die man nicht versteht, kann die Prototyp-Vorgehensweise hilfreich sein. Man baut sich das Problem in einer neuen Anwendung nach, und lässt dabei alles weg, was nicht notwendig ist, um das Phänomen nachzustellen. Dann kann man sich auf das wesentliche konzentrieren und daran Untersuchungen anstellen.

            dedlfix.