Estou desenvolvendo um componente personalizado para o Joomla! 3.xe deseja fazer uma chamada AJAX dentro dele para recuperar alguns dados. Qual é a maneira correta de fazer isso?
Estou desenvolvendo um componente personalizado para o Joomla! 3.xe deseja fazer uma chamada AJAX dentro dele para recuperar alguns dados. Qual é a maneira correta de fazer isso?
Respostas:
Observe que esta resposta já tem alguns anos e não foi atualizada. Sinta-se livre para editar / comentar se você acha que algo não é mais exato.
Quase não existe uma maneira oficial de lidar com isso, depende muito da complexidade e do quanto você deseja confiar no padrão MVC para fazer o trabalho.
Abaixo estão algumas soluções possíveis que devem funcionar no Joomla 2.5 e 3.x. O código não é apresentado para um trabalho de copiar e colar, mas como uma idéia geral.
Antes do Joomla! 3.2 a única coisa que você precisa para usar os exemplos abaixo é a component
. Após o Joomla 3.2 (para tarefas menos complexas), você pode lidar com solicitações de módulos e plugins.
Seu URL para a tarefa precisa ter a seguinte aparência:
index.php?option=com_similar&task=abc&format=raw
Você criou o controlador que usará a visualização, digamos Abc
, que conterá o arquivo view.raw.html (idêntico a um arquivo de visualização normal).
Abaixo você tem o código para gerar uma resposta HTML bruta:
/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: Esta é a solução que eu usaria se tivesse que retornar HTML (é mais limpo e segue a lógica do Joomla). Para retornar dados JSON simples, veja abaixo como colocar tudo no controlador.
Se você fizer sua solicitação do Ajax para um subcontrolador , como:
index.php?option=com_similar&controller=abc&format=raw
Do que o nome do seu subcontratado (para a visualização bruta) precisa ser abc.raw.php
.
Isso significa também que você terá / poderá ter 2 subcontroladores chamados Abc.
Se você retornar JSON, pode fazer sentido usar format=json
e abc.json.php
. No Joomla 2.5. Eu tive alguns problemas para que essa opção funcionasse (de alguma forma, a saída foi corrompida), então usei raw.
Se você precisar gerar uma resposta JSON válida , consulte a página de documentos Gerando saída 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);
Você geralmente colocaria esse código no controlador (você chamará um modelo que retornará os dados que você codifica - um cenário muito comum). Se você precisar ir além, também poderá criar uma visualização JSON (view.json.php), semelhante ao exemplo bruto.
Agora que a solicitação do Ajax está funcionando, não feche a página ainda. Leia abaixo.
Não se esqueça de procurar falsificações de pedidos. JSession::checkToken()
venha a calhar aqui. Leia a documentação em Como adicionar anti-spoofing CSRF aos formulários
Pode acontecer que, se você não enviar o nome do idioma na solicitação, o Joomla não traduzirá as seqüências de caracteres desejadas.
Considere anexar de alguma forma o parâmetro lang à sua solicitação (como &lang=de
).
Novo no Joomla 3.2! - permitiu que você fizesse solicitações de manipulação sem criar um componente
Joomla! Interface Ajax - O Joomla agora oferece uma maneira leve de lidar com a solicitação do Ajax em um plug-in ou módulo. Você pode querer usar o Joomla! Interface Ajax se você ainda não possui um componente ou se precisa fazer solicitações de um módulo que já possui.
JRequest
? Ele está obsoleto, deve ser simplesmente $this->input
desde que eu uso a v3.x?
JRequest
. Obrigado
Valid JSON Response
seção.
Esta é uma resposta tardia para esta pergunta muito bem respondida, mas eu queria adicionar esta solução simples para aqueles que precisam apenas de uma maneira simples de acessar os dados de seus componentes com uma chamada AJAX.
Com todas as versões do Joomla, possibilidades de terceiros e hacks que eu encontrei ao longo de vários dias pesquisando no Google, essa foi a abordagem mais simples que eu pude criar - e o feedback é DEFINATAMENTE apreciado.
execute
ao meu controlador principal existenteURL para chamar / executar a tarefa:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Controlador principal modificado \ 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);
}
}
}
Novo subcontrolador \ 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();
}
}
Saída JSON renderizada
{
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"
}
}
A resposta do Valentin é boa, mas é um pouco complexa, se tudo o que você precisa fazer é adicionar 1 ou 2 chamadas ajax a um componente que já foi criado. É perfeitamente possível evitar não criar arquivos controller.raw.php
ou view.raw.php
arquivos separados .
Para fazer esta chamada ajax
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
No job
subcontrolador
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();
}
}
A resposta de Valentin é boa.
Eu prefiro um controlador json que lida com a codificação e manipulação de erros para isso, criei uma 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();
}
}
Esse controlador é estendido pela classe do controlador que faz o trabalho, algo como isto:
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 você chama a solicitação assim:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
O hash do token é gerado por JSession :: getFormToken (). Portanto, a chamada completa completa pode ser assim:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
O segundo parâmetro é definido como "false" para que possamos usá-lo em chamadas javascript sem reescrever xml.
JResponseJson
classe para lidar com isso?
Se você tem 100% de certeza de que não há um plug-in thrid-party que adicione qualquer saída Javascript, um json_encode puro funciona.
Mas ... por exemplo, o JomSocial adiciona "" a todo o site.
Então ... um truque útil, envolva json_encode com tags e processe-o no lado do Javascript.
echo '@START@' . json_encode(...) . '@END@';
Você pode acessar um controlador diretamente usando o nome do controlador na tarefa:
index.php?option=com_similar&task=controller.abc&format=raw
chamará: controller.raw.php (o retorno é bruto)
index.php?option=com_similar&task=controller.abc
chamará: controller.php (o retorno é html se você não usar die;
)