Joomla!のカスタムコンポーネントを開発しています。3.xで、内部でAJAX呼び出しを行ってデータを取得したい。それを行う適切な方法は何ですか?
Joomla!のカスタムコンポーネントを開発しています。3.xで、内部でAJAX呼び出しを行ってデータを取得したい。それを行う適切な方法は何ですか?
回答:
この回答は既に数年前のものであり、更新されていないことに注意してください。何かがもはや正確ではないと思う場合は、自由に編集/コメントしてください。
これを扱う公式な方法はほとんどありません。それは、複雑さと、作業を行うためにMVCパターンにどれだけ依存したいかに大きく依存します。
以下は、Joomla 2.5および3.xで動作するいくつかの可能なソリューションです。コードはコピー-貼り付けジョブではなく、一般的なアイデアとして提示されています。
Joomla!の前に 3.2以下の例を使用するために必要な唯一のものはですcomponent
。Joomla 3.2(複雑度の低いタスク用)の後、モジュールとプラグインからのリクエストを処理できます。
あなたのURLタスクのは、このように見える必要があります。
index.php?option=com_similar&task=abc&format=raw
ビューを使用するコントローラーを作成します。たとえばAbc
、ビューview.raw.html(通常のビューファイルと同じ)を含むビューを使用します。
以下に、生のHTML応答を生成するコードを示します。
/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";
注:これは、HTMLを返す必要がある場合に使用するソリューションです(よりクリーンでJoomlaのロジックに従います)。単純なJSONデータを返すには、以下を参照して、すべてをコントローラーに配置する方法を参照してください。
Ajaxリクエストをサブコントローラーに送信すると、次のようになります。
index.php?option=com_similar&controller=abc&format=raw
サブコントローラー名(rawビューの場合)よりもが必要abc.raw.php
です。
これは、Abcという名前の2つのサブコントローラーがあることを意味します。
JSONを返す場合、format=json
and を使用するのが理にかなっていますabc.json.php
。Joomla 2.5で。このオプションを機能させるためにいくつかの問題が発生したため(出力が破損したため)、そのまま使用しました。
有効なJSON応答を生成する必要がある場合は、ドキュメントページで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);
通常、このコードをコントローラーに配置します(エンコードするデータを返すモデルを呼び出します-非常に一般的なシナリオ)。さらに進める必要がある場合は、未加工の例と同様に、JSONビュー(view.json.php)を作成することもできます。
Ajaxリクエストが機能するようになったので、まだページを閉じないでください。以下をお読みください。
リクエストの偽造を確認することを忘れないでください。JSession::checkToken()
ここで役立ちます。CSRFアンチスプーフィングをフォームに追加する方法に関するドキュメントを読む
リクエストで言語名を送信しないと、Joomlaが必要な言語文字列を翻訳しないことがあります。
リクエストに何らかの方法でlangパラメータを追加することを検討してください(など&lang=de
)。
Joomla 3.2の新機能!-コンポーネントを構築せずにハンドルリクエストを作成できるようにしました
Joomla!Ajaxインターフェイス -Joomlaは、プラグインまたはモジュールでAjaxリクエストを処理する軽量な方法を提供するようになりました。Joomla!を使用することもできます。コンポーネントがまだない場合、または既に持っているモジュールからリクエストを行う必要がある場合は、Ajaxインターフェイス。
JRequest
ですか?$this->input
v3.xを使用しているため、単純に廃止されるべきですか?
JRequest
。ありがとう
Valid JSON Response
セクションで言及しました。
これは非常によく回答されたこの質問に対する遅い回答ですが、AJAX呼び出しでコンポーネントのデータにアクセスする簡単な方法が必要な場合に、この簡単なソリューションを追加したかったのです。
Joomlaのすべてのバージョン、サードパーティの可能性、および数日間のグーグルで見つけたハックにより、これは私が思いつく最も簡単なアプローチでした-フィードバックは間違いなく高く評価されています。
execute
既存のメインコントローラーに機能を追加タスクを呼び出す/実行するURL:
www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname
変更されたメインコントローラー\ 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);
}
}
}
新しいサブコントローラー\ 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();
}
}
レンダリングされたJSON出力
{
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"
}
}
Valentinの答えは良いのですが、既に構築されているコンポーネントに1つまたは2つのajax呼び出しを追加するだけでよい場合は、少し複雑すぎます。個別のファイルcontroller.raw.php
やview.raw.php
ファイルを作成しないで済ませることは完全に可能です。
このajax呼び出しを行うには
index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1
ではjob
サブコントローラ
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();
}
}
バレンティンの答えは良いです。
私はこれのためにエンコーディングとエラー処理を処理するjsonコントローラーを好みます。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();
}
}
このコントローラーは、次のような作業を行うコントローラークラスによって拡張されます。
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();
}
}
次のようにリクエストを呼び出します:
index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1
トークンハッシュは、JSession :: getFormToken()によって生成されます。したがって、完全な完全な呼び出しは次のようになります。
$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);
2番目のパラメーターは「false」に設定されているため、xmlの書き換えなしでjavascript呼び出しでこれを使用できます。
JResponseJson
クラスを使ってそれを処理しないのですか?