My book recommendations

TYPO3 und AJAX – Wie geht das?

Achtung: Das Tutorial ist nun auf typo3-tutorials.org zu finden! Kommentare bitte dort schreiben !

Dieses Tutorial soll euch eine kleine Einführung geben, wie man AJAX zusammen mit TYPO3 am besten nutzen kann!
Dazu werden wir das Javascript Framework jQuery verwenden. Selbstverständlich kann man auch jedes andere Framework verwenden was eine AJAX API anbietet.

Grundlegend gibt es bei TYPO3 zwei verschiedene Wege im Frontend und einen im Backend über die man einen AJAX Request absetzen kann.
Da wäre im Frontend einmal der so genannte typeNum, wo man per GET Parameter den entsprechenen type mit übermittelt, und zum anderen gibt es den sogenannten eID Mechanismus. Ich werde zu beiden Wegen ein kleines Beispiel zeigen. Im Backend gibt es den Weg über die ajaxID. Dazu werde ich ganz zum Schluß noch ein paar Worte sagen!

Beginnen wir aber erst mit dem Frontend und mit den Grundlagen die beide Wege die ich genannt hatte benötigen.
Bedeutet, wir müssen erst einmal das jQuery Framework einbinden um eine entsprechende AJAX API nutzen zu können. Hierzu verwende ich immer folgendes Script:

jQuerySrc = 'fileadmin/js/jquery-min.js';

// only load jQuery if not present
if (typeof jQuery == 'undefined')  {
    document.write("<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">");
}

// if Google is down
if (typeof jQuery == 'undefined') {
    document.write("</script><script type="text/javascript" src="" + jQuerySrc + "">");
}

Was passiert hier:
Es wird überprüft ob jQuery schon eingebunden wurde. Es kann ja sein das per TypoScript oder einer anderen Extension das jQuery Framework schon in die Seite eingebunden ist und doppelt wollen wir es ja nicht haben. Wenn jQuery also noch nicht eingebunden wurde wird es von der Google API geholt. Sollte die Google API einmal down sein, was zu 99,99% nie der fall sein sollte,  überprüft eine weitere Bedingung erneut ob jQuery eingebunden wurde. Ist die Google API also mal down, lachen wir google erstmal kurz aus und lehnen uns wieder entspannt zurück, den es wird dann unsere lokale Version eingebunden. Ihr müsst dazu natürlich die jQuerySrc Variable entsprechend anpassen.

Soweit so gut, Grundstein ist gelegt, für Kaffee ist gesorgt, oder ? :-) Weiter gehts…

In unserem Beispiel gehen wir davon aus das ein Klick auf einen Button, der die id “triggerButton” als Attribut hat, den AJAX Request auslöst (der sogenannte Trigger – Auslöser).

In jQuery kann das so aussehen:

$('#triggerButton').bind('click', function() {
    // mache was
});

Sehr gut, Putzlappen raus, jetzt kommt AJAX zum Einsatz :-)
Innerhalb des click Events kommt jetzt unser AJAX Request rein der wie folgt aussehen kann

