Выполнение task при отсутствии метода в контроллере на бэкэнде

Заметил непонятную мне вещь:
Создал свой компонент. В админке всё сделал по стандарту - в toolbar есть команда "удалить", на ней висит вызов:
Joomla.submitbutton('_chado_app_data.delete')

Т.е., оно должно пойти в контроллер _chado_app_data.php, найти там метод delete() и сделать, что он скажет. Верно ведь?
Он и делает, т.е., удаляет данные. Проблема, однако, в том, что контроллер НЕ СОДЕРЖИТ такого метода. При этом контроллер загружается, как и должен (я проверял, выставив в файле die('controller_name') для чистоты эксперимента.
Но метода delete(), как я уже отметил, там нет. Единственное, что я могу предположить, это то, что, не находя его (метода с этим именем), оно идёт дальше, и ищет его в модели (там он есть) и, если находит, вызывает.
Буду одинаково рад услышать как подтверждение, так и опровержение своей гипотезы.
С нетерпением жду заключения экспертов! :)
no image

Аноним

30 января, 09:40
890

Нет комментариев

Добавить комментарий
Вы не можете оставлять комментарии. Чтобы добавить комментарий, залогиньтесь или зарегистрируйтесь
Вы не можете голосовать. Чтобы проголосовать, залогиньтесь или зарегистрируйтесь

1 ответ

Вот тут получается ссылка на класс таблицы

/**
* Модель HelloWorld.
*/

class HelloWorldModelHelloWorld extends JModelAdmin
{
   /**
   * Возвращает ссылку на объект таблицы, всегда его создавая.
   *
   * @param    type    Тип таблицы для подключения.
   * @param    string    Префикс класса таблицы. Необязателен.
   * @param    array    Конфигурационный массив. Необязателен.
   *
   * @return JTable Объект JTable.
   */

   public function getTable($type = 'HelloWorld', $prefix = 'HelloWorldTable', $config = array())
   {
      return JTable::getInstance($type, $prefix, $config);
   }
//...
}


По умолчанию он стандартный но можно переопределить его в /administrator/com_catalog/tables/helloworld.php

// No direct access to this file
defined('_JEXEC') or die('Restricted access');

jimport('joomla.database.table');

/**
 * HelloWorld Model
 */

class HelloWorldTable extends JTable
{
        function __construct(&$_db)
        {
                parent::__construct('#__table_name', 'id_key', $_db);
        }
       
        function check(){
                if(!$this->introtext){
                        $this->setError(JText::_('Intro text can not be empty'));
                        return false;
                }
                return true;
        }
       
        function store($updateNulls = false)
        {
               
                $data = JRequest::getVar('jform', array(), 'post', 'array');
               
                $this->set('introtext', $data['introtext']);
                $this->set('fulltext',  $data['fulltext']);
               
                foreach( $this->images as $i => $url ){
                        if( trim($url) == '' ){
                                unset($this->images[$i]);
                        }
                }
               
                $this->images = @implode("::", $this->images);
               
                parent::store($updateNulls);
               
                return count($this->getErrors())==0;
               
        }
}
        Сократил как мог видимо переборщил :)<br>

Попробую объяснить подробнее.
Joomla в админке передает постом переменную task (например helloworld.delete) из туллбара.
Затем метод dispatch($component = null) в классе JAdministrator

public function dispatch($component = null)
{
  try
  {
    if ($component === null) {
      $component = JAdministratorHelper::findOption();
    }

    $document  = JFactory::getDocument();
    $user    = JFactory::getUser();

    switch ($document->getType()) {
      case 'html':
        $document->setMetaData('keywords', $this->getCfg('MetaKeys'));
        break;

      default:
        break;
    }

    $document->setTitle($this->getCfg('sitename'). ' - ' .JText::_('JADMINISTRATION'));
    $document->setDescription($this->getCfg('MetaDesc'));
    $document->setGenerator('Joomla! - Open Source Content Management');

    $contents = JComponentHelper::renderComponent($component);
    $document->setBuffer($contents, 'component');

    // Trigger the onAfterDispatch event.
    JPluginHelper::importPlugin('system');
    $this->triggerEvent('onAfterDispatch');
  }
  // Mop up any uncaught exceptions.
  catch (Exception $e)
  {
    $code = $e->getCode();
    JError::raiseError($code ? $code : 500, $e->getMessage());
  }
}



вот тут "JComponentHelper::renderComponent($component)" все просто инклудится файл "/administrator/components/com_helloworld/helloworld.php"


