it-swarm-tr.com

Bileşende bir AJAX çağrı yapmanın uygun yolu nedir?

Joomla! İçin özel bir bileşen geliştiriyorum! 3.x ve bazı verileri almak için içine bir AJAX çağrı yapmak istiyorum.

40
Dmitry Rekun

BU CEVAPIN zaten birkaç yaşında olduğunu ve güncellenmediğini LÜTFEN DİKKAT EDİN. Bir şeyin artık kesin olmadığını düşünüyorsanız, düzenleme/yorum yapmaktan çekinmeyin.

Öz

Bununla başa çıkmak için neredeyse resmi bir yol yoktur, bu çok karmaşıklığa ve işi yapmak için MVC modeline ne kadar güvenmek istediğinize bağlıdır.

Aşağıda Joomla 2.5 ve 3.x'te çalışması gereken bazı olası çözümler bulunmaktadır. Kod bir kopyala yapıştır işi için değil genel bir fikir olarak sunulur.

Joomla! 3.2 Aşağıdaki örnekleri kullanmanız gereken tek şey component. Joomla 3.2'den (daha düşük karmaşık işler için) sonra modüllerden ve eklentilerden gelen istekleri işleyebilirsiniz.


Genel HTML yanıtı (eski MVC'yi izleyerek)

Görev için [~ # ~] url [~ # ~] şunun gibi görünmesi gerekir:

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

Görünümü kullanacak bir denetleyici oluşturmaktan ziyade, diyelim Abc, ve view.raw.html dosyasını (normal bir görünüm dosyasıyla aynı) içerecektir.

Aşağıda ham bir HTML yanıtı oluşturmak için kod var:

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

/görünümler/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);
    }
}

/görüntüleme/abc/tmpl/default.php

<?php

echo "Hello World from /views/abc/tmpl/default.php";

Not: Bu, HTML döndürmek zorunda kalırsam kullanacağım çözümdür (daha temiz ve Joomla mantığını izler). Basit JSON verilerini döndürmek için, her şeyi denetleyiciye nasıl yerleştireceğinize bakın.

Alt kontrol

Ajax isteğinizi aşağıdaki gibi bir alt denetleyiciye yaparsanız:

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

Alt denetleyici adınızın (ham görünüm için) abc.raw.php Olması gerekir.

Bu ayrıca Abc adında 2 alt denetleyicinizin olacağı/olabileceğiniz anlamına gelir.

JSON döndürürseniz, format=json Ve abc.json.php Kullanmak mantıklı olabilir. Joomla 2.5. Bu seçeneği (bazı şekilde çıktı bozuk) çalışmak için bazı sorunlar vardı, bu yüzden ham kullanılır.


Geçerli JSON Yanıtı (yeni/eski MVC'yi izleyen)

geçerli bir JSON yanıtı oluşturmanız gerekiyorsa , dokümanlar sayfasına bakın JSON çıktısı oluşturma

// 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);

Genellikle bu kodu denetleyiciye koyarsınız (kodladığınız verileri döndürecek bir modeli çağıracaksınız - çok yaygın bir senaryo). Daha ileri götürmeniz gerekiyorsa, ham örneğe benzer bir JSON görünümü de oluşturabilirsiniz (view.json.php).


Güvenlik

Artık Ajax isteği çalışıyor, henüz sayfayı kapatmayın. Alttarafı oku.

Talep sahtekarlığını kontrol etmeyi unutmayın. JSession::checkToken() burada işe yarar. Formlara CSRF kimlik sahtekarlığı nasıl eklenir ile ilgili belgeleri okuyun


Çok dilli siteler

Dil adını istekte göndermezseniz, Joomla istediğiniz dil dizelerini çevirmeyebilir.

İsteğinize bir şekilde lang parametresi eklemeyi düşünün (&lang=de Gibi).


Joomla! Ajax Arayüzü

Joomla 3.2'de yeni! - bir bileşen oluşturmadan tanıtıcı istekleri yapabilmenizi sağladı

Joomla! Ajax Arayüzü - Joomla artık bir eklenti veya modülde Ajax talebini işlemek için hafif bir yol sunuyor. Joomla! 'Yı kullanmak isteyebilirsiniz. Henüz bir bileşeniniz yoksa veya zaten sahip olduğunuz bir modülden istek yapmanız gerekiyorsa Ajax Arayüzü.

47
Valentin Despa

Bu çok iyi cevaplanan soru için geç bir cevap, ama ben sadece AJAX çağrısı ile bileşenlerinin verilerine ulaşmak için basit bir yol ihtiyacı olanlar için bu kesip-kovalanan çözüm eklemek istedim.

Tüm Joomla sürümleri, 3. taraf olasılıkları ve birkaç günlük googling'de bulduğum hack'lerle, bu benim bulabileceğim en basit yaklaşımdı - ve geri bildirim kesinlikle takdir ediliyor.

  1. Mevcut ana denetleyicime execute işlevi eklendi
  2. AJAX ile aramak istediğim görev (ler) için genel işlevli bir alt denetleyici oluşturuldu
  3. Çıktıyı işlemek için yerleşik Joomla JResponseJson sınıfını kullandı ( Gerçekten güzel! )

Görevi çağırmak/yürütmek için URL:

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

Değiştirilmiş Ana Denetleyici\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);
        }
    }
}

Yeni Alt Denetleyici\com_example\denetleyiciler\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();
    }
}

İşlenmiş JSON Çıkışı

{
    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

Valentin yanıtı iyidir, ancak yapmanız gereken tek şey önceden oluşturulmuş bir bileşene 1 veya 2 ajax çağrısı eklemekse biraz fazla karmaşıktır. Ayrı controller.raw.php Veya view.raw.php Dosyaları oluşturmamanız tamamen mümkündür.

Bu ajax çağrısı yapmak için

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

job alt denetleyicisinde

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

Valentin'in cevabı iyi.

Ben bunun için kodlama ve hata işleme işleyen bir json denetleyicisi tercih json temel sınıf yarattı:

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

}

Bu denetleyici, işi yapan denetleyici sınıfı tarafından genişletilir, şöyle bir şey:

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

ve isteği şöyle çağırırsınız:

index.php?option=com_component&task=address.get&format=json&id=1234&tokenhash=1

Jeton karması JSession :: getFormToken () tarafından oluşturulur. Yani tam bir çağrı şöyle görünebilir:

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

İkinci parametre "false" olarak ayarlanmıştır, bu nedenle xml yeniden yazmadan javascript çağrılarında kullanabilirsiniz.

7
Harald Leithner

Herhangi bir Javascript çıktısı ekleyen hiçbir üçüncü taraf eklentisi olmadığından% 100 eminseniz, saf bir json_encode Tamam çalışır.

Ama ... örneğin JomSocial tüm siteye "" ekler.

Yani ... kullanışlı bir hile, json_encode ile etiketleri sarın ve Javascript tarafında işleyin.

echo '@[email protected]' . json_encode(...) . '@[email protected]';
4
Anibal

Bir denetleyiciye görevdeki denetleyici adını kullanarak doğrudan erişebilirsiniz:

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

arayacak: controller.raw.php (dönüş ham)

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

arayacak: controller.php (die; kullanmıyorsanız dönüş html'dir)

3
Dennis Heiden