घटक में AJAX कॉल करने का उचित तरीका क्या है?


40

मैं जूमला के लिए एक कस्टम घटक विकसित कर रहा हूं! 3.x और कुछ डेटा पुनः प्राप्त करने के लिए इसके अंदर एक AJAX कॉल करना चाहते हैं। इसे करने का उचित तरीका क्या है?


महत्वपूर्ण सलाह जूमला के प्रवाह को कभी नहीं तोड़ती है। उदाहरण के लिए कुछ घटक isten ajax request onAfterRoute ईवेंट और कार्य करते हैं और यहां अनुरोध को ही मार देते हैं। इसके कारण त्रुटियां हैं जो डीबग करना कठिन हैं।
श्याम

क्या आपका मतलब है - एक ऐप को बंद न करें? क्या आप अधिक विस्तृत कर सकते हैं?
दिमित्री रेकुन

हां, अगर जूमला ऐप को बंद करता है, तो यह सबसे अच्छा होगा। तो आपके एक्सटेंशन की एक्स्टेंसिबिलिटी बनी रहेगी।
श्याम

अभी भी पूरी तरह से समझ नहीं आ रहा है। क्या मैं बात कर रहा हूँ $ app-> करीब () नियंत्रक में है। क्या आपका भी यही मतलब है? :)
दिमित्री रीकुन

हां, उसी बिंदु पर बात करते हुए। हमें नियंत्रक में ऐप क्यों बंद करना चाहिए, जबकि जूमला द्वारा ही किया जाएगा।
श्याम

जवाबों:


47

कृपया ध्यान दें कि यह उत्तर पहले से ही कुछ साल पुराना है और अद्यतन नहीं किया गया था। अगर आपको लगता है कि कुछ ठीक नहीं है, तो संपादित करें / टिप्पणी के लिए स्वतंत्र महसूस करें।

सार

इससे निपटने का लगभग कोई आधिकारिक तरीका नहीं है, यह बहुत जटिलता पर निर्भर करता है और आप काम करने के लिए एमवीसी पैटर्न पर कितना भरोसा करना चाहते हैं।

नीचे कुछ संभावित उपाय दिए गए हैं जो जूमला 2.5 और 3.x में काम करना चाहिए। कोड को कॉपी पेस्ट नौकरी के लिए प्रस्तुत नहीं किया जाता है, बल्कि एक सामान्य विचार के रूप में प्रस्तुत किया जाता है।

जुमला से पहले! 3.2 केवल एक चीज जिसे आपको नीचे दिए गए उदाहरणों का उपयोग करने की आवश्यकता है, एक है component। जूमला 3.2 (कम जटिल कार्यों के लिए) के बाद आप मॉड्यूल और प्लगइन्स के अनुरोध को संभाल सकते हैं।


जेनेरिक HTML प्रतिक्रिया (विरासत MVC के बाद)

कार्य के लिए आपका 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 लौटना है (यह क्लीनर है और जूमला तर्क का अनुसरण करता है)। साधारण JSON डेटा वापस करने के लिए, नियंत्रक में सब कुछ कैसे रखा जाए, नीचे देखें।

Subcontrollers

यदि आप अपने अजाक्स को उप- नियंत्रक से अनुरोध करते हैं , जैसे:

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

अपने उपमहाद्वीप के नाम (कच्चे दृश्य के लिए) से अधिक होना चाहिए abc.raw.php

इसका मतलब यह भी है कि आपके पास एबीसी नाम के 2 उप-नियंत्रक होंगे।

यदि आप JSON लौटाते हैं, तो इसका उपयोग करने के लिए समझ में आ सकता है format=jsonऔर abc.json.php। जूमला 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) भी बना सकते हैं।


सुरक्षा

अब जब अजाक्स अनुरोध काम कर रहा है, तब भी पृष्ठ को बंद न करें। नीचे दिया गया पढ़ें।

अनुरोध forgeries के लिए जाँच करने के लिए मत भूलना। JSession::checkToken()यहाँ आ जाओ। CSRF को एंटी-स्पूफिंग फॉर्म में कैसे जोड़ा जाए, इस पर प्रलेखन पढ़ें


बहुभाषी साइटें

ऐसा हो सकता है कि यदि आप अनुरोध में भाषा का नाम नहीं भेजते हैं, तो जूमला आपके द्वारा इच्छित भाषा तार का अनुवाद नहीं करेगा।

किसी भी तरह अपने अनुरोध (जैसे &lang=de) के लिए लंब परम अपील करने पर विचार करें ।


जूमला! अजाक्स इंटरफ़ेस

जूमला 3.2 में नया! - आप एक घटक के निर्माण के बिना संभाल अनुरोध करने के लिए सक्षम है

जूमला! अजाक्स इंटरफ़ेस - जुमला अब एक प्लगइन या मॉड्यूल में अजाक्स अनुरोध को संभालने के लिए एक हल्का तरीका प्रदान करता है। आप जूमला का उपयोग करना चाह सकते हैं! Ajax इंटरफ़ेस यदि आपके पास पहले से कोई घटक नहीं है या यदि आपके पास पहले से मौजूद मॉड्यूल से अनुरोध करने की आवश्यकता है।


9
सबसे अच्छी गुणवत्ता का उत्तर मैंने अभी तक joomla.stackexchange.com पर देखा है - अच्छी तरह से किया और बार को बढ़ाने का तरीका। बहुत ही उत्तम कार्य!
NivF007

सहमत हूँ, लेकिन किस बारे में JRequest? $this->inputजब मैं v3.x का उपयोग करता हूं, तो यह पदावनत होना चाहिए ?
दिमित्री रेकुन

1
मैंने आपकी चिंता को संबोधित किया JRequest। धन्यवाद
वैलेन्टिन Despa

3
अच्छा जवाब, बस यह उल्लेख करना चाहता था कि 3.1 से एक जूमला वर्ग है जो JSON आउटपुट को संभालता है: API , उपयोग
fruppel

@ fl0r yeap, वैलेंटाइन ने Valid JSON Responseअनुभाग में इसका उल्लेख किया है ।
दिमित्री रेकुन

20

यह बहुत अच्छी तरह से पूछे गए प्रश्न के लिए एक देर से जवाब है, लेकिन मैं उन लोगों के लिए इस कट-टू-चेस समाधान को जोड़ना चाहता था, जिन्हें बस AJAX कॉल के साथ अपने घटकों के डेटा को प्राप्त करने के लिए एक सरल तरीका चाहिए।

सभी जूमला संस्करणों के साथ, 3 पार्टी की संभावनाएं, और हैक जो मुझे कई दिनों के गोग्लिंग में मिले, यह सबसे सरल दृष्टिकोण था जिसके साथ मैं आ सकता था - और प्रतिक्रिया की सराहना की गई है।

  1. executeमेरे मौजूदा मुख्य नियंत्रक में फ़ंक्शन जोड़ा गया
  2. टास्क (ओं) के लिए एक सार्वजनिक समारोह के साथ एक उप-नियंत्रक बनाया, जिसे मैं AJAX के साथ कॉल करना चाहता था
  3. आउटपुट को संभालने के लिए Joomla JResponseJson वर्ग में निर्मित का उपयोग किया ( यह वास्तव में अच्छा है! )

कार्य को कॉल / निष्पादित करने के लिए URL:

www.mysite.com/index.php?option=com_example&task=ForAjax.mytaskname

संशोधित मुख्य नियंत्रक \ com_example \ नियंत्रक.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 \ नियंत्रकों \ 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"
    }
}

11

वैलेंटाइन का उत्तर अच्छा है, लेकिन थोड़ा अधिक जटिल है अगर आपको बस इतना करना है कि पहले से निर्मित एक घटक में 1 या 2 अजाक्स कॉल जोड़ें। यह अलग controller.raw.phpया view.raw.phpफ़ाइलों को नहीं बनाने के साथ दूर होने के लिए पूरी तरह से संभव है ।

इस अजाक्स कॉल करने के लिए

index.php?format=raw&option=com_example&controller=job&task=keep_alive&tokenhash=1

में jobsubcontroller

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();
    }
}

7

वैलेंटाइन का जवाब अच्छा है।

मैं एक json नियंत्रक पसंद करता हूँ जो एन्कोडिंग और एरर हैंडलिंग को हैंडल करता है इसके लिए मैंने json base class बनाया है:

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

टोकन हैश जेसेशन द्वारा प्राप्त किया जाता है :: getFormToken ()। तो पूरा पूरा कॉल इस तरह दिख सकता है:

$link = JRoute::_('index.php?option=com_component&task=address.get&format=json&id=1234&'.JSession::getFormToken().'=1', false);

दूसरा पैरामीटर "झूठा" पर सेट है, इसलिए हम इसे एक्सएमएल रीराइट के बिना जावास्क्रिप्ट कॉल में उपयोग कर सकते हैं।


1
अच्छा लगा, लेकिन JResponseJsonइसे संभालने के लिए कक्षा का उपयोग क्यों नहीं किया गया?
दिमित्री रेकुन

JResponseJson को Joomla 3
Anibal

कोई जूमला एसई नहीं था जहां मैं पूछ सकता था;)
हैराल्ड लेथनर

4

यदि आप 100% सुनिश्चित हैं कि कोई जावास्क्रिप्ट-आउटपुट प्लगइन नहीं है, तो किसी भी जावास्क्रिप्ट आउटपुट को जोड़ने पर, शुद्ध json_encode ठीक काम करता है।

लेकिन ... उदाहरण के लिए JomSocial पूरी साइट पर "" जोड़ता है।

तो ... टैग्स के साथ एक आसान ट्रिक, json_encode लपेटें और इसे जावास्क्रिप्ट पक्ष पर संसाधित करें।

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

3

आप कार्य में नियंत्रक नाम का उपयोग करके किसी नियंत्रक को सीधे एक्सेस कर सकते हैं:

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

कॉल करेगा: कंट्रोलर। क्र.फपी (रिटर्न कच्चा है)

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

कॉल करेगा: कंट्रोलर। एफपी (यदि आप उपयोग नहीं करते हैं तो रिटर्न html है die;)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.