当前位置: 首页 > 知识库问答 >
问题:

Joomla 2.5创建组件并保存数据

壤驷心思
2023-03-14

我一直在使用这个留档(我在网上唯一能找到的)来构建一个组件:http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Introduction

我可以在一定程度上理解它,但它确实缺乏任何定义。我创建的组件在一定程度上工作正常,尽管我有一些更严重的问题。

基本上,我需要组件做的只是加载一个设置区域来设置一些值,并通过它来更改这些值。以下是我所拥有的东西的分类:

表单视图,从数据库加载表单中的数据。用于保存/应用和取消的工具栏设置。

这样加载时不会出现错误,根据我在joomla上找到的所有文档,通过使用模型中连接的JTable初始化JControllerPerform实例,表单的简单保存应该会自动工作。然而,即使在代码中的任何地方都没有对末尾带有s的视图的引用(主视图是tireapi,表单总是重定向到tireapi)。

这将导致500错误,因为没有具有该视图的位置集。文档中确实包含一个视图列表,但是我只需要编辑一行,所以列表是没有意义的。我知道可以将参数设置为组件,而不是创建数据库字段,但是我找不到任何与此相关的文档。

我正在寻找的是如何停止组件重定向到一个不存在的视图,并正确保存数据的方向。留档链接不仅显示示例代码,还描述函数及其工作方式,这将是有益的。

以下是一些代码,请随意指出我可能完全忽略的任何内容(我是创建组件的新手):

蒂雷皮。php:

<?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 TireAPI
$controller = JController::getInstance('TireAPI');

// Get the task
$jinput = JFactory::getApplication()->input;
$task = $jinput->get('task', "", 'STR' );

// Perform the Request task
$controller->execute($task);

// Redirect if set by the controller
$controller->redirect();
?>

控制器。php:

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

// import Joomla controller library
jimport('joomla.application.component.controller');

class TireAPIController extends JController{
    function display($cachable = false){
        // set default view if not set
        $input = JFactory::getApplication()->input;
        $input->set('view', $input->getCmd('view', 'TireAPI'));

        // call parent behavior
        parent::display($cachable);
    }
}
?>

控制器/tireapi.php:

<?php
// No direct access to this file
 defined('_JEXEC') or die('Restricted access');
// import Joomla controllerform library
jimport('joomla.application.component.controllerform');
class TireAPIControllerTireAPI extends JControllerForm{}
?>

型号/tireapi。php:

<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import the Joomla modellist library
jimport('joomla.application.component.modeladmin');
class TireAPIModelTireAPI extends JModelAdmin{
    protected $settings; //define settings

    public function getTable($type = 'TireAPI', $prefix = 'TireAPITable', $config = array()){
        return JTable::getInstance($type, $prefix, $config);
    }

    public function getSettings(){ //grab settings from database
        if(!isset($this->settings)){
            $table = $this->getTable();
            $table->load(1);
            $this->settings = $table;
        }
        return $this->settings;
    }
    public function getForm($data = array(), $loadData = true){
    // Get the form.
        $form = $this->loadForm('com_tireapi.tireapi', 'tireapi',
            array('control' => 'jform', 'load_data' => $loadData));
        if (empty($form)){
            return false;
        }
        return $form;
    }
    protected function loadFormData(){
        // Check the session for previously entered form data.
        $data = JFactory::getApplication()->getUserState('com_tireapi.edit.tireapi.data', array());
        if (empty($data)){
            $data = $this->getSettings();
        }
        return $data;
    }
}
?>

表/tireapi。php:

<?php
// No direct access
defined('_JEXEC') or die('Restricted access');

// import Joomla table library
jimport('joomla.database.table');
class TireAPITableTireAPI extends JTable
{
    function __construct( &$db ) {
        parent::__construct('#__tireapi', 'id', $db);
    }
}
?>

视图/tireapi/视图。html。php:

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

// import Joomla view library
jimport('joomla.application.component.view');

