Saya sedang mengembangkan komponen khusus untuk Joomla! 3.x dan ingin membuat panggilan AJAX di dalamnya untuk mengambil beberapa data. Apa cara yang tepat untuk melakukannya?
Saya sedang mengembangkan komponen khusus untuk Joomla! 3.x dan ingin membuat panggilan AJAX di dalamnya untuk mengambil beberapa data. Apa cara yang tepat untuk melakukannya?
Jawaban:
HARAP DICATAT BAHWA JAWABAN INI sudah berusia beberapa tahun dan tidak diperbarui. Jangan ragu untuk mengedit / berkomentar jika Anda berpikir ada sesuatu yang tidak tepat lagi.
Hampir tidak ada cara resmi untuk menangani hal ini, ini sangat tergantung pada kompleksitas dan seberapa banyak Anda ingin bergantung pada pola MVC untuk melakukan pekerjaan.
Di bawah ini adalah beberapa solusi yang mungkin apa yang harus bekerja di Joomla 2.5 dan 3.x. Kode ini tidak disajikan untuk pekerjaan salin-rekat melainkan sebagai gagasan umum.
Sebelum ke Joomla! 3.2 satu-satunya hal yang perlu Anda gunakan contoh di bawah ini adalah a component
. Setelah Joomla 3.2 (untuk tugas-tugas kompleks yang lebih rendah) Anda dapat menangani permintaan dari modul dan plugin.
URL Anda untuk tugas harus terlihat seperti ini:
index.php?option=com_similar&task=abc&format=raw
Anda daripada membuat pengontrol yang akan menggunakan tampilan, katakanlah Abc
, yang akan berisi file view.raw.html (identik dengan file tampilan normal).
Di bawah ini Anda memiliki kode untuk menghasilkan respons HTML mentah:
/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";
Catatan: Ini adalah solusi yang akan saya gunakan jika saya harus mengembalikan HTML (lebih bersih dan mengikuti logika Joomla). Untuk mengembalikan data JSON sederhana, lihat di bawah ini cara meletakkan semuanya di controller.
Jika Anda membuat permintaan Ajax ke subkontroller , seperti:
index.php?option=com_similar&controller=abc&format=raw
Daripada perlu nama subkontroler (untuk tampilan mentah) abc.raw.php
.
Ini juga berarti bahwa Anda akan / mungkin memiliki 2 subkontrol bernama Abc.
Jika Anda mengembalikan JSON, mungkin masuk akal untuk menggunakan format=json
dan abc.json.php
. Di Joomla 2.5. Saya punya beberapa masalah untuk mendapatkan opsi ini untuk bekerja (entah bagaimana hasilnya rusak), jadi saya menggunakan mentah.
Jika Anda perlu membuat respons JSON yang valid , lihat halaman dokumen Menghasilkan 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);
Anda biasanya akan meletakkan kode ini di controller (Anda akan memanggil model yang akan mengembalikan data yang Anda encode - skenario yang sangat umum). Jika Anda perlu melangkah lebih jauh, Anda juga dapat membuat tampilan JSON (view.json.php), mirip dengan contoh mentah.
Sekarang setelah permintaan Ajax berfungsi, jangan tutup halamannya. Baca di bawah.
Jangan lupa untuk memeriksa permintaan pemalsuan. JSession::checkToken()
berguna di sini. Baca dokumentasi di Bagaimana menambahkan CSRF anti-spoofing ke bentuk
Mungkin saja terjadi jika Anda tidak mengirim nama bahasa dalam permintaan, Joomla tidak akan menerjemahkan string bahasa yang Anda inginkan.
Pertimbangkan untuk menambahkan entah bagaimana lang param ke permintaan Anda (seperti &lang=de
).
Baru di Joomla 3.2! - Memungkinkan Anda membuat permintaan handle tanpa membangun komponen
Joomla! Ajax Interface - Joomla sekarang menyediakan cara yang ringan untuk menangani permintaan Ajax dalam plugin atau modul. Anda mungkin ingin menggunakan Joomla! Ajax Interface jika Anda belum memiliki komponen atau jika Anda perlu membuat permintaan dari modul yang sudah Anda miliki.
JRequest
? Itu sudah tidak digunakan lagi $this->input
karena saya menggunakan v3.x?
JRequest
. Terima kasih
Valid JSON Response
bagian.
Ini adalah jawaban yang terlambat untuk pertanyaan yang dijawab dengan sangat baik ini, tetapi saya ingin menambahkan solusi cut-to-the-chase ini bagi mereka yang hanya membutuhkan cara sederhana untuk mendapatkan data komponen mereka dengan panggilan AJAX.
Dengan semua versi Joomla, kemungkinan pihak ketiga, dan peretasan yang saya temukan selama beberapa hari di Google, ini adalah pendekatan paling sederhana yang dapat saya lakukan - dan umpan balik sangat dihargai.
execute
ke pengontrol utama saya yang adaURL untuk memanggil / menjalankan tugas:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Pengontrol Utama Yang Dimodifikasi \ 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);
}
}
}
Subkontroller Baru \ 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 yang Diberikan
{
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"
}
}
Jawaban Valentin baik tetapi sedikit terlalu rumit jika yang perlu Anda lakukan adalah menambahkan 1 atau 2 panggilan ajax ke komponen yang sudah dibangun. Sangat mungkin untuk pergi tanpa membuat file controller.raw.php
atau terpisah view.raw.php
.
Untuk melakukan panggilan ajax ini
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
Di job
subkontroller
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();
}
}
Jawaban Valentin bagus.
Saya lebih suka pengontrol json yang menangani pengodean dan penanganan kesalahan untuk ini saya membuat kelas dasar 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();
}
}
Pengontrol ini diperluas oleh kelas pengontrol yang melakukan pekerjaan, seperti ini:
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();
}
}
dan Anda memanggil permintaan seperti ini:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
Hash token yang dihasilkan oleh JSession :: getFormToken (). Jadi panggilan lengkap yang lengkap bisa seperti ini:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
Parameter kedua diatur ke "false" sehingga kita dapat menggunakan ini dalam panggilan javascript tanpa xml rewrite.
JResponseJson
kelas untuk menanganinya?
Jika Anda 100% yakin tidak ada plugin pihak ketiga yang menambahkan output Javascript apa pun, json_encode murni berfungsi OK.
Tapi ... misalnya JomSocial menambahkan "" ke seluruh situs.
Jadi ... trik praktis, bungkus json_encode dengan tag, dan proses di sisi Javascript.
echo '@START@' . json_encode(...) . '@END@';
Anda dapat mengakses pengontrol secara langsung dengan menggunakan nama pengontrol di tugas:
index.php?option=com_similar&task=controller.abc&format=raw
akan memanggil: controller.raw.php (return is raw)
index.php?option=com_similar&task=controller.abc
akan memanggil: controller.php (return adalah html jika Anda tidak menggunakan die;
)