Anzeige:
Ergebnis 1 bis 11 von 11

Thema: Funktionsname aus Variableninhalt generieren

  1. #1
    Registrierter Benutzer
    Registriert seit
    30.12.2002
    Ort
    Tübingen
    Beiträge
    20

    Funktionsname aus Variableninhalt generieren

    Hallo,

    entwickle momentan eine webbasierte medizinische Datenbank.

    Als Datenbank-Abstraktions-Layer kommt Propel zum Einsatz, zur Darstellung der Daten im Browser setze ich auf extjs.

    Zum Abwickeln der Datenbankanfragen von extjs an Propel entwickle ich gerade einen 'dataproxy', der die POST-Daten von extjs auswertet, dementsprechend eine DB-Anfrage an Propel stellt und die Daten in entsprechender Form aufbereitet wieder zurücksendet.

    Spezifisch auf einen speziellen Fall bezogen, funktioniert das soweit auch wunderbar, nun will ich aber diesen Dataproxy soweit abstrahieren, dass ich nicht für jede mögliche Anfrage- und Sortiermöglichkeit das entsprechende Gegenstück abbilden muss, sondern dieses durch eine entsprechende Generalisierung selbst geschieht.

    Konkret bedeutet das: Fallspezifisch habe ich beispielsweise folgenden Code in meinem Dataproxy:
    Code:
    if(!is_null($_POST['dir'])){
        if($_POST['dir']=="ASC"){
            $crit->addAscendingOrderByColumn(PatientenPeer::VORNAME);
        }
        else {
            $crit->addDescendingOrderByColumn(PatientenPeer::VORNAME);
        }
    }
    Dieses Vorgehen würde bedeuten, ich muss für jede Spalte und jede Sortierrichtung alle Fälle abdecken und ein gewaltiges Konstrukt bauen, dass alle diese Fälle abdeckt.

    Meine Idee war es nun, VORNAME durch das entsprechende POST-Feld (ich weiß, ich sollte an dieser Stelle auf SQL-Injection-Probleme achten...) zu ersetzen, so dass z.B.:
    Code:
    $crit->addDescendingOrderByColumn(PatientenPeer::strtoupper($_POST['sort']));
    aufgerufen wird und ich obiges Konstrukt in wenigen Zeilen für alle vorhandenen Tabellen anwenden kann.

    Da bei dieser Schreibweise aber $_POST als String-Konstante ausgewertet wird, musste ich hier einen kleinen Umweg über Variablen-Funktionen gehen:
    Code:
    $tmpvar=strtoupper($_POST['sort']);
    $crit->addDescendingOrderByColumn(PatientenPeer::$tmpvar());
    Theoretisch funktioniert dieser Weg auch, dummerweise scheint PHP aus dem eigentlich kompletten UPPERCASE-String einen kompletten lowercase-String zu machen:
    Code:
    Call to undefined method PatientenPeer::vorname()
    Folgendes hart kodiertes Beispiel verdeutlicht das:
    Code:
    $tmpvar="VORNAME";
    $crit->addAscendingOrderByColumn(PatientenPeer::$tmpvar());
    Auch hier sieht das Ergebnis wieder so aus:
    Code:
    Call to undefined method PatientenPeer::vorname()
    Mit folgendem kurzem Codebeispiel konnte ich das Verhalten nicht reproduzieren:
    Code:
    <?php
        class TestClass{
                public function TEST(){
                echo "Hallo Welt";
            }
        }
        $tmpvar="TEST";
        TestClass::$tmpvar();
    ?>
    Weiß jemand, was hier schief läuft? Hat jemand andere Ansätze zu dem Problem oder eine Lösung, warum der Uppercase-String zu Lowercase umgewandelt wird?

    Vielen Dank & Gruß,

    Elias P.
    Geändert von EliasP (08-01-2008 um 15:27 Uhr)

  2. #2
    Registrierter Benutzer
    Registriert seit
    19.12.2006
    Beiträge
    13
    Probier ma die Funktion so aufzurufen:

    call_user_func(array("TestClass", $tmpvar));

    sollte funktionieren, solange die Methode TEST public ist.

  3. #3
    Registrierter Benutzer
    Registriert seit
    30.12.2002
    Ort
    Tübingen
    Beiträge
    20
    Jetzt scheint die Funktion schonmal korrekt aufgerufen zu werden, aber es schlägt trotzdem noch fehl:
    Der Fehler muss aber in diesem Aufruf liegen, denn der selbe Code mit testweise hartgecodeten Werten läuft.
    Hat noch jmd eine Idee?
    Code:
    PHP Warning:  call_user_func(PatientenPeer::VORNAME): First argument is expected to be a valid callback in /raid/www/htdocs/DokuArchiv/data/dataproxy.php on line 22
    PHP Fatal error:  Uncaught exception 'PropelException' with message ' [wrapped: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ASC LIMIT 3' at line 1]' in /usr/share/php5/PEAR/propel/util/BasePeer.php:464
    Stack trace:
    #0 /raid/www/htdocs/DokuArchiv/build/classes/dokuarchiv/om/BasePatientenPeer.php(269): BasePeer::doSelect(Object(Criteria), Object(PropelPDO))
    #1 /raid/www/htdocs/DokuArchiv/build/classes/dokuarchiv/om/BasePatientenPeer.php(239): BasePatientenPeer::doSelectStmt(Object(Criteria), NULL)
    #2 /raid/www/htdocs/DokuArchiv/data/dataproxy.php(28): BasePatientenPeer::doSelect(Object(Criteria))
    #3 {main}
      thrown in /usr/share/php5/PEAR/propel/util/BasePeer.php on line 464

  4. #4
    Registrierter Benutzer
    Registriert seit
    26.12.2001
    Ort
    CH
    Beiträge
    122
    Ist das Problem nicht die Klammern hinter dem Variablenaufruf (rot markiert)? Du willst ja nur den Variableninhalt und nicht eine Funktion aufrufen oder versteh ich das falsch?

    Folgendes hart kodiertes Beispiel verdeutlicht das:
    Code:
    Code:
    $tmpvar="VORNAME";
    $crit->addAscendingOrderByColumn(PatientenPeer::$tmpvar());
    Auch hier sieht das Ergebnis wieder so aus:
    Code:
    Code:
    Call to undefined method PatientenPeer::vorname()
    I never saw my PC smiling before - LINUX

  5. #5
    Registrierter Benutzer
    Registriert seit
    30.12.2002
    Ort
    Tübingen
    Beiträge
    20
    Zitat Zitat von magpie Beitrag anzeigen
    Ist das Problem nicht die Klammern hinter dem Variablenaufruf (rot markiert)? Du willst ja nur den Variableninhalt und nicht eine Funktion aufrufen oder versteh ich das falsch?
    Das hatte ich zuerst auch gedacht. Dieses Vorgehen liefert aber eine Meldung wie:
    Code:
    PHP Fatal error:  Access to undeclared static property:  PatientenPeer::$tmpvar in /raid/www/htdocs/DokuArchiv/data/dataproxy.php on line 21
    Die PHP-Dokumentation zu Variable-Funktionen hat mir hier aber weitergeholfen, bzw. mich auf eine andere Fährte gelockt. Demnach wäre die Schreibweise mit Klammern korrekt und in einem klassenlosen Testcode funktioniert das auch wunderbar.

    Nur eben nicht, sobald ich es mache wie oben beschrieben.

  6. #6
    Registrierter Benutzer
    Registriert seit
    19.12.2006
    Beiträge
    13
    Wie genau hast du denn die Funktion samt Parametern denn aufgerufen?

    Laut call_user_func, ist das erste Argument die Callback Funktion und die folgenden sind die Parameter zur Callback Funktion also in deinem fall:

    call_user_func(array($klasse, $method), $arg1, $arg2);

    Falls ich dein Problem jetzt richtig verstanden hab ^^

  7. #7
    Registrierter Benutzer
    Registriert seit
    30.12.2002
    Ort
    Tübingen
    Beiträge
    20
    Die Funktion ist parameterlos, habe sie so aufgerufen:

    Code:
    $crit->addAscendingOrderByColumn(call_user_func(array("PatientenPeer", strtoupper($_POST['sort']))));
    auch mit hart gecodeten Werten hat es nicht funktioniert:
    Code:
    $crit->addAscendingOrderByColumn(call_user_func(array("PatientenPeer", "VORNAME")));
    Das entspricht also deinen Vorgaben.
    Mein ersteres Problem, dass der Funktionsname bei der Verwendung von Variablen-Funktionen klein geschrieben wird, sieht für mich nach einem PHP-Bug aus.

  8. #8
    Registrierter Benutzer
    Registriert seit
    11.01.2006
    Beiträge
    103
    hast du es schonmal mit eval() probiert?
    Code:
    eval("Classname::".$function_name."();");

  9. #9
    Registrierter Benutzer
    Registriert seit
    30.12.2002
    Ort
    Tübingen
    Beiträge
    20
    Zitat Zitat von inge Beitrag anzeigen
    hast du es schonmal mit eval() probiert?
    Code:
    eval("Classname::".$function_name."();");
    Hab es jetzt mal ausprobiert, aber auch hier wird aus meinem Uppercase-String ein Lowercase-Funktionsname gemacht:
    Code:
    PHP Fatal error:  Call to undefined method PatientenPeer::vorname() in /raid/www/htdocs/DokuArchiv/data/dataproxy.php(30) : eval()'d code on line 1

  10. #10
    Registrierter Benutzer Avatar von undefined
    Registriert seit
    01.03.2004
    Beiträge
    1.255
    Auch wenn es mir wiederstrebt, befasse dich lieber mit __get() __set()
    PHP-Code:

    class PatientenPeer
    {
      static public function 
    MeineFunktion()
      {
        return 
    "ICH:" __METHOD__;
      }
    }

    $tmpvar "MeineFunktion";
    if (
    method_exists(new PatientenPeer,$tmpvar))
      echo 
    PatientenPeer::$tmpvar(); 
    mfg undefined
    --
    Undefined Behavior (undefiniertes Verhalten) bedeutet meistens etwas ungültiges.
    xhtml Debugger

  11. #11
    Registrierter Benutzer
    Registriert seit
    30.12.2002
    Ort
    Tübingen
    Beiträge
    20
    Zitat Zitat von undefined Beitrag anzeigen
    Auch wenn es mir wiederstrebt, befasse dich lieber mit __get() __set()
    PHP-Code:

    class PatientenPeer
    {
      static public function 
    MeineFunktion()
      {
        return 
    "ICH:" __METHOD__;
      }
    }

    $tmpvar "MeineFunktion";
    if (
    method_exists(new PatientenPeer,$tmpvar))
      echo 
    PatientenPeer::$tmpvar(); 
    Hmm, ein anderer Ansatz das Problem zu lösen ist mir natürlich sehr willkommen. Kannst du mir noch nen etwas größeren Schubs in die richtige Richtung geben? Verstehe nicht wirklich, was du mir damit sagen willst.

    Eine Modifikation der Peer Methoden wird etwas komplizierter werden, da diese Aufgrund des bestehenden DB-Schemas von Propel generiert werden.

    Meines Wissens ist es aber auch möglich, den Build-Prozess anzupassen und dort einzugreifen. Aber vielleicht willst du mir ja auch was ganz anderes sagen

    Danke & Gruß

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •