Tôi đang phát triển một thành phần tùy chỉnh cho Joomla! 3.x và muốn thực hiện cuộc gọi AJAX bên trong nó để lấy một số dữ liệu. Cách thích hợp để làm điều đó là gì?
Tôi đang phát triển một thành phần tùy chỉnh cho Joomla! 3.x và muốn thực hiện cuộc gọi AJAX bên trong nó để lấy một số dữ liệu. Cách thích hợp để làm điều đó là gì?
Câu trả lời:
XIN LƯU Ý R ANNG TRẢ LỜI NÀY đã vài năm tuổi và chưa được cập nhật. Hãy chỉnh sửa / bình luận nếu bạn nghĩ rằng một cái gì đó không còn chính xác.
Hầu như không có cách nào thực sự chính thức để giải quyết vấn đề này, nó phụ thuộc nhiều vào độ phức tạp và mức độ bạn muốn dựa vào mẫu MVC để thực hiện công việc.
Dưới đây là một số giải pháp khả thi những gì sẽ hoạt động trong Joomla 2.5 và 3.x. Mã này không được trình bày cho một công việc sao chép - dán mà là một ý tưởng chung.
Trước Joomla! 3.2 điều duy nhất bạn cần sử dụng các ví dụ dưới đây là a component
. Sau Joomla 3.2 (đối với các tác vụ phức tạp thấp hơn), bạn có thể xử lý yêu cầu từ các mô-đun và plugin.
URL của bạn cho tác vụ cần phải trông như thế này:
index.php?option=com_similar&task=abc&format=raw
Bạn hơn là tạo bộ điều khiển sẽ sử dụng chế độ xem, giả sử Abc
, trong đó sẽ chứa tệp view.raw.html (giống hệt với tệp xem thông thường).
Dưới đây bạn có mã để tạo phản hồi HTML thô:
/controll.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();
}
/view/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);
}
}
/view/abc/tmpl/default.php
<?php
echo "Hello World from /views/abc/tmpl/default.php";
Lưu ý: Đây là giải pháp tôi sẽ sử dụng nếu tôi phải trả về HTML (nó sạch hơn và tuân theo logic Joomla). Để trả về dữ liệu JSON đơn giản, hãy xem bên dưới cách đặt mọi thứ vào bộ điều khiển.
Nếu bạn thực hiện yêu cầu Ajax của bạn đến một subcontroller , như:
index.php?option=com_similar&controller=abc&format=raw
Hơn tên điều khiển con của bạn (cho chế độ xem thô) cần phải có abc.raw.php
.
Điều này cũng có nghĩa là bạn sẽ / có thể có 2 người điều khiển phụ tên là Abc.
Nếu bạn trả về JSON, nó có thể có ý nghĩa để sử dụng format=json
và abc.json.php
. Trong Joomla 2.5. Tôi có một số vấn đề khiến tùy chọn này hoạt động (bằng cách nào đó đầu ra bị hỏng), vì vậy tôi đã sử dụng thô.
Nếu bạn cần tạo phản hồi JSON hợp lệ , hãy xem trang tài liệu Tạo đầu ra 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);
Bạn thường sẽ đặt mã này vào bộ điều khiển (bạn sẽ gọi một mô hình sẽ trả về dữ liệu bạn mã hóa - một kịch bản rất phổ biến). Nếu bạn cần đưa nó đi xa hơn, bạn cũng có thể tạo chế độ xem JSON (view.json.php), tương tự như ví dụ thô.
Bây giờ yêu cầu Ajax đang hoạt động, chưa đóng trang. Đọc dưới đây.
Đừng quên kiểm tra các giả mạo yêu cầu. JSession::checkToken()
đến đây có ích Đọc tài liệu về Cách thêm CSRF chống giả mạo vào biểu mẫu
Có thể xảy ra là nếu bạn không gửi tên ngôn ngữ trong yêu cầu, Joomla sẽ không dịch các chuỗi ngôn ngữ bạn muốn.
Xem xét nối thêm bằng cách nào đó lang param vào yêu cầu của bạn (như &lang=de
).
Mới trong Joomla 3.2! - cho phép bạn thực hiện các yêu cầu xử lý mà không cần xây dựng một thành phần
Joomla! Giao diện Ajax - Joomla hiện cung cấp một cách nhẹ nhàng để xử lý yêu cầu Ajax trong một plugin hoặc mô-đun. Bạn có thể muốn sử dụng Joomla! Giao diện Ajax nếu bạn chưa có thành phần hoặc nếu bạn cần thực hiện các yêu cầu từ mô-đun mà bạn đã có.
JRequest
? Nó không được chấp nhận nếu $this->input
tôi sử dụng v3.x?
JRequest
. Cảm ơn
Valid JSON Response
phần.
Đây là một câu trả lời muộn cho câu hỏi được trả lời rất tốt này, nhưng tôi muốn thêm giải pháp cắt xén này cho những người chỉ cần một cách đơn giản để lấy dữ liệu của các thành phần của họ bằng một cuộc gọi AJAX.
Với tất cả các phiên bản Joomla, khả năng của bên thứ 3 và các bản hack mà tôi đã tìm thấy trong nhiều ngày làm việc, đây là cách tiếp cận đơn giản nhất tôi có thể đưa ra - và phản hồi được DEFINATELY đánh giá cao.
execute
vào bộ điều khiển chính hiện có của tôiURL để gọi / thực hiện tác vụ:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
Bộ điều khiển chính đã sửa đổi \ 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);
}
}
}
Bộ điều khiển mới \ com_example \ controls \ 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();
}
}
Kết xuất JSON được kết xuất
{
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"
}
}
Câu trả lời của Valentin là tốt nhưng hơi phức tạp một chút nếu tất cả những gì bạn cần làm là thêm 1 hoặc 2 cuộc gọi ajax vào một thành phần đã được xây dựng. Hoàn toàn có thể thoát khỏi việc không tạo các tệp controller.raw.php
hoặc view.raw.php
tệp riêng biệt .
Để thực hiện cuộc gọi ajax này
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
Trong 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();
}
}
Câu trả lời của Valentin là tốt.
Tôi thích một bộ điều khiển json xử lý mã hóa và xử lý lỗi cho việc này Tôi đã tạo một lớp cơ sở 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();
}
}
Bộ điều khiển này được mở rộng bởi lớp trình điều khiển thực hiện công việc, đại loại như thế này:
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();
}
}
và bạn gọi yêu cầu như thế này:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
Hàm băm token được tạo bởi JSession :: getFormToken (). Vì vậy, cuộc gọi hoàn chỉnh hoàn chỉnh có thể giống như thế này:
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
Tham số thứ hai được đặt thành "false" để chúng tôi có thể sử dụng tham số này trong các cuộc gọi javascript mà không cần viết lại xml.
JResponseJson
lớp để xử lý nó?
Nếu bạn chắc chắn 100% không có plugin bên thrid nào thêm bất kỳ đầu ra Javascript nào, thì json_encode thuần hoạt động.
Nhưng ... ví dụ JomSocial thêm "" vào toàn bộ trang.
Vì vậy, ... một mẹo hữu ích, bọc json_encode bằng các thẻ và xử lý nó ở phía Javascript.
echo '@START@' . json_encode(...) . '@END@';
Bạn có thể truy cập bộ điều khiển trực tiếp bằng cách sử dụng tên bộ điều khiển trong tác vụ:
index.php?option=com_similar&task=controller.abc&format=raw
sẽ gọi: control.raw.php (trả về là raw)
index.php?option=com_similar&task=controller.abc
sẽ gọi: controller.php (return là html nếu bạn không sử dụng die;
)