class TireAPIViewTireAPI extends JView{
        function display($tpl = null){

            $form = $this->get('Form');
            $item = $this->get('Settings');

            // Check for errors.
            if(count($errors = $this->get('Errors'))){
                JError::raiseError(500, implode('<br />', $errors));
                return false;
            }
            // Assign data to the view
            $this->item = $item;
            $this->form = $form;

            $this->addToolBar();

            // Display the template
            parent::display($tpl);
        }
        protected function addToolBar() {
            $input = JFactory::getApplication()->input;
            JToolBarHelper::title(JText::_('COM_TIREAPI_MANAGER_TIREAPIS'));
            JToolBarHelper::apply('tireapi.apply');
            JToolBarHelper::save('tireapi.save');
            JToolBarHelper::cancel('tireapi.cancel');
        }
}
?>

视图/tireapi/tmpl/default.php:

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

// load tooltip behavior
JHtml::_('behavior.tooltip');
?>
<form action="<?php echo JRoute::_('index.php?option=com_tireapi&layout=edit&id='.(int) $this->item->id); ?>"
      method="post" name="adminForm" id="tireapi-form">
    <fieldset class="adminform">
            <legend><?php echo JText::_( 'COM_TIREAPI_DETAILS' ); ?></legend>
            <ul class="adminformlist">
    <?php foreach($this->form->getFieldset() as $field): ?>
                    <li><?php echo $field->label;echo $field->input;?></li>
    <?php endforeach; ?>
            </ul>
    </fieldset>
    <div>
        <input type="hidden" name="task" value="tireapi.edit" />
        <?php echo JHtml::_('form.token'); ?>
    </div>
</form>

这些都是我能想到的可能很重要的文件,让我知道我是否应该包括更多。