$.ajax({
    url: '',
    success: function(data) {

    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {

    }
});

Das ist ein Aufruf mit grundlegenden Einstellungen, hier gibt es natürlich noch weitere Einstellungen um den Rückgabetyp zu definieren und und und, hier einfach mal in die AJAX API von jQuery schauen.

Die “url” erkläre ich gleich da hier die zwei unterschiedlichen Wege zum Einsatz kommen.
“success” wird aufgerufen wenn der Call erfolgreich war und “error” sofern ein Fehler aufgetreten ist! Beides sind funktionen in denen man dann entsprechende Aktionen auslösen kann!

Ok, fangen wir mit dem ersten Weg an:

Der typeNum!

Der typeNum sollte uns schon etwas sagen, den unsere Webseite basiert auf dem typeNum 0. 0 Ist dabei der default typeNum.
Gibt der user also die Domain euerer Webseite ein und gibt keinen “type” als GET Parameter ein, wird der default typeNum 0 genommen.
Das TypoScript sieht in den meisten Fällen so aus

[typoscript]page = PAGE
page.typeNum = 0
page.bodyTag = <body>

page.10 = TEMPLATE
page.10.template = FILE
page.10.template.file = fileadmin/index.html
page.10.workOnSubpart = DOCUMENT

page.10 {
subparts {
CONTENT < styles.content.get
}

# usw
} [/typoscript]

Ok, also, wir können also beliebig viele weitere typeNums definieren, diese müssen halt nur einmalig sein, da der letzte sonst immer gewinnen würde. Ihr kennt das Prinzip, TypoScript wird von oben nach unten eingelesen und wenn ihr Definitionen doppelt drin habt gewinnt immer der letzte!

Wunderbar, wir wollen also einen typNum definieren den wir für unsere AJAX Anfrage nutzen. Also, tragen wir folgendes im TypoScript Setup ein:

[typoscript]ajaxCall = PAGE
ajaxCall {
typeNum = 5000
10 < plugin.tx_unsereextension_pi1

config {
disableAllHeaderCode = 1
xhtml_cleaning = 0
admPanel = 0
debug = 0
no_cache = 1
}
}[/typoscript]

[Setzt voraus wir haben eine Extension “unsereextension” die installiert ist. Das kann eine recht einfache über den Kickstarter erstellte Extension sein die mindestens eine pi1 enthält]

Das TypoScript bewirkt das, wenn wir eine URL mit dem type=5000 aufrufen, das sofort an das Plugin tx_unsereextension_pi1 weitergeleitet wird und das was dort als return zurück kommt ausgegeben wird. Im Bereich config stellen wir noch ein paar Feinheiten ein, wie zB disableAllHeaderCode = 1 was bewirkt das wir unser Ergebnis als reinen Plaintext wieder bekommen ohne das der von TYPO3 generierte HTML Header etc. mit ausgegeben wird. Da wir auch keine anderen Ausgaben haben wollen deaktivieren wir auch das adminPanel und die debug Ausgabe und deaktivieren das Caching.

In unserer Extension steht aktuell folgendes in der main Methode
typo3conf/ext/unsereextension/pi1/class.tx_unsereextension_pi1.php

// ...

public function main($content, $conf) {
    return 'Das ist ein Test!';
}

// ...

Um vorab einmal zu testen ob unser neu angelegter typeNum funktioniert rufen wir das ganze manuell auf. Gebt also euere Domain + den neuen type als GET Parameter an: http://www.domain.de/?type=5000

Als Ausgabe müssten wir jetzt sehen “Das ist ein Test!” und wenn wir in den Quellcode der Seite gucken dürfte dort auch KEIN HTML Tag etc. stehen sondern nur der reine Plaintext.

Sollte das nicht funktieren stellt bitte sicher ob ihr den Frontend Cache geleert habt :-) Ein häufiger Fehler wenn man nicht mit dem Template Modul arbeitet. Im Template Modul passiert das nämlich automatisch.

Aber wir gehen davon aus das alles geklappt hat und kümmern uns jetzt um das AJAX
Im AJAX Call tragen wir also in der “url” folgendes ein

$.ajax({
    url: '/?type=5000',
    success: function(result) {
        alert(result);
    },
});

Wenn jetzt auf den Button geklickt wird den wir als Trigger nutzen, müsste ein Alert erscheinen in dem steht: Das ist ein Test!
Ich würde sagen, glückwunsch! Ihr habt es geschafft!
Jetzt könnt Ihr mit jQuery das Ergebnis entsprechend verarbeiten.

Dem AJAX Call kann man natürlich auch noch Daten mit übergeben damit, anhand dieser Daten kann man im AJAX Script bestimmte Aktionen durchgeführen lassen!
Nehmen wir also an ihr wollt die FE User ID eines eingeloggten Users mit übergeben

var useruid = 1; // müsste dann dynamisch gefüllt werden

$.ajax({
    url: '/?type=5000',
    data: 'useruid=' + useruid,
    success: function(result) {
        alert(result);
    },
});

Der Aufruf sieht jetzt aber wie folgt aus: http://www.domain.de/?type=5000&useruid=X
Dementsprechend könnt ihr in euerem AJAX Script auf den GET Parameter zugreifen!

Möchte man die Extension mit mehreren verschiedenen typNums nutzen kann man in der Extension einfach folgendes machen

switch ($GLOBALS['TSFE']->type) {
  case 5000: // fuer typeNum 5000
    break;
  case 5001: // fuer typeNum 5001
    break;
  // usw
}

Der Vorteil bei dem Weg über typeNum ist das uns alle globalen Variablen wie das komplette TSFE mit cObj etc. zur Verfügung stehen. Bei dem Weg per eID musste man vor der TYPO3 Version 4.3 noch ein eigenes TSFE Objekt erzeugen. Seit der 4.3 bietet das das eID Script aber an womit wir direkt zum zweiten Weg kommen!

eID steht für Extension ID

Der eID Mechanismus ist  seit der Version 4.0 dabei!

Angesprochen wird er über einen GET oder POST Parameter. Sobald also eID als Parameter in der URL vorhanden ist, zB. www.domain.de/?eID=schuesselwort, wird der normale Prozess sehr früh abgebrochen und auf ein Script weitergeleitet was von uns vorher registriert wurde. Da der normale Prozess so früh abgebrochen wird kommt es auch noch zu keiner Ausgabe. Es wird nichts gecachet und kein HeaderCode etc. generiert. Wir bekommen also ein blankes Ergebnis unserer main Methode ausgegeben.

Wollen wir uns einmal die index_ts.php (typo3/sysext/cms/tslib/) Zeile 174 bis 185 ansehen.

// *********************
// Look for extension ID which will launch alternative output engine
// *********************
if ($temp_extId = t3lib_div::_GP('eID')) {
    if ($classPath = t3lib_div::getFileAbsFileName($TYPO3_CONF_VARS['FE']['eID_include'][$temp_extId])) {
        // Remove any output produced until now
        ob_clean();
        require($classPath);
    }
    exit;
}

Hier wird überprüft ob es einen GET bzw POST Parameter mit dem Namen eID gibt, sofern vorhanden wird geguckt ob dieser Key registriert wurde und der Pfad zu unserem Script wird in $classPath gespeichert und per require eingebunden. Danach folgt ein exit damit der restliche Prozess von TYPO3 nicht mehr ausgeführt wird.

Wie genau können wir unser Script registrieren ?

Das sagen wir dem System über $TYPO3_CONF_VARS[‘FE’][‘eID_include’][$temp_extId]
Wir müssten entweder in die localconf.php oder in eine ext_localconf.php einer Extension folgendes Eintragen

$TYPO3_CONF_VARS['FE']['eID_include']['helloworld'] = 'EXT:meinExtKey/meinScript.php';

Steht jetzt also in der Adresse www.domain.de/?eID=helloworld geht er in die erste if Abfrage und sieht das
$TYPO3_CONF_VARS[‘FE’][‘eID_include’][$temp_extId] vorhanden ist und speichert ‘EXT:meinExtKey/meinScript.php’ in die Variable $classPath und includiert unser Script.

Da unser Script noch leer ist bekommen wir eine weiße Seite angezeigt in der auch der komplette Quelltext leer ist.

Damit wir auch ein FE User Objekt, das TSFE Objekt und eine Datenbank Verbindung zur Verfügung haben, geben wir folgendes ein

$feUserObject = tslib_eidtools::initFeUser();
$TSFEObject = tslib_eidtools::getTSFE();

Die erste Zeile initialisert den Frontent User und gibt uns diesen als Objekt zurück. Dabei wird auch eine Verbindung zur Datenbank hergestellt.
Um jetzt noch das komplette TSFE zur Verfügung zu haben rufen wir in der zweiten Zeile die getTSFE Methode auf.
Im Weiteren können wir ganz normal auch TYPO3 Funktionalitäten benutzen und eine entsprechende Rückgabe an unseren AJAX Request geben.

Möchten wir zB explizit JSON als Format zurückgeben können wir im AJAX Call einen dataType definieren und im PHP einfach json_encode($content); zurück geben. Damit kann man in der success Funktion dann auf das JSON Objekt zugreifen. Beispiel:

$.ajax({
    url: '/?eID=helloworld',
    dataType: 'json',
    success: function(result) {
        alert('Hello ' + result.myResult);
    },
});

class unsereKlasse {

    public function main() {
        $feUserObject = tslib_eidtools::initFeUser();
        $TSFEObject = tslib_eidtools::getTSFE();
        return json_encode(array('myResult' => 'World'));
    }

}

$output = t3lib_div::makeInstance('unsereKlasse');
echo $output->main();

Das war es soweit zum Frontend. Kommen wir noch zum Backend, hier hatte ich ja gesagt das es einen Weg per ajaxID gibt.
Machen wir es kurz und schmerzlos :-)

Ihr habt eine Extension in der wir in die ext_localconf.php folgendes eintragen

$TYPO3_CONF_VARS['BE']['AJAX']['tx_extkey::helloworld'] = t3lib_extMgm::extPath($_EXTKEY) . 'classes/class.tx_extkey_helloworld_ajax.php:tx_extkey_helloworld_ajax->sayHello';

OHA, was ist das 😉 Gang einfach, ich schreibe es nochmal so

$TYPO3_CONF_VARS['BE']['AJAX']['tx_extkey::key'] = 'pfad/datei.php:klassenname->methodenname';

Ich denke jetzt ist es verständlicher und bedarf keiner weiteren Worte :-) oder doch ? Ok!
In unserer Datei class.tx_extkey_helloworld_ajax.php die im Ordner classes liegt gibt es also eine Klasse mit dem Namen tx_extkey_helloworld_ajax in der eine
Methode sayHello ist.

Mit dieser Zeile haben wir unser AJAX Script erstmal registriert!
Ein Aufruf aus einem Modul etc. ist jetzt relativ einfach

$url = $this->doc->backPath . 'ajax.php?ajaxID=tx_extkey::helloworld';

Diese Url ruft Ihr jetzt per AJAX API über jQuery oder extJS (seit 4.3 fest im Core) auf. Dabei wird dann die oben gannten Klasse->Methode aufgerufen und liefert das Ergebnis der Methode zurück.

So, der Kaffee ist leer und somit auch das Tutorial zu ende! Ich hoffe ich konnte euch einen kleinen grundlegenden Einstieg verschaffen. Wenn Ihr noch Fragen, Anregungen, Lob oder Kritik habt, nutzt bitte die Kommentarfunktion!

Cheers und bis zum nächsten mal,
Julian

Achtung: Das Tutorial ist nun auf typo3-tutorials.org zu finden! Kommentare bitte dort schreiben !

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn
  • Pingback: t3n.de/socialnews()

  • Pingback: Julian Kleinhans()

  • Danke für die ausführliche Anleitung. Schön wärs, wenn mehr solcher Tutorials auf typo3.org zu finden wären.

  • Pingback: Julian Kleinhans()

  • Manschich

    Super Tutorial!

  • Vielen Dank für die tolle Beschreibung, hat auf Anhieb geklappt.

  • Schreiber

    Sehr gutes Tutorial. Großes Lob. In einer Extension verwende ich die typenum Variante. Ich habe das Problem, dass ich weder auf Flexform-Werte noch auf Typoscript Konfigurationen aus dem setup zugreifen kann. Das liegt wahrscheinlich in der Natur der Sache, aber weißt du zufällig von einer Möglichkeit, doch an individuelle Konfigurationen zu kommen, ohne die Werte durch die ganze Anwendung schleifen zu müssen?

  • Schreiber

    Hat sich erledigt: man muss natürlich die TS Konfigurationen für das neue Page Objekt anlegen und nicht für das Plugin im Allgemeinen. Was die Flexform anbelangt, so wird halt die Root-Seite aufgerufen und nicht die Seite auf der die Flexform liegt.

  • Die folgende Scriptzeile

    $TSFEObject = tslib_eidtools::getTSFE();

    ergibt folgende Fehlermeldung: “Fatal error: Call to private method tslib_eidtools::getTSFE() from context ” in…

    Wie lässt sich das vermeiden??

    Danke für Feedback
    Axel

  • chris

    Ich schließe mich dem Kommentar von axel an, bei mir kommt die selbe Fehlermeldung! Welche Lösung gibt es da!

  • chris

    Moin Alex!
    Die Fehlermeldung muss kommen. In der Klasse tslib_eidtools ist die Funktion als “private” registriert. Ich habe aber gesehen, dass in der Funktion “initFeUser” die private Funktion “getTSFE” aufgerufen wird. Du hast nun zwei Möglichkeiten. Entweder du deklarierst die Funktion “getTSFE” in der Klasse tslib_eidtools als public oder du schreibst du Funktion initFeUser etwas um. Ersetze dort den return-Wert indem du das komplette Array zurück gibst und nicht nur den Wert fe_user des Arrays. Ich habe letztere Möglichkeit genutzt und nun lautet die Zeile mit dem return bei mir wie folgt:
    return $tsfe;

  • We have go through your blog for a few day, love the idea!

  • Pingback: Marc Schneider()

  • Pingback: Tobias Liegl()

  • Great post! I really enjoyed it.

  • Hallo. Dies ist ein sehr hilfreicher Beitrag. Ich muss ja in der localconf die Php Datei registrieren. Kann ich auch direkt auf eine Funktion in meiner Extension zugreifen anstelle auf eine externe Php Datei? Weil sonst hab ich einmal eine Datenbankabfrage in meiner Extension und einmal in der ext Php Datei.

  • Sehr hilfreich und gut strukturiert. Danke Julian!
    Gruß, Jörg.

  • Martin Klauer

    Danke, super tutorial!

  • SK

    Hi, ich muss nochmal fragen. Kann ich auch fürs Frontend eine Methode in einer Klasse aufrufen. Ich habe zum Beispiel die Klasse tx_tl24_pi1 und da drin befindet sich die Methode subs(). Wie kann ich die aufrufen. Für Backend geht es ja mit:

    $TYPO3_CONF_VARS[‘BE’][‘AJAX’][‘tx_extkey::helloworld’] = t3lib_extMgm::extPath($_EXTKEY) . ‘classes/class.tx_extkey_helloworld_ajax.php:tx_extkey_helloworld_ajax->sayHello’;

    Gibt es diese Möglichkeit nicht auch fürs Frontend. Deine Variante hier ruft ja eine Php Datei auf. Ich möchte aber gezielt eine Methode aufrufen.

    Hat einer ne Idee?

    Danke

  • SK

    Halloooo? Jemand hier?

    typo3conf/ext/unsereextension/pi1/class.tx_unsereextension_pi1.php

    Ich möchte gerne einen Ajax Aufruf auf eine Funktion/Methode in der obigen Php Datei erstellen. Ich bekomme es aber einfach nicht registriert in der ext_localconf. Hat hier einer eine Idee was ich noch probieren könnte?

  • Pingback: Michael T Wolfinger()

  • Freak
  • Pingback: fabi()

  • Get up to 100000 forum backlinks with our backlinks service & massive targeted traffic Get great web traffic using best backlink service available. We can post your marketing post up to 100’000 forums around the web, get insane amount of backlinks and great targeted web traffic in shortest time. Most affordable and most powerful service for web traffic and backlinks in the world!!!! Your post will be published up to 100000 forums worldwide your website or blog will get instant traffic and massive increase in seo rankings just after few days or weeks so your site will get targeted long term traffic from search engines. Order now: backlinks

  • Thank you for the tutorial, my German is not perfect but I could understand what is covered in the text. Vielen Dank!

  • Chris

    I wrote an tutorial for FLOW3 Ajax ViewHelpers, you can find it here: http://blog.blubyte.de/2012/07/flow3-how-to-ajax-viewhelper-using-jquery/

  • alex

    Hab das Problem das ich von der Extension $_GET nich die ajax(data) bekomme. :(