web-dev-qa-db-ja.com

AJAXコンポーネントを呼び出す適切な方法は何ですか?

Joomlaのカスタムコンポーネントを開発しています! 3.xでAJAXを呼び出してデータを取得する場合。適切な方法は何ですか?

40
Dmitry Rekun

この回答はすでに数年前のものであり、更新されていないことに注意してください。正確ではないと思われる場合は、自由に編集/コメントしてください。

概要

これに対処するための実際に公式な方法はほとんどありません。それは、複雑さと、MVCパターンに依存して作業をどの程度行うかによって大きく異なります。

以下は、Joomla 2.5および3.xで機能する可能性のあるいくつかの解決策です。コードはコピー-貼り付けジョブではなく、一般的なアイデアとして提示されています。

Joomlaの前に! 3.2以下の例を使用するために必要なのはcomponentだけです。 Joomla 3.2(より複雑なタスク用)以降では、モジュールとプラグインからのリクエストを処理できます。


Generic HTML response(following legacy MVC)

タスクの[〜#〜] url [〜#〜]は次のようにする必要があります。

_index.php?option=com_similar&task=abc&format=raw_

次に、ビューを使用するコントローラーを作成します。たとえば、view.raw.htmlファイル(通常のビューファイルと同じ)を含むAbcとしましょう。

以下は、生の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リクエストをsubcontrollerに送信すると、次のようになります。

_index.php?option=com_similar&controller=abc&format=raw_

(rawビューの)サブコントローラー名は_abc.raw.php_である必要があります。

これは、Abcという名前の2つのサブコントローラーがある/する可能性があることも意味します。

JSONを返す場合は、_format=json_および_abc.json.php_を使用するのが理にかなっています。 Joomla 2.5で。このオプションが機能するためにいくつかの問題があった(どういうわけか出力が破損した)ため、そのまま使用しました。


有効なJSON応答(新規/従来のMVCに続く)

有効な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! Ajaxインターフェース

Joomla 3.2の新機能! -コンポーネントをビルドせずにハンドルリクエストを作成できるようになりました

Joomla!Ajaxインターフェース -Joomlaは、プラグインまたはモジュールでAjaxリクエストを処理する軽量な方法を提供するようになりました。 Joomlaを使いたいかもしれません!コンポーネントがまだない場合、またはすでに持っているモジュールからリクエストを行う必要がある場合は、Ajaxインターフェース。

47
Valentin Despa

これは非常によく回答された質問に対する遅い回答ですが、AJAX呼び出しでコンポーネントのデータにアクセスする簡単な方法が必要な場合のために、この簡単な解決策を追加したいと思いました。

Joomlaのすべてのバージョン、サードパーティの可能性、グーグルで数日かけて見つけたハッキン​​グで、これは私が思いつくことができる最も簡単なアプローチでした-フィードバックは間違いなく高く評価されています。

  1. 既存のメインコントローラに関数executeを追加しました
  2. AJAXで呼び出したいタスクのパブリック関数を持つサブコントローラーを作成しました
  3. 組み込みのJoomla JResponseJsonクラスを使用して出力を処理しました(それは本当にいいです!

タスクを呼び出す/実行する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"
    }
}
20
GDP

バレンティンの答えは良いですが、すでに構築されているコンポーネントに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();
    }
}
11
Spunkie

バレンティンの答えは良いです。

私はこのためにエンコーディングとエラー処理を処理する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呼び出しでこれを使用できます。

7
Harald Leithner

Javascript出力を追加するサードパーティのプラグインがないと100%確信している場合は、純粋なjson_encodeで問題ありません。

しかし...たとえば、JomSocialはサイト全体に「」を追加します。

だから...便利なトリック、json_encodeをタグでラップし、JavaScript側で処理します。

echo '@START@' . json_encode(...) . '@END@';
4
Anibal

タスクでコントローラー名を使用して、コントローラーに直接アクセスできます。

index.php?option=com_similar&task=controller.abc&format=raw

呼び出します:controller.raw.php(戻り値はraw)

index.php?option=com_similar&task=controller.abc

呼び出します:controller.php(die;を使用しない場合、戻り値はhtmlです)

3
Dennis Heiden