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

  • GelaMu
    hat ein Thema erstellt etwas ähnliches wie __autoload() für Funktionen.

    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!

  • GelaMu
    antwortet
    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);
    }

    ?>

    Einen Kommentar schreiben:


  • GelaMu
    antwortet
    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.

    Einen Kommentar schreiben:


  • MerlinderZauberer
    antwortet
    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

    Einen Kommentar schreiben:


  • KingCrunch
    antwortet
    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

    Einen Kommentar schreiben:


  • GelaMu
    antwortet
    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...

    Einen Kommentar schreiben:


  • KingCrunch
    antwortet
    Laptop Aber die Aussage bleibt die selbe

    Einen Kommentar schreiben:


  • Zergling-new
    antwortet
    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

    Einen Kommentar schreiben:


  • KingCrunch
    antwortet
    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

    Einen Kommentar schreiben:


  • Zergling-new
    antwortet
    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.

    Einen Kommentar schreiben:


  • squig
    antwortet
    Hola,

    was ist mit der Verwendung von __call?


    Bis dääähne.

    Einen Kommentar schreiben:


  • GelaMu
    antwortet
    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

    Einen Kommentar schreiben:


  • pepe24
    antwortet
    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ß

    Einen Kommentar schreiben:


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

    Einen Kommentar schreiben:


  • pepe24
    antwortet
    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ß

    Einen Kommentar schreiben:

Lädt...
X