AJAX araması yapmak için bileşenin doğru yolu nedir?


40

Joomla! İçin özel bir bileşen geliştiriyorum. 3.x ve bazı verileri almak için içinde AJAX araması yapmak istiyor. Bunu yapmanın doğru yolu nedir?


Önemli bir tavsiye asla Joomla'nın akışını bozmaz. Örneğin, birkaç bileşen istenirseAfterRoute olayına istek verir ve görevi burada gerçekleştirir ve isteği kendisi öldürür. Bu hata ayıklamak zor hatalara neden olur.
Shyam

Yani - Bir Uygulamayı kapatmıyor musunuz? Daha fazla detay verebilir misiniz?
Dmitry Rekun

Evet, joomla uygulamayı kapatırsa, en iyisi olacaktır. Böylece, uzantınızın genişletilebilirliği korunacaktır.
Shyam

Hala tam olarak anlamıyorum. Bahsettiğim şey denetleyicideki $ app-> close (). Aynı mı demek istiyorsun? :)
Dmitry Rekun

Evet, aynı konu hakkında konuşuyorum. Joomla'nın kendisi tarafından neden yapılacaksa, denetleyicideki uygulamayı neden kapatmalıyız?
Shyam

Yanıtlar:


47

LÜTFEN BU CEVAP LÜTFEN zaten birkaç yaşında ve güncellenmedi. Bir şeyin artık kesin olmadığını düşünüyorsanız, düzenlemek / yorum yapmaktan çekinmeyin.

Soyut, Özet

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

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

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


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

Sizin URL görev için böyle bir görünüm gerekir:

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

AbcView.raw.html (normal bir görüntüleme dosyasıyla aynı) dosyasını içerecek olan görünümü kullanacak olan denetleyiciyi oluşturmaktan çok diyelim .

Ham bir HTML yanıtı oluşturmak için kodunuzun altında:

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

Not: HTML'yi döndürmek zorunda kalsam kullanacağım çözüm budur (daha temiz ve Joomla mantığını izler). Basit JSON verilerini döndürmek için, her şeyi kontrol ünitesine nasıl koyacağınıza bakınız.

alt kontrol

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

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

Alt denetleyicinizin adından (işlenmemiş görünüm için) olması gerekir abc.raw.php.

Bu aynı zamanda Abc adında 2 alt denetleyiciye sahip olabileceğiniz / olabileceğiniz anlamına gelir.

Eğer JSON dönerseniz, kullanımı mantıklı olabilir format=jsonve abc.json.php. Joomla 2.5'te. Bu seçeneğin çalışması için bazı sorunlar yaşadım (bir şekilde çıktı bozuldu), bu yüzden ham kullandım.


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

Geçerli bir JSON yanıtı oluşturmanız gerekiyorsa , JSON çıktısını oluşturma belgesini inceleyin.

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

Bu kodu genellikle denetleyiciye koyarsınız (kodladığınız verileri döndürecek bir model arayacaksınız - çok yaygın bir senaryo). Daha ileri gitmeniz gerekiyorsa, ham örneğe benzer bir JSON görünümü de (view.json.php) oluşturabilirsiniz.


Güvenlik

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

Sahtecilik talebini kontrol etmeyi unutma. JSession::checkToken()burada işe yarayacak. CSRF anti-spoofing forma ekleme hakkında belgeleri okuyun.


Çok dilli siteler

İstekte dil adını göndermezseniz, Joomla istediğiniz dil dizelerini çevirmez.

İsteğinize bir şekilde lang paramını eklemeyi düşünün (gibi &lang=de).


Joomla! Ajax Arabirimi

Joomla 3.2'deki Yenilikler! - bir bileşen oluşturmadan işlem istekleri yapmanızı sağlar

Joomla! Ajax Arabirimi - Joomla artık bir eklenti veya modülde Ajax isteğini yerine getirmenin hafif bir yolunu sunuyor. Joomla !'yı kullanmak isteyebilirsiniz. Ajax Arayüzü, eğer zaten bir bileşeniniz yoksa veya sahip olduğunuz bir modülden istekte bulunmanız gerekiyorsa.


9
Joomla.stackexchange.com sitesinde gördüğüm en iyi kalite cevabı - çok iyi bir şekilde yapıldı ve çıtayı yükseltmenin yolu. Mükemmel iş!
NivF007

Katılıyorum, peki ya JRequest? $this->inputV3.x kullandığımdan beri öyle olmalı mı?
Dmitry Rekun

1
Endişenizi dile getirdim JRequest. Teşekkürler
Valentin Despa

3
Güzel cevap, sadece JSON çıkışını ele alan 3.1'den beri bir Joomla sınıfı olduğunu
söylemek istedim

@ fl0r yeap, Valentin Valid JSON Responsebölümde bahsetti .
Dmitry Rekun

20

Bu çok iyi cevaplanmış bir soru için geç bir cevap, ancak bir AJAX çağrısı ile bileşenlerinin verilerine ulaşmak için basit bir yol arayanlar için bu kısaltmaya hazır çözümü eklemek istedim.

Tüm Joomla sürümleri, 3. parti olanakları ve birkaç gün süren googling ile ilgili bulduğum hack'lerle, bulabildiğim en basit yaklaşım buydu - ve geri bildirimler kesinlikle takdir edildi.

  1. executeMevcut ana denetleyicime işlev eklendi
  2. AJAX ile çağırmak istediğim görev (ler) için ortak işlevli bir alt kontrolör yarattı
  3. Çıktıyı işlemek için yerleşik Joomla JResponseJson sınıfında kullanıldı ( gerçekten güzel! )

Görevi aramak / 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 \ 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();
    }
}

Render 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"
    }
}

11

Valentin cevabı iyidir, ancak yapmanız gereken tek şey hali hazırda inşa edilmiş bir bileşene 1 veya 2 ajax çağrısı eklemekse, biraz fazla karmaşıktır. Ayrı controller.raw.phpveya view.raw.phpdosya yapmadan kurtulmak mükemmel bir şekilde mümkün .

Ajax araması yapmak için

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

Alt jobkontrolörde

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

Valentin'in cevabı iyidir.

Bir json temel sınıfı oluşturduğum için kodlama ve hata işlemeyi yapan bir json denetleyicisini tercih ediyorum:

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:

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 sen buna benzer bir istek diyorsun:

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

Belirteç karma JSession :: getFormToken () tarafından üretilir. Yani tam arama aşağıdaki gibi 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 yüzden bunu xml rewrite olmadan javascript çağrılarında kullanabiliriz.


1
Güzel, ama neden JResponseJsonsınıfı idare etmek için kullanmıyorsun ?
Dmitry Rekun

JResponseJson Joomla 3'te tanıtıldı
Anibal


4

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

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

Yani ... kullanışlı bir numara, json_encode'u etiketlerle sarın ve Javascript tarafında işleyin.

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

3

Görevdeki denetleyici adını kullanarak doğrudan denetleyiciye 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 (eğer kullanmazsanız return html olur die;)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.