Ankündigung

Einklappen
Keine Ankündigung bisher.

etwas ähnliches wie __autoload() für Funktionen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • etwas ähnliches wie __autoload() für Funktionen

    Guten Morgen zusammen =)

    Ich habe in meiner CMS mal Gebrauch von __autoload() gemacht, damit die Includes automatisch eingebunden werden, die diese Klassen enthalten.

    PHP-Code:
    <?php

    function __autoload($__Name) {
        
    $__File STDINC_PATH."/inc/class.".$__Name.".php";
        if(
    is_file($__File)) {
            include(
    $__File);
        } else {
            exit(
    "<H2>__autoload('".$__Name."'): Fehler beim Nachladen der Klasse</H2>");
        }
    }

    ?>
    So, und jetzt wollte ich fragen, ob es denn eine ähnliche Möglichkeit gibt, darauf zu reagieren, wenn eine nicht definierte Funktion aufgerufen wird?
    Könnte man irgendwie Fehler abfangen und trotzdem unbemerkt (ohne eine Fehlermeldung auszugeben) das Script weiterlaufen lassen?
    Und wenn ja: würde dadurch die Geschwindigkeit zu leiden haben?

    Danke euch im Voraus!


  • #2
    Exception Handling. Damit kannst Du einen Fehler abfangen und das Skript in eine beispielsweise "alternative" Richtung leiten. Es einfach weiter laufen zu lassen ist schlicht unlogisch (und geht meines wissens nicht.).

    Gruß

    Kommentar


    • #3
      Also, unlogisch wäre es auch für mich, aber __autload() gibt es ja auch =)

      Kommentar


      • #4
        irgendwie Fehler abfangen und trotzdem unbemerkt (ohne eine Fehlermeldung auszugeben)
        Eine (noch) nicht geladenes Objekt ist ja kein Fehler, denn meistens gehört das ja zur Programmarchitektur dazu, dass Objekte dynamisch geladen werden (siehe FActory-Klassen).
        Wofür wäre denn das gut, wenn eine nicht definierte Funktion durch eine art __autoload-Aufruf geladen würde? Wäre die Funktion dann in einer externen PHP-Datei in einer Art "FUnktionspool"? Da ist doch eine Klasse mit den (passenden) Methoden doch um einiges Besser und flexibler, denn ein __autoload für Funktionen wäre ja - in diesem Kontext - wieder ein rückschritt in richtung prozeduralsprache.

        Oft wird noch unterschätzt, wozu Exceptions fähig sind(bzw. viele nutzen sie nicht, weil sie aus gründen der bequemlichkeit(u.a) lieber ihre konservativen error-handling methoden verwenden - was ja auch meistens ok ist), aber es ist auf jeden fall einen Blick wert.

        Gruß

        Kommentar


        • #5
          Also, die Sache ist die, dass Klassen um einiges langsamer arbeiten und mehr Speicher verbrauchen, als normale Funktionen. Okay, der Speicherverbrauch ist zwar kein so großes Ding, aber die Tatsache, dass Klassen langsamer sind, ist oft ein Gegenargument für mich.

          Aber naja... das war wohl tatsächlich eine blöde Idee
          Da ist zwar eine Funktion Namens load(), die mir meine Includes einbindet, aber einen Moment lang dachte ich mir, wie schön es doch wäre, sich nicht mal die Mühe machen zu müssen, diesen aufrufen zu müssen.

          Ach so, noch etwas: wenn man irgendwo klasse::methode(); benutzt, ist es doch kein Objekt, oder?
          Man kann zwar trotzdem sagen $o = new klasse;, aber die Klasse enthält in dem Fall nur Funktionen, die nicht miteinander kommunizieren.
          Die Klasse dient in dem Fall nur als Bunker, um die Funktionen unter einem Dach zu bringen

          P.S. entschuldigt wenn die Smilies etwas kindisch wirken

          Kommentar


          • #6
            Hola,

            was ist mit der Verwendung von __call?


            Bis dääähne.

            Kommentar


            • #7
              Zitat von GelaMu
              Also, die Sache ist die, dass Klassen um einiges langsamer arbeiten und mehr Speicher verbrauchen, als normale Funktionen. Okay, der Speicherverbrauch ist zwar kein so großes Ding, aber die Tatsache, dass Klassen langsamer sind, ist oft ein Gegenargument für mich.
              Ist das denn wirklich noch so? Ich hatte kürzlich das gleiche vor wie du und mir dann ebenfalls überlegt, gut erstelle ich statt einer Funktion eben eine Sammel-Klasse mit statischer Methode. Zumindest ähnliche Funktionen könnte man darin ja sammeln. Von der Geschwindigkeit her habe ich mal statische und nicht-statische Methoden sowie Funktionen verglichen, etwas Rechnerei darin und eine Millionen Neu-Aufrufe (also mit Instanzierung bei der nicht-statischen Variante), die Ergebnisse waren nahezu gleich.

              Das mag zwar kein ordentlicher Benchmark-Test gewesen sein, aber zumindest scheint es ja so, dass sich die drei Kandidaten nicht viel nehmen.

              Kommentar


              • #8
                Zitat von GelaMu
                Also, die Sache ist die, dass Klassen um einiges langsamer arbeiten und mehr Speicher verbrauchen, als normale Funktionen. Okay, der Speicherverbrauch ist zwar kein so großes Ding, aber die Tatsache, dass Klassen langsamer sind, ist oft ein Gegenargument für mich.
                Um welchem Faktor denn? Mal so zum Nachdenken.
                PHP-Code:
                <?php
                define 
                ("TESTCASEA"1000000);
                define ("TESTCASEB"1000000);
                define ("LOOP"1000000);

                class 
                {
                    public static function 
                test ($a,$b)  {
                        for (
                $i 1$i <= $a$i++) {
                            
                $x $x $b;
                        }
                    }
                }

                class 
                {
                    public function 
                test ($a,$b)  {
                        for (
                $i 1$i <= $a$i++) {
                            
                $x $x $b;
                        }
                    }
                }


                function 
                ($a,$b) {
                   for (
                $i1$i <= $a$i++) {
                       
                $x $x $b;
                   }
                }

                $stamp microtime (true);
                for (
                $p 0$p >= LOOP$p++) {
                    
                (TESTCASEA,TESTCASEB);
                }
                echo (
                microtime (true) - $stamp) * 1000 1000;
                echo 
                "
                "
                ;

                $stamp microtime (true);
                for (
                $p 0$p >= LOOP$p++) {
                    
                A::test (TESTCASEA,TESTCASEB);
                }
                echo (
                microtime (true) - $stamp) * 1000 1000;
                echo 
                "
                "
                ;

                $stamp microtime (true);
                for (
                $p 0$p >= LOOP$p++) {
                    
                $test = new ();
                    
                $test->test (TESTCASEA,TESTCASEB);
                }
                echo (
                microtime (true) - $stamp) * 1000 1000;
                echo 
                "
                "
                ;

                ?>
                Code:
                20.9808349609
                11.9209289551
                10.0135803223
                Und wenn du wirklich effizient programmieren willst: Schreib in Assember
                Nicht jeder Fehler ist ein Bug.

                Kommentar


                • #9
                  Zitat von KingCrunch
                  Code:
                  20.9808349609
                  11.9209289551
                  10.0135803223
                  Was hast du'n für ne alte Mühle?

                  20.0271606445
                  8.10623168945
                  5.96046447754


                  Ich hatte keine Schleife bei meinen Tests, aber da sieht man mal wie wie hingeklatschte Benchmarks fürn Arsch sein können

                  Kommentar


                  • #10
                    Laptop Aber die Aussage bleibt die selbe
                    Nicht jeder Fehler ist ein Bug.

                    Kommentar


                    • #11
                      KingCrunch,

                      wenn die Funktion einmal am Laufen ist, gibt es ja auch keine Geschwindkeitsunterschiede, es sei denn, man greift auf die Klasse zu, in dem man $this->var oder klass::$var benutzt (oder ähnliches).
                      Schleifen in dem Sinne wie for($i=0; $i<9999; $i++) { $x=$x*$i*x; } machen da fast keine Unterschiede.

                      Ich hab`s ganz einfach gestestet:
                      PHP-Code:
                      <?php

                      $GLOBALS
                      ["*x*"] = array();
                      function 
                      meine_funktion() {
                          
                      $GLOBALS["*x*"][] = microtime(true);
                      }

                      class 
                      meine_klasse {
                          static 
                      $s = array();
                          function 
                      meine_funktion() {
                              
                      meine_klasse::$s[] = microtime(true);
                          }
                      }

                      class 
                      meine_classe {
                          var 
                      $s = array();
                          function 
                      meine_funktion() {
                              
                      $this->s[] = microtime(true);
                          }
                      }

                      # Platz 1
                      $t1 microtime(true);
                      for(
                      $i=0$i<99999$i++) {
                         
                      meine_funktion();
                      }
                      $t2 microtime(true);
                      echo (
                      $t2-$t1)."\n";

                      # Platz 2
                      $t1 microtime(true);
                      for(
                      $i=0$i<99999$i++) {
                         
                      meine_klasse::meine_funktion();
                      }
                      $t2 microtime(true);
                      echo (
                      $t2-$t1)."\n";

                      # Platz 3
                      $o = new meine_classe;
                      $t1 microtime(true);
                      for(
                      $i=0$i<99999$i++) {
                         
                      $o->meine_funktion();
                      }
                      $t2 microtime(true);
                      echo (
                      $t2-$t1)."\n";

                      ?>

                      EDIT: Also, da hat sich wohl einiges geändert seit meinen letzten Tests
                      Platz 3 ist jetzt im Gegenteil Platz 1

                      Übrigens: sowas hier echo (microtime (true) - $stamp) * 1000 * 1000; ist immer etwas ungenauer. Besser zuerst sich die Timestamp in eine Variable holen, dann subtrahieren...

                      Kommentar


                      • #12
                        Jetzt vergleichst du allerdings Äpfel mit Birnen: Du kannst doch nicht Klassenvariablen mit Objektvariablen und schon garnicht mit globalen Variablen (wobei diese sowieso furchtbar sind) vergleichen. Vergleichbarer wäre es, wenn du in deinen Methoden ebenfalls globale Variablenzugriff nutzen würdest. Zudem ist dein Beispiel beim Objekt sowieso nicht ganz durchdacht, weil du nun 100000 Objekte, mit einer Objektvariable als Array mit genau einem Element besitzt. Ich sachs ja: Äpfel und Birnen.

                        Etwas vergleichbares, wie Klassen- oder Objektvariablen gibt es nun mal in Funktionen nicht. Und da du ja eh nur die Klassen als "Funktionscontainer" benutzen wolltest, brauchst du sie auch garnicht Willst du allerdings mehr mit den Klassen oder Objekten machen, wird es immer schwieriger äquivalente Funktionen zu finden.

                        Die for-Schleife diente bei mir nur dazu PHP etwas zu beschäftigen. Im Endeffekt läuft es darauf hinaus, dass Klassen und Funktionen nunmal zwei verschiedene Dinge sind. Sich aber auf Funktionen zu beschränken, weil die vermeintlich schneller sind, ist allerdings nicht zu Ende gedacht. Man kann sich auch zu Tode optimieren

                        Zitat von GelaMu
                        Übrigens: sowas hier echo (microtime (true) - $stamp) * 1000 * 1000; ist immer etwas ungenauer. Besser zuerst sich die Timestamp in eine Variable holen, dann subtrahieren...
                        Das ist mir neu, kannst du mir das vielleicht erläutern? Meinem Wissensstand wird es ziemlich gleich behandelt. Oder meinst zu bezogen auf korrekte Zeitmessung und nicht Werteungenauigkeit? Dann wiederum ist es vernachlässigbar, da ja alle Werte von dieser Ungenauigkeit betroffen sind
                        Nicht jeder Fehler ist ein Bug.

                        Kommentar


                        • #13
                          Hallo,

                          ich habe ein ähnliches Problem gehabt. Um zu prüfen, ob eine Funktion vorhanden ist, benutze ich folgendes Codeschnipsel:

                          PHP-Code:
                              if (!function_exists('[name_der_funktion]'))
                                  {
                                  
                          trigger_error('Benötigte Funktionen [name_der_funktion] wurden nicht geladen!',E_USER_ERROR);
                                  } 
                          Statt trigger_error kannst hier dann eine include-Anweisung einbauen, um Deine fehlende Funktion aufzurufen.

                          Gruß

                          Merlin der Zauberer
                          www.Sternenwelt.net - Astronomie im Internet -
                          www.SternenweltForum.net - Antworten rund um die Astronomie -

                          Kommentar


                          • #14
                            KingCrunch,
                            ich weiß, dass das Benutzen der globalen Variable nicht so eine gute Idee ist, aber um mehreren Funktionen die Möglichkeit zu geben, untereinander Werte zu tauschen, ist es die einzige Möglichkeit für mich.

                            Und das zweitere: ja, ich meinte damit die Ungenauigkeit, aber wie du schon gesagt hast, spielt es keine Rolle, wenn es wo anders genau so benutzt wird und man keine genaueren Werte haben möchte, sondern Vergleiche.

                            Kommentar


                            • #15
                              Zitat von MerlinderZauberer
                              Hallo,

                              ich habe ein ähnliches Problem gehabt. Um zu prüfen, ob eine Funktion vorhanden ist, benutze ich folgendes Codeschnipsel:

                              PHP-Code:
                              <?php
                              if (!function_exists('[name_der_funktion]')) {
                                 
                              trigger_error('Benötigte Funktionen [name_der_funktion] wurden nicht geladen!',E_USER_ERROR);
                              }
                              ?>
                              Statt trigger_error kannst hier dann eine include-Anweisung einbauen, um Deine fehlende Funktion aufzurufen.

                              Gruß

                              Merlin der Zauberer
                              Also, bei mir geht das noch einfacher: load("func.beispiel");
                              PHP-Code:
                              <?php

                              function load() {
                                  static 
                              $JustLoad = array();
                                  
                              $Files func_get_args();
                                  foreach(
                              $Files as $Name) {
                                      
                              $File STDINC_PATH."/inc/".$Name.".php";
                                      if(!
                              in_array($Name$JustLoad)) {
                                          if(
                              file_exists($File) AND is_readable($File)) {
                                              
                              $JustLoad[] = $Name;
                                              
                              __load($File$Name);
                                          } else {
                                              
                              debug::ferror(
                                                  
                              "load(".varexp($Name).")",
                                                  
                              "Konnte die Datei nicht includen: ".$File
                                              
                              );
                                          }
                                      }
                                  }
                                  return 
                              TRUE;
                              }
                              function 
                              __load($__File$__Name) {
                                  
                              $__Self substr($__Namestrpos($__Name".")+1);
                                  include(
                              $__File);
                              }

                              ?>

                              Kommentar

                              Lädt...
                              X