更新:现在我可以停止重定向问题,但是它不会保存数据。我得到了这个错误:您不允许使用该链接直接访问该页面(#1)。

这是让这个极其基本的管理功能发挥作用的最后一个障碍。有什么想法吗?为了澄清这一点,我通过一个xml文件设置表单,并正确加载,甚至使用数据库中的正确数据填充表单。但是,当我单击“应用”时,它只会将我引导回具有上面列出的错误的表单,而不会保存。

共有2个答案

贺博厚
2023-03-14

这不是一个真正的答案,但你的问题也不是一个真正的问题(我读了三遍)。

复数“s”(tireapis)的东西是什么Joomla!自动做。你可以覆盖它。

我建议您看看核心组件(如com_横幅)。

您需要做的是避免重定向。您应该只有“保存”按钮,这将使您保持在同一页上。而“保存”

司马飞
2023-03-14

您留下的主要问题是您希望它重定向到哪里?默认情况下,Joomla会重定向到列表视图(除非您直接指定列表视图,否则可以在视图名称中添加's')。

您可以通过以下两种方式覆盖此选项:

在控制器(controllers/tireapi.php)中,设置自己的列表视图。我认为你甚至可以提出同样的观点:

function __construct() {
    $this->view_list = 'tireapi';
    parent::__construct();
}

重写save函数以更改保存后发生的重定向(再次在控制器中)。这是通过更改对其他对象自然发生的重定向来实现的:

public function save($key = null, $urlVar = null) {
    $return = parent::save($key, $urlVar);
    $this->setRedirect(JRoute::_('index.php?option=com_tireapi&view=tireapi'));
    return $return;
}

其中一个应该能帮到你。

**更新

要使项目最初签出,您需要更改组件处理未设置视图的方式。现在您只需设置视图,让我们重定向!更新控制器。下面是php。

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

// import Joomla controller library
jimport('joomla.application.component.controller');

class TireAPIController extends JController{
    function display($cachable = false){
        // set default view if not set
        $input = JFactory::getApplication()->input;
        $view = $input->get('view');
        if (!$view) {
            JFactory::getApplication()->redirect('index.php?option=com_tireapi&task=tireapi.edit&id=1');
            exit();
        }

        // call parent behavior
        parent::display($cachable);
    }
}
?>

注意:如果有多人需要编辑此内容,则此操作将非常糟糕,因为如果在保存后将组件重定向回此页面,则系统会在您打开组件时将其签出。因为这样,它将始终签出给最后一个编辑它的人,因此下一个人将无法打开它。如果只有一个人编辑,就可以了。

第二个注意事项:如果你不想入侵结账系统,你也可以在保存过程中忽略它,这基本上是相同级别的入侵。

下面是库/joomla/应用程序/组件/中controllerform.php的保存函数的副本。这是在保存时正常运行的内容(因为从哪里继承。如果项目被签出,我已经删除了支票。所以如果你把它放在你的tireapi.php控制器中,父::保存...位是,它将运行,而你不必费心检查项目(即忽略所有的注释....)。老实说,在你的情况下,你可能可以删除更多的内容,但这就是保存时发生的事情,顺便说一句!)

public function save($key = null, $urlVar = null)
{
    // Check for request forgeries.
    JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

    // Initialise variables.
    $app   = JFactory::getApplication();
    $lang  = JFactory::getLanguage();
    $model = $this->getModel();
    $table = $model->getTable();
    $data  = JRequest::getVar('jform', array(), 'post', 'array');
    $checkin = property_exists($table, 'checked_out');
    $context = "$this->option.edit.$this->context";
    $task = $this->getTask();

    // Determine the name of the primary key for the data.
    if (empty($key))
    {
        $key = $table->getKeyName();
    }

    // To avoid data collisions the urlVar may be different from the primary key.
    if (empty($urlVar))
    {
        $urlVar = $key;
    }

    $recordId = JRequest::getInt($urlVar);

    // Populate the row id from the session.
    $data[$key] = $recordId;

    // The save2copy task needs to be handled slightly differently.
    if ($task == 'save2copy')
    {
        // Check-in the original row.
        if ($checkin && $model->checkin($data[$key]) === false)
        {
            // Check-in failed. Go back to the item and display a notice.
            $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
            $this->setMessage($this->getError(), 'error');

            $this->setRedirect(
                JRoute::_(
                    'index.php?option=' . $this->option . '&view=' . $this->view_item
                    . $this->getRedirectToItemAppend($recordId, $urlVar), false
                )
            );

            return false;
        }

        // Reset the ID and then treat the request as for Apply.
        $data[$key] = 0;
        $task = 'apply';
    }

    // Access check.
    if (!$this->allowSave($data, $key))
    {
        $this->html" target="_blank">setError(JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
        $this->setMessage($this->getError(), 'error');

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

        return false;
    }

    // Validate the posted data.
    // Sometimes the form needs some posted data, such as for plugins and modules.
    $form = $model->getForm($data, false);

    if (!$form)
    {
        $app->enqueueMessage($model->getError(), 'error');

        return false;
    }

    // Test whether the data is valid.
    $validData = $model->validate($form, $data);

    // Check for validation errors.
    if ($validData === false)
    {
        // Get the validation messages.
        $errors = $model->getErrors();

        // Push up to three validation messages out to the user.
        for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++)
        {
            if ($errors[$i] instanceof Exception)
            {
                $app->enqueueMessage($errors[$i]->getMessage(), 'warning');
            }
            else
            {
                $app->enqueueMessage($errors[$i], 'warning');
            }
        }

        // Save the data in the session.
        $app->setUserState($context . '.data', $data);

        // Redirect back to the edit screen.
        $this->setRedirect(
            JRoute::_(
                'index.php?option=' . $this->option . '&view=' . $this->view_item
                . $this->getRedirectToItemAppend($recordId, $urlVar), false
            )
        );

        return false;
    }

    // Attempt to save the data.
    if (!$model->save($validData))
    {
        // Save the data in the session.
        $app->setUserState($context . '.data', $validData);

        // Redirect back to the edit screen.
        $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()));
        $this->setMessage($this->getError(), 'error');

        $this->setRedirect(
            JRoute::_(
                'index.php?option=' . $this->option . '&view=' . $this->view_item
                . $this->getRedirectToItemAppend($recordId, $urlVar), false
            )
        );

        return false;
    }

    // Save succeeded, so check-in the record.
    if ($checkin && $model->checkin($validData[$key]) === false)
    {
        // Save the data in the session.
        $app->setUserState($context . '.data', $validData);

        // Check-in failed, so go back to the record and display a notice.
        $this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
        $this->setMessage($this->getError(), 'error');

        $this->setRedirect(
            JRoute::_(
                'index.php?option=' . $this->option . '&view=' . $this->view_item
                . $this->getRedirectToItemAppend($recordId, $urlVar), false
            )
        );

        return false;
    }

    $this->setMessage(
        JText::_(
            ($lang->hasKey($this->text_prefix . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS')
                ? $this->text_prefix
                : 'JLIB_APPLICATION') . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS'
        )
    );

    // Redirect the user and adjust session state based on the chosen task.
    switch ($task)
    {
        case 'apply':
            // Set the record data in the session.
            $recordId = $model->getState($this->context . '.id');
            $this->holdEditId($context, $recordId);
            $app->setUserState($context . '.data', null);
            $model->checkout($recordId);

            // Redirect back to the edit screen.
            $this->setRedirect(
                JRoute::_(
                    'index.php?option=' . $this->option . '&view=' . $this->view_item
                    . $this->getRedirectToItemAppend($recordId, $urlVar), false
                )
            );
            break;

        case 'save2new':
            // Clear the record id and data from the session.
            $this->releaseEditId($context, $recordId);
            $app->setUserState($context . '.data', null);

            // Redirect back to the edit screen.
            $this->setRedirect(
                JRoute::_(
                    'index.php?option=' . $this->option . '&view=' . $this->view_item
                    . $this->getRedirectToItemAppend(null, $urlVar), false
                )
            );
            break;

        default:
            // Clear the record id and data from the session.
            $this->releaseEditId($context, $recordId);
            $app->setUserState($context . '.data', null);

            // Redirect to the list screen.
            $this->setRedirect(
                JRoute::_(
                    'index.php?option=' . $this->option . '&view=' . $this->view_list
                    . $this->getRedirectToListAppend(), false
                )
            );
            break;
    }

    // Invoke the postSave method to allow for the child class to access the model.
    $this->postSaveHook($model, $validData);

    return true;
}
 类似资料:
  • 这是我的服务 这是我的主要组件,我订阅了服务并将其传递给另一个服务,以将其传递到其他组件 这是我的路线组件 这是共享服务 这是我的item.template 我可以成功地将数据从 appcomponent 传递到 'ItemComponent'。因此,每当我加载我的应用程序时,它都会订阅http调用并将数据传递给SharedService。当我单击 Item 时,它会路由到 ItemCompone

  • 我有一个巨大的字符串,我想保存为Django模型中的文件。为了做到这一点,我编写了以下代码: 这产生了一个错误, ’_ io。TextIOWrapper对象没有属性“_committed” 但是在网上搜索解决方案后,我陷入了死胡同。任何建议将不胜感激! 环境: 请求方法:获取请求 URL:http://127.0.0.1:8000/app/dbkarga/6/ Django版本:1.11.1 Py

  • 问题内容: 我正在尝试创建文件并将其保存到站点的根目录,但是我不知道它在哪里创建文件,因为看不到任何文件。而且,如果可能的话,我需要每次都覆盖该文件。 这是我的代码: 如何设置保存在根目录下? 问题答案: 它在与脚本相同的目录中创建文件。试试这个吧。

  • 我有问题保存我的数组列表。当应用程序销毁或更改意图或更改方向时,我想保存我的数组列表: 首先,我尝试保存在文件中,但Paint类不是可序列化类。第二,我尝试使用onSaveInstanceState(Bundle outState)/onRestoreInstanceState(Bundle savedInstanceState),但我无法保存Arraylist;第三,我尝试使用数据库,但没有任何

  • 我需要一些帮助:我正在做一个在Java的飞行花名册模拟。名册将容纳25名乘客,其中22名来自文本文件(passengerlist.txt)。对于每个乘客,有3个必需的数据点;姓名、座位等级和座位号和2个可选数据点数常旅客号码和常旅客点数。每个乘客都在自己的线路上,每个数据点都用逗号隔开。例如: 我有这个类,到目前为止还有构造函数: 我需要做的是从文本文件中读取每一行并创建数组,即使第一个look行

  • 我有一个映射,它的文件名是< code>String格式的< code>key,内容是< code>bytearray (byte[])格式的< code>value。 我想将map中的所有条目压缩到一个tar文件中,并将tar文件转换成< code>bytearray,而不将任何内容保存到磁盘上。 到目前为止,我正在temp目录中创建tar文件,并再次将tar文件读取为byteArray。 但是