Ext mit eigenen Klassen erweitern

  • mischa mischa
    Jedi-Meister
    0 x
    411 Beiträge
    5 Hilfreiche Beiträge
    15. 07. 2007, 22:35

    Hallo zusammen,

    mit Sicherheit wurde das Thema schon tausendmal durchgekaut und ich versinke vor Scham im Boden, dass ich selber danach fragen muss, aber ich habe einfach ein Problem mit dem Auslagern von Funktionen in externe Klassen meiner Extension.
    :o

    Was will ich machen? Ich will grundsätzlich die class.tx_meine_ext_pi1.php schlank halten und alle Funktionen, die ich brauche, in externe Klassen aufteilen. Das klappt ja auch wunderbar wunderschön, aber ein kleines Gallisches Dorf will mich unbedingt fertig machen und das ist die pibase.

    Meine "Hauptklasse"

    1. class tx_mhdialekte_pi1 extends tslib_pibase {
    2. var $prefixId = 'tx_mhdialekte_pi1';
    3. var $scriptRelPath = 'pi1/class.tx_mhdialekte_pi1.php';
    4. var $extKey = 'mh_dialekte';
    5. var $pi_checkCHash = true;
    6. ...
    7. function showList($content,$conf){
    8. $this->cObj->conf = $this->conf;
    9. $ListView = t3lib_div::makeInstanceClassName("tx_mhdialekte_list");
    10. $list = new tx_mhdialekte_list($this->cObj);
    11.  
    12. return $list->showList($cObj);
    13. }
    14.  
    15. ...
    16.  
    17. include_once($ext_path.'pi1/class.tx_mhdialekte_list.php');

    in class.tx_mhdialekte_list.php steht dann

    1. class tx_mhdialekte_list extends tx_mhdialekte_pi1 {
    2.  
    3. var $cObj;
    4.  
    5. function showList($cObj){
    6. $this->cObj = $cObj;
    7. $this->conf = $this->cObj->conf;
    8.  
    9. $select_fields = '*';
    10. $from_table = 'tx_mhdialekte_dict';
    11. $where_clause = 'word LIKE "%'.$this->piVars['suche'].'%"';
    12.  
    13.  
    14. $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='word',$limit='0,10');
    15.  
    16. while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
    17. $return .= $this->pi_linkToPage($row['word'],8,$target='',$urlParameters=array('tx_mhdialekte_pi1[word]'=>$row['uid']));
    18. }
    19. return $return;
    20. }
    21. }

    Probleme macht mir hierbei die Zeile

    1. $return .= $this->pi_linkToPage($row['word'],8,$target='',$urlParameters=array('tx_mhdialekte_pi1[word]'=>$row['uid']));

    denn hier meckert php ständig

    Fatal error: Call to a member function on a non-object in /srv/www/vhosts/dialekte.org/httpdocs/typo3/sysext/cms/tslib/class.tslib_pibase.php on line 283

    Ich habe auch schon versucht, die

    1. require_once(PATH_tslib.'class.tslib_pibase.php');
    in die Nebenklasse einzubinden - auch mit direktem Pfad zur Datei - keine Chance.

    Weiß jemand, wie ich die pi_base in der Nebenklasse zum laufen kriege?

    LG,

    Mischa.


  • Harakiri Harakiri
    Padawan
    0 x
    56 Beiträge
    0 Hilfreiche Beiträge
    16. 07. 2007, 13:04

    Wo wird denn eigentlich in "class tslib_pibase" die "var $cObj" instanziert?
    Finde das nirgendwo in der Klasse.

  • Harakiri Harakiri
    Padawan
    0 x
    56 Beiträge
    0 Hilfreiche Beiträge
    16. 07. 2007, 13:49

    Auszüge aus der PHP-Doku:

    Manchmal ist es hilfreich, auf Funktionen in Basisklassen bzw. auf Funktionen in Klassen zuzugreifen, die noch keine Instanzen haben. Dafür wird der :: Operator verwendet.

    1. class A
    2. {
    3. function example()
    4. {
    5. echo "I am the original function A::example().<br>\n";
    6. }
    7. }
    8.  
    9. class B extends A
    10. {
    11. function example()
    12. {
    13. echo "I am the redefined function B::example().<br>\n";
    14. A::example();
    15. }
    16. }
    17.  
    18. // Es gibt kein Objekt der Klasse A.
    19. // Dies wird folgendes ausgeben
    20. // I am the original function A::example().<br>
    21. A::example();
    22.  
    23. // Erstellt ein Objekt der Klasse B.
    24. $b = new B;
    25.  
    26. // Dies wird folgendes ausgeben
    27. // I am the redefined function B::example().<br>
    28. // I am the original function A::example().<br>
    29. $b->example();

    Das obige Beispiel ruft die Funktion example() der Klasse A auf. Nachdem noch kein Objekt der Klasse A existiert, können wir nicht $a->example() oder ähnliches schreiben. Stattdessen rufen wir example() als 'Klassenfunktion' auf, d.h. als Funktion der Klasse selbst, und nicht irgendein Objekt dieser Klasse.

    Es gibt Klassenfunktionen, aber keine Klassenvariablen. Tatsächlich gibt es zur Zeit des Aufrufs kein Objekt. Deshalb darf eine Klassenfunktion keine Objektvariablen benutzen (aber sie kann lokale und globale Variablen verwenden), und sie darf $this ebenfalls nicht benutzen.

    In dem obigen Beispiel definiert Klasse B die Funktion example() neu. Die ursprüngliche Definition in Klasse A ist überschattet und nicht länger verfügbar, außer Sie verweisen mittels des ::-Operators speziell auf example() in Klasse A. Schreiben Sie A::example(), um dies zu tun (Tatsächlich sollten Sie parent::example() schreiben, wie im nächsten Abschnitt beschrieben).

    In diesem Kontext besteht ein Objekt, das Objektvariablen haben kann. Deshalb können Sie auch $this und Objektvariablen verwenden, wenn sie von innerhalb einer Objektfunktion verwendet werden.

  • mischa mischa
    Jedi-Meister
    0 x
    411 Beiträge
    5 Hilfreiche Beiträge
    16. 07. 2007, 21:19

    Danke für die Antworten.

    Problem ist wohl, dass in der Subklasse, die ich selber erzeuge, die Variable cObj nicht vorhanden ist. Die muss - leider - über den Funktionsaufruf übergeben werden. Dann kann in der Subklasse die pi_base auch wieder instantiiert werden. (oder so). Ist zwar nicht gerade komfortabel, aber wenn man es weiß!!

    also müsste der passende Teil meines Codes lauten:

    1. return $list->showList($this->cObj);

    (habe nur das $this-> vergessen. Dann hats geklappt.

    LG,

    Mischa.

  • Harakiri Harakiri
    Padawan
    0 x
    56 Beiträge
    0 Hilfreiche Beiträge
    17. 07. 2007, 08:40

    Eine andere Möglichkeit wäre m.M.n. noch die ext-Klassen alle von tslib_pibase abzuleiten.

  • steffenk steffenk
    Obi-Wan Kenobi
    0 x
    4666 Beiträge
    0 Hilfreiche Beiträge
    17. 07. 2007, 12:29

    oder man macht in der Hauptklasse eine Funktion, die die entsprechenden Objekte liefert

    1. function getCobj() { return $this->cObj; }
    2. function getPibase() { return $this; }

  • Knalltuete Knalltuet...
    Sternenflotten-Admiral
    0 x
    169 Beiträge
    0 Hilfreiche Beiträge
    17. 07. 2007, 23:03

    Ich versuche momentan auch eine klasse a mit der klasse b zu erweitern.. irgendwie bekomme ich es aber auch nicht hin.

    1. function getCobj() { return $this->cObj; }
    2. function getPibase() { return $this; }

    Wie muss ich das einbinden?

    Muss ich für die Klasse b extends benutzen?
    Wie macht man das denn sauber.. ich hab gestern den ganzen abend gelesen, jedoch keine lösung gefunden.

    vielleicht kann einer von euch mir helfen!
    momentan sieht mein code ungefaehr genauso aus wie der vom mischa..

    mfg tueti

  • steffenk steffenk
    Obi-Wan Kenobi
    0 x
    4666 Beiträge
    0 Hilfreiche Beiträge
    17. 07. 2007, 23:21

    es gibt immer mehrere Möglichkeiten, hier z.b. eine:

    1. require_once(t3lib_extMgm::extPath('my_ext').'lib/class.tx_myext_views.php');
    2.  
    3. class tx_myext_pi1 extends tslib_pibase {
    4. ...
    5. $b = t3lib_div::makeInstance('tx_myext_views');
    6. $b->init($this,$this->conf);
    7. ...
    8.  
    9. function doIt() {
    10.  
    11. }
    12. }
    13.  
    14. class tx_myext_views {
    15.  
    16. function init(&$conf,&$pibase) {
    17. $this->conf = $conf;
    18. $this->pibase = $pibase;
    19. }
    20. ...
    21. }

    Das ist eine einfache Methode eine weitere Klasse einzubinden und ihr das Hauptobjekt pibase mitzugeben.

    Die Funktionen der Hauptklasse erreicht man dann so:

    1. $a = $this->pibase-doIt();

    Die pi1-Klasse zu erweitern macht keinen Sinn, diese ist eine Erweiterung der tslib_pibase. Dies aus dem Grund, damit man die Objekte der tslib_pibase zur Verfügung hat. Es ist also viel leichter, diese Objekte durchzureichen.

  • Knalltuete Knalltuet...
    Sternenflotten-Admiral
    0 x
    169 Beiträge
    0 Hilfreiche Beiträge
    17. 07. 2007, 23:43

    okaii.. irgendwie steh ich auf schlauch!

    was macht diese funktion:

    1. function init(&$conf,&$pibase) {
    2. $this->conf = $conf;
    3. $this->pibase = $pibase;
    4. }

    und wie kann ich dann aus der hauptklasse a eine funktion aus der unterklasse b ansprechen? zb.

    1. function getFile($file,$errormsg) {
    2. if (!$this->cObj->fileResource($file)) ;//echo $this->errorwrap($errormsg);
    3. else return $this->cObj->fileResource($file);
    4. }

  • steffenk steffenk
    Obi-Wan Kenobi
    0 x
    4666 Beiträge
    0 Hilfreiche Beiträge
    17. 07. 2007, 23:48

    die init dient der Weitergabe der Objekte, die Hauptklasse macht folgendes:

    1. einbinden (require_once)
    2. instanzieren ($b = t3lib_div::makeInstance('tx_myext_views');)
    3. conf und pibase übergeben ($b->init($this->conf,$this);)

    Und im 3. Schritt siehst Du auch, wie man aus der Hauptklasse auf die eingebundene zugreift. Ist dort also Deine Funktion getFile, so rufst Du sie so auf:

    1. $b->getFile(...);

    PS ich hatte die Reihenfolge der Parameter oben verdreht, aber sollte offensichtlich sein.