// No direct access to this file
defined('_JEXEC') or die('Restricted access');
 
// import joomla controller library
jimport('joomla.application.component.controller');
 
// Get an instance of the controller prefixed by HelloWorld
$controller = JController::getInstance('HelloWorld');
 
// Perform the Request task
$controller->execute(JRequest::getCmd('task'));
 
// Redirect if set by the controller
$controller->redirect();



class JController метод getInstance($prefix, $config = array())
есть такая строка
$class = ucfirst($prefix) . 'Controller' . ucfirst($type); // получается HelloworldControllerHelloworlds, $type берется первая часть из переменной $task - 'helloworlds.delete'.
дальше 2 пути один в при сохранении сортировки и некоторых других методах (class HelloworldControllerHelloworld extends JControllerForm), второй (class HelloworldControllerHelloworlds extends JControllerAdmin) там есть метод удаления


// No direct access to this file
defined('_JEXEC') or die('Restricted access');
 
// import Joomla controllerform library
jimport('joomla.application.component.controllerform');
 
/**
 * HelloWorld Controller
 */

class HelloworldControllerHelloworlds extends JControllerForm
{
}


extends JControllerForm вот тут class JControllerForm extends JController и мы возвращаемся в метод $controller->execute(JRequest::getCmd('task'));

public function execute($task)
{
  $this->task = $task;
   
  $task = strtolower($task);
  if (isset($this->taskMap[$task]))
  {
    $doTask = $this->taskMap[$task];
  }
  elseif (isset($this->taskMap['__default']))
  {
    $doTask = $this->taskMap['__default'];
  }
  else
  {
    return JError::raiseError(404, JText::sprintf('JLIB_APPLICATION_ERROR_TASK_NOT_FOUND', $task));
  }

  // Record the actual task being fired
  $this->doTask = $doTask;
   
  // Make sure we have access
  if ($this->authorise($doTask))
  {
    $retval = $this->$doTask();
    return $retval;
  }
  else
  {
    return JError::raiseError(403, JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'));
  }
}


вот тут "$retval = $this->$doTask();" вызовется метод save() в классе JControllerForm есть метод save()
далее $model = $this->getModel(); класс HelloworldModelHelloworld extends JModelAdmin
в классе JModelAdmin есть методы получающие объект таблицы и выполняющие все что нужно.

и второй класс


// No direct access to this file
defined('_JEXEC') or die('Restricted access');
 
// import Joomla controlleradmin library
jimport('joomla.application.component.controlleradmin');
 
/**
 * HelloWorlds Controller
 */

class HelloworldControllerHelloworlds extends JControllerAdmin
{
  /**
   * Proxy for getModel.
   * @since  2.5
   */

  public function getModel($name = 'Helloworld', $prefix = 'HelloworldModel')
  {
    $model = parent::getModel($name, $prefix, array('ignore_request' => true));
    return $model;
  }
}


наследуется от JControllerAdmin

public function delete()
{
  // Check for request forgeries
  JSession::checkToken() or die(JText::_('JINVALID_TOKEN'));

  // Get items to remove from the request.
  $cid = JRequest::getVar('cid', array(), '', 'array');

  if (!is_array($cid) || count($cid) < 1)
  {
    JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED'));
  }
  else
  {
    // Get the model.
    $model = $this->getModel();

    // Make sure the item ids are integers
    jimport('joomla.utilities.arrayhelper');
    JArrayHelper::toInteger($cid);

    // Remove the items.
    if ($model->delete($cid))
    {
      $this->setMessage(JText::plural($this->text_prefix . '_N_ITEMS_DELETED', count($cid)));
    }
    else
    {
      $this->setMessage($model->getError());
    }
  }

  $this->setRedirect(JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list, false));
}



фух, можно выдохнуть :)

30 января, 09:40

Нет комментариев

Добавить комментарий
Вы не можете отвечать на вопросы. Чтобы ответить на вопрос, пожалуйста залогиньтесь или зарегистрируйтесь
Работа в Украине
Вакансии от WORK.ua
Печатник цифровой и струйной печати, 6000 грн.
Харьков, Астра Мультимедиа, ООО
Project manager
Киев, Ajax Systems
Контент-менеджер (MS Excel)
Николаев (Николаевская обл.), Nexteum
Програміст 1С
Хмельницкий, Vitagro, група компаній
Системный администратор, 10000 грн.
Одесса, Інбудторг, ПП
Junior Email Marketing Specialist
Одесса, Nexteum