Sto sviluppando un componente personalizzato per Joomla! 3.xe desideri effettuare una chiamata AJAX al suo interno per recuperare alcuni dati. Qual è il modo corretto di farlo?
Sto sviluppando un componente personalizzato per Joomla! 3.xe desideri effettuare una chiamata AJAX al suo interno per recuperare alcuni dati. Qual è il modo corretto di farlo?
Risposte:
SI PREGA DI NOTARE CHE QUESTA RISPOSTA ha già qualche anno e non è stata aggiornata. Sentiti libero di modificare / commentare se pensi che qualcosa non sia più esatto.
Non esiste quasi un modo veramente ufficiale di gestirlo, dipende molto dalla complessità e da quanto si desidera fare affidamento sul modello MVC per svolgere il proprio lavoro.
Di seguito sono riportate alcune possibili soluzioni che dovrebbero funzionare in Joomla 2.5 e 3.x. Il codice non viene presentato per un processo di copia e incolla ma piuttosto come un'idea generale.
Prima di Joomla! 3.2 l'unica cosa di cui hai bisogno per usare gli esempi seguenti è a component
. Dopo Joomla 3.2 (per attività complesse inferiori) è possibile gestire la richiesta da moduli e plugin.
L' URL per l'attività deve essere simile al seguente:
index.php?option=com_similar&task=abc&format=raw
Si crea il controller che utilizzerà la vista, diciamo Abc
, che conterrà il file view.raw.html (identico a un normale file di visualizzazione).
Di seguito è riportato il codice per generare una risposta HTML non elaborata:
/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";
Nota: questa è la soluzione che userei se dovessi restituire HTML (è più pulito e segue la logica di Joomla). Per la restituzione di semplici dati JSON, vedere di seguito come inserire tutto nel controller.
Se invii la tua richiesta Ajax a un subcontrollore , ad esempio:
index.php?option=com_similar&controller=abc&format=raw
Il nome del subcontrollore (per la vista non elaborata) deve essere abc.raw.php
.
Questo significa anche che avrai / potresti avere 2 subcontrollori chiamati Abc.
Se si restituisce JSON, potrebbe essere logico utilizzare format=json
e abc.json.php
. In Joomla 2.5. Ho avuto dei problemi a far funzionare questa opzione (in qualche modo l'output era corrotto), quindi ho usato raw.
Se è necessario generare una risposta JSON valida , consultare la pagina dei documenti Generazione dell'output JSON
// 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);
In genere inseriresti questo codice nel controller (chiamerai un modello che restituirà i dati che codifichi - uno scenario molto comune). Se è necessario andare oltre, è anche possibile creare una vista JSON (view.json.php), simile all'esempio non elaborato.
Ora che la richiesta Ajax funziona, non chiudere ancora la pagina. Leggere sotto.
Non dimenticare di controllare i falsi delle richieste. JSession::checkToken()
vieni utile qui. Leggi la documentazione su Come aggiungere l' anti-spoofing CSRF ai moduli
Può succedere che se non invii il nome della lingua nella richiesta, Joomla non tradurrà le stringhe della lingua che desideri.
Valuta di aggiungere in qualche modo il parametro lang alla tua richiesta (come &lang=de
).
Novità in Joomla 3.2! - ti ha permesso di effettuare richieste handle senza creare un componente
Joomla! Interfaccia Ajax - Joomla ora fornisce un modo leggero per gestire la richiesta Ajax in un plugin o modulo. Potresti voler usare Joomla! Interfaccia Ajax se non si dispone già di un componente o se è necessario effettuare richieste da un modulo già esistente.
JRequest
? È deprecato dovrebbe essere semplicemente $this->input
da quando uso v3.x?
JRequest
. Grazie
Valid JSON Response
sezione.
Questa è una risposta tardiva a questa domanda a cui è stata data una risposta molto buona, ma volevo aggiungere questa soluzione immediata per coloro che hanno solo bisogno di un modo semplice per accedere ai dati dei loro componenti con una chiamata AJAX.
Con tutte le versioni di Joomla, le possibilità di terze parti e gli hack che ho trovato in diversi giorni di ricerche su Google, questo è stato l'approccio più semplice che ho potuto escogitare - e il feedback è DEFINATAMENTE apprezzato.
execute
al mio controller principale esistenteURL per chiamare / eseguire l'attività:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Controller principale modificato \ 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);
}
}
}
Nuovo subcontrollore \ com_example \ controllers \ 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();
}
}
Output JSON reso
{
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"
}
}
La risposta di Valentin è buona ma è un po 'troppo complessa se tutto ciò che devi fare è aggiungere 1 o 2 chiamate ajax a un componente che è già stato creato. È perfettamente possibile cavarsela senza creare file controller.raw.php
o view.raw.php
file separati .
Per effettuare questa chiamata Ajax
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
Nel job
subcontrollore
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();
}
}
La risposta di Valentin è buona.
Preferisco un controller json che gestisce la codifica e la gestione degli errori per questo Ho creato una classe base json:
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();
}
}
Questo controller viene esteso dalla classe controller che fa il lavoro, qualcosa del genere:
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();
}
}
e chiamate la richiesta in questo modo:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
L'hash token viene generato da JSession :: getFormToken (). Quindi la chiamata completa completa potrebbe essere simile a questa:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
Il secondo parametro è impostato su "false", quindi possiamo usarlo nelle chiamate javascript senza riscrivere xml.
JResponseJson
classe per gestirlo?
Se sei sicuro al 100% che non esiste un plug-in di terze parti che aggiunge alcun output Javascript, un json_encode puro funziona bene.
Ma ... per esempio JomSocial aggiunge "" all'intero sito.
Quindi ... un trucco utile, avvolgi json_encode con i tag ed elaboralo sul lato Javascript.
echo '@START@' . json_encode(...) . '@END@';
È possibile accedere direttamente a un controller utilizzando il nome del controller nell'attività:
index.php?option=com_similar&task=controller.abc&format=raw
chiamerà: controller.raw.php (il ritorno è grezzo)
index.php?option=com_similar&task=controller.abc
chiamerà: controller.php (il ritorno è html se non lo usi die;
)