Ich entwickle eine benutzerdefinierte Komponente für Joomla! 3.x und möchten einen AJAX-Aufruf ausführen, um einige Daten abzurufen. Was ist der richtige Weg, um es zu tun?
Ich entwickle eine benutzerdefinierte Komponente für Joomla! 3.x und möchten einen AJAX-Aufruf ausführen, um einige Daten abzurufen. Was ist der richtige Weg, um es zu tun?
Antworten:
BITTE BEACHTEN SIE, DASS DIESE ANTWORT bereits einige Jahre alt ist und nicht aktualisiert wurde. Fühlen Sie sich frei zu bearbeiten / kommentieren, wenn Sie denken, dass etwas nicht mehr genau ist.
Es gibt praktisch keine offizielle Möglichkeit, damit umzugehen. Dies hängt stark von der Komplexität ab und davon, wie sehr Sie sich bei der Ausführung der Arbeit auf das MVC-Muster verlassen möchten.
Nachfolgend sind einige mögliche Lösungen aufgeführt, die in Joomla 2.5 und 3.x funktionieren sollten. Der Code wird nicht zum Kopieren und Einfügen, sondern als allgemeine Idee angezeigt.
Vor Joomla! 3.2 Das einzige, was Sie zur Verwendung der folgenden Beispiele benötigen, ist a component
. Nach Joomla 3.2 (für weniger komplexe Aufgaben) können Sie Anfragen von Modulen und Plugins bearbeiten.
Ihre URL für die Aufgabe muss folgendermaßen aussehen:
index.php?option=com_similar&task=abc&format=raw
Sie erstellen dann den Controller, der die Ansicht verwendet, beispielsweise Abc
die Datei view.raw.html (identisch mit einer normalen Ansichtsdatei).
Im Folgenden finden Sie den Code zum Generieren einer rohen HTML-Antwort:
/controller.php
public function abc()
{
// Set view
// Joomla 2.5
JRequest::setVar('view', 'Abc');
// (use JInput in 3.x)
$this->input->set('view', 'Abc');
parent::display();
}
/views/abc/view.raw.php
<?php
defined('_JEXEC') or die;
jimport('joomla.application.component.view');
class SimilarViewAbc extends JViewLegacy
{
function display($tpl = null)
{
parent::display($tpl);
}
}
/views/abc/tmpl/default.php
<?php
echo "Hello World from /views/abc/tmpl/default.php";
Hinweis: Dies ist die Lösung, die ich verwenden würde, wenn ich HTML zurückgeben müsste (sie ist sauberer und folgt der Joomla-Logik). Informationen zum Zurückgeben einfacher JSON-Daten finden Sie unten, wie Sie alles in den Controller einfügen.
Wenn Sie Ihre Ajax-Anfrage an einen Subcontroller richten , wie:
index.php?option=com_similar&controller=abc&format=raw
Dann muss der Name Ihres Subcontrollers (für die Rohansicht) lauten abc.raw.php
.
Dies bedeutet auch, dass Sie 2 Subcontroller mit dem Namen Abc haben werden / können.
Wenn Sie JSON zurückgeben, ist es möglicherweise sinnvoll, format=json
und zu verwenden abc.json.php
. In Joomla 2.5. Ich hatte einige Probleme damit, diese Option zum Laufen zu bringen (irgendwie war die Ausgabe beschädigt), also habe ich raw verwendet.
Wenn Sie eine gültige JSON-Antwort generieren müssen , lesen Sie die Dokumentationsseite JSON-Ausgabe generieren
// We assume that the whatver you do was a success.
$response = array("success" => true);
// You can also return something like:
$response = array("success" => false, "error"=> "Could not find ...");
// Get the document object.
$document = JFactory::getDocument();
// Set the MIME type for JSON output.
$document->setMimeEncoding('application/json');
// Change the suggested filename.
JResponse::setHeader('Content-Disposition','attachment;filename="result.json"');
echo json_encode($response);
Sie würden diesen Code im Allgemeinen in den Controller einfügen (Sie rufen ein Modell auf, das die von Ihnen codierten Daten zurückgibt - ein sehr häufiges Szenario). Wenn Sie noch weiter gehen möchten, können Sie auch eine JSON-Ansicht (view.json.php) erstellen, ähnlich wie im Rohbeispiel.
Schließen Sie die Seite noch nicht, da die Ajax-Anfrage funktioniert. Lesen Sie unten.
Vergessen Sie nicht, nach Fälschungen zu suchen. JSession::checkToken()
hier nützlich sein. Lesen Sie die Dokumentation zum Hinzufügen von CSRF-Antispoofing zu Formularen
Es kann vorkommen, dass Joomla die gewünschten Sprachzeichenfolgen nicht übersetzt, wenn Sie den Namen der Sprache in der Anfrage nicht senden.
Erwägen Sie, den Parameter lang an Ihre Anfrage anzuhängen (wie &lang=de
).
Neu in Joomla 3.2! - Ermöglicht die Bearbeitung von Anfragen, ohne dass eine Komponente erstellt werden muss
Joomla! Ajax-Schnittstelle - Joomla bietet jetzt eine einfache Möglichkeit, Ajax-Anfragen in einem Plugin oder Modul zu bearbeiten. Vielleicht möchten Sie das Joomla! Ajax-Schnittstelle, wenn Sie noch keine Komponente haben oder Anforderungen von einem Modul stellen müssen, das Sie bereits haben.
JRequest
? Es ist veraltet, sollte es einfach sein, $this->input
da ich v3.x verwende?
JRequest
. Vielen Dank
Valid JSON Response
Abschnitt erwähnt.
Dies ist eine späte Antwort auf diese sehr gut beantwortete Frage, aber ich wollte diese auf den Punkt gebrachte Lösung für diejenigen hinzufügen, die nur eine einfache Möglichkeit benötigen, mit einem AJAX-Aufruf an die Daten ihrer Komponenten zu gelangen.
Mit all den Joomla-Versionen, Möglichkeiten von Drittanbietern und Hacks, die ich in mehreren Tagen des Googelns gefunden habe, war dies der einfachste Ansatz, den ich mir einfallen lassen konnte - und Feedback wird auf jeden Fall geschätzt.
execute
zu meiner vorhandenen Hauptsteuerung hinzugefügtURL zum Aufrufen / Ausführen der Aufgabe:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Modifizierter Hauptcontroller \ com_example \ controller.php
class ExampleController extends JControllerLegacy {
public function display($cachable = false, $urlparams = false) {
$app = JFactory::getApplication();
$view = $app->input->getCmd('view', 'default');
$app->input->set('view', $view);
parent::display($cachable, $urlparams);
return $this;
}
public function execute()
{
// Not technically needed, but a DAMN good idea. See http://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms
// JSession::checkToken();
$task = JFactory::getApplication()->input->get('task');
try
{
parent::execute($task);
}
catch(Exception $e)
{
echo new JResponseJson($e);
}
}
}
Neuer Subcontroller \ com_example \ controller \ forajax.php
require_once JPATH_COMPONENT.'/controller.php';
class ExampleControllerForAjax extends ExampleController
{
public function MyTaskName()
{
$app = JFactory::getApplication();
$data['myRequest'] =$_REQUEST;
$data['myFile'] =__FILE__;
$data['myLine'] ='Line '.__LINE__;
$app->enqueueMessage('This part was reached at line ' . __LINE__);
$app->enqueueMessage('Then this part was reached at line ' . __LINE__);
$app->enqueueMessage('Here was a small warning at line ' . __LINE__, 'warning');
$app->enqueueMessage('Here was a big warning at line ' . __LINE__, 'error');
$task_failed = false;
echo new JResponseJson($data, 'My main response message',$task_failed);
$app->close();
}
}
Gerenderte JSON-Ausgabe
{
success: true,
message: "My main response message",
messages: {
message: [
"This part was reached at line 26",
"Then this part was reached at line 27"
],
warning: [
"Here was a small warning at line 28"
],
error: [
"Here was a big warning at line 29"
]
},
data: {
myRequest: {
option: "com_example",
task: "mytaskname",
Itemid: null
},
myFile: "C:\mysite\components\com_example\controllers\forajax.php",
myLine: "Line 24"
}
}
Die Antwort von Valentin ist gut, aber etwas zu komplex, wenn Sie nur 1 oder 2 Ajax-Aufrufe zu einer bereits erstellten Komponente hinzufügen müssen. Es ist durchaus möglich, weg mit nicht getrennt zu machen controller.raw.php
oder view.raw.php
Dateien.
Um diesen Ajax-Anruf zu tätigen
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
Im job
Subcontroller
public function keep_alive() {
$this->ajax_check();
//Do your processing and echo out whatever you want to return to the AJAX call
header('HTTP/1.1 202 Accepted', true, 202);
echo 'OK';
JFactory::getApplication()->close();
}
// Verifies jtoken and does a basic check that this is actually an AJAX call
private function ajax_check() {
if(!JSession::checkToken('GET') || !isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') {
header('HTTP/1.1 403 Forbidden', true, 403);
JFactory::getApplication()->close();
}
}
Valentins Antwort ist gut.
Ich bevorzuge einen JSON-Controller, der die Codierung und Fehlerbehandlung übernimmt. Ich habe eine JSON-Basisklasse erstellt:
class itrControllerJson extends JControllerLegacy {
/** @var array the response to the client */
protected $response = array();
public function addResponse($type, $message, $status=200) {
array_push($this->response, array(
'status' => $status,
'type' => $type,
'data' => $message
));
}
/**
* Outputs the response
* @return JControllerLegacy|void
*/
public function display() {
$response = array(
'status' => 200,
'type' => 'multiple',
'count' => count($this->response),
'messages' => $this->response
);
echo json_encode($response);
jexit();
}
}
Dieser Controller wird um die Controller-Klasse erweitert, die die Arbeit erledigt:
require_once __DIR__.'json.php';
class componentControllerAddress extends itrControllerJson {
public function get() {
try {
if (!JSession::checkToken()) {
throw new Exception(JText::_('JINVALID_TOKEN'), 500);
}
$app = JFactory::getApplication();
$id = $app->input->get('id', null, 'uint');
if (is_null($id)) {
throw new Exception('Invalid Parameter', 500);
}
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*');
$query->from('#__table');
$query->where('id = '.$db->quote($id));
$db->setQuery($query);
$response = $db->loadObject();
$this->addResponse('message', $response, 200);
} catch (Exception $e) {
$this->addResponse('error', $e->getMessage(), 500);
}
$this->display();
}
}
und du rufst die Anfrage so an:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
Der Token-Hash wird von JSession :: getFormToken () generiert. Der vollständige Aufruf könnte also so aussehen:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
Der zweite Parameter ist auf "false" gesetzt, damit wir dies in Javascript-Aufrufen ohne xml-Neuschreibung verwenden können.
JResponseJson
Klasse umgehen?
Wenn Sie zu 100% sicher sind, dass es kein Plugin für Drittanbieter gibt, das Javascript-Ausgaben hinzufügt, funktioniert ein reiner json_encode.
Aber ... zum Beispiel fügt JomSocial "" der gesamten Site hinzu.
Also ... ein praktischer Trick, wickeln Sie json_encode in Tags ein und verarbeiten Sie ihn auf der Javascript-Seite.
echo '@START@' . json_encode(...) . '@END@';
Sie können direkt auf einen Controller zugreifen, indem Sie den Controllernamen in der Task verwenden:
index.php?option=com_similar&task=controller.abc&format=raw
ruft auf: controller.raw.php (return ist raw)
index.php?option=com_similar&task=controller.abc
ruft auf: controller.php (return ist html wenn du es nicht verwendest die;
)