Je développe un composant personnalisé pour Joomla! 3.x et souhaitez faire un appel AJAX à l'intérieur pour récupérer des données. Quelle est la bonne façon de le faire?
Je développe un composant personnalisé pour Joomla! 3.x et souhaitez faire un appel AJAX à l'intérieur pour récupérer des données. Quelle est la bonne façon de le faire?
Réponses:
VEUILLEZ NOTER QUE CETTE RÉPONSE date déjà de quelques années et n’a pas été mise à jour. N'hésitez pas à éditer / commenter si vous pensez que quelque chose n'est plus exact.
Il n’existe pratiquement pas de solution officielle à ce problème, cela dépend en grande partie de la complexité et de la mesure dans laquelle vous souhaitez vous appuyer sur le modèle MVC pour effectuer le travail.
Vous trouverez ci-dessous quelques solutions possibles à ce qui devrait fonctionner dans Joomla 2.5 et 3.x. Le code n'est pas présenté pour un travail copier-coller, mais plutôt comme une idée générale.
Avant Joomla! 3.2 la seule chose dont vous avez besoin pour utiliser les exemples ci-dessous est un component
. Après Joomla 3.2 (pour les tâches moins complexes), vous pouvez gérer les requêtes des modules et des plugins.
Votre URL pour la tâche doit ressembler à ceci:
index.php?option=com_similar&task=abc&format=raw
Vous créez ensuite le contrôleur qui utilisera la vue, par exemple Abc
, qui contiendra le fichier view.raw.html (identique à un fichier de vue normale).
Vous trouverez ci-dessous le code permettant de générer une réponse HTML brute:
/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";
Remarque: C’est la solution que j’utiliserais si je devais retourner du code HTML (il est plus propre et respecte la logique de Joomla). Pour renvoyer des données JSON simples, voir ci-dessous comment tout mettre dans le contrôleur.
Si vous faites votre demande Ajax à un sous - contrôleur , par exemple:
index.php?option=com_similar&controller=abc&format=raw
Que le nom de votre sous-contrôleur (pour la vue brute) doit être abc.raw.php
.
Cela signifie également que vous aurez / pourrez avoir 2 sous-contrôleurs nommés Abc.
Si vous retournez JSON, il peut être judicieux d'utiliser format=json
et abc.json.php
. Dans Joomla 2.5. J'ai eu quelques problèmes à faire fonctionner cette option (la sortie était corrompue), alors j'ai utilisé raw.
Si vous devez générer une réponse JSON valide , consultez la page de documentation Génération d'une sortie 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);
Vous mettriez généralement ce code dans le contrôleur (vous appelerez un modèle qui renverra les données que vous encodez - un scénario très courant). Si vous avez besoin d'aller plus loin, vous pouvez également créer une vue JSON (view.json.php), similaire à l'exemple brut.
Maintenant que la requête Ajax fonctionne, ne fermez pas encore la page. Lire ci-dessous.
N'oubliez pas de vérifier les faux de demande. JSession::checkToken()
être utile ici. Lisez la documentation sur Comment ajouter de l' anti-usurpation CSRF aux formulaires
Il peut arriver que si vous n'envoyez pas le nom de la langue dans la demande, Joomla ne traduira pas les chaînes de la langue souhaitée.
Pensez à ajouter en quelque sorte le paramètre lang à votre requête (du type &lang=de
).
Nouveau dans Joomla 3.2! - vous permet de faire des requêtes sans construire de composant
Joomla! Interface Ajax - Joomla fournit désormais un moyen léger de gérer les demandes Ajax dans un plugin ou un module. Vous voudrez peut-être utiliser le logiciel Joomla! Ajax Interface si vous ne possédez pas déjà de composant ou si vous devez faire des demandes à partir d'un module que vous avez déjà.
JRequest
? C'est obsolète devrait-il être simplement $this->input
depuis que j'utilise v3.x?
JRequest
. Merci
Valid JSON Response
section.
C'est une réponse tardive à cette question très bien répondue, mais je voulais ajouter cette solution parfaitement adaptée à ceux qui recherchent simplement un moyen simple d'obtenir les données de leurs composants avec un appel AJAX.
Avec toutes les versions de Joomla, les possibilités offertes par une tierce partie et les piratages que j'ai trouvés au cours de plusieurs jours passés sur google, c’était l’approche la plus simple que je pouvais proposer - et les retours sont définitivement appréciés.
execute
à mon contrôleur principal existantURL à appeler / exécuter la tâche:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Contrôleur principal modifié \ 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);
}
}
}
Nouveau sous-contrôleur \ 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();
}
}
Rendu JSON rendu
{
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 réponse de Valentin est bonne mais elle est un peu trop complexe si tout ce que vous avez à faire est d’ajouter 1 ou 2 appels ajax à un composant déjà construit. Il est parfaitement possible de se contenter de ne pas faire séparément controller.raw.php
ou view.raw.php
fichiers.
Pour faire cet appel ajax
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
Dans le job
sous - contrôleur
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 réponse de Valentin est bonne.
Je préfère un contrôleur json qui gère l'encodage et la gestion des erreurs pour cela. J'ai créé une classe de 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();
}
}
Ce contrôleur est étendu par la classe de contrôleur qui fait le travail, quelque chose comme ceci:
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();
}
}
et vous appelez la requête comme ceci:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
Le hachage du jeton est généré par JSession :: getFormToken (). Ainsi, l'appel complet complet pourrait ressembler à ceci:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
Le second paramètre est défini sur "false" afin que nous puissions l'utiliser dans les appels javascript sans réécriture XML.
JResponseJson
class pour le gérer?
Si vous êtes sûr à 100% qu'il n'y a pas de plugin tiers qui ajoute une sortie Javascript, un json_encode pur fonctionne bien.
Mais ... par exemple, JomSocial ajoute "" à l'ensemble du site.
Alors ... un truc pratique, habillez json_encode avec des balises et traitez-le du côté Javascript.
echo '@START@' . json_encode(...) . '@END@';
Vous pouvez accéder directement à un contrôleur en utilisant le nom du contrôleur dans la tâche:
index.php?option=com_similar&task=controller.abc&format=raw
appellera: controller.raw.php (le retour est brut)
index.php?option=com_similar&task=controller.abc
va appeler: controller.php (le retour est html si vous n'utilisez pas die;
)