4

コンポーネントを構築するために、このドキュメント (Web で見つけられる唯一のもの) を使用しています: http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Introduction

ある程度は理解できますが、実際には定義がありません。私が作成したコンポーネントはある程度機能しますが、いくつかの問題があります。

基本的に、コンポーネントに必要なのは、いくつかの値を設定する設定領域をロードするだけで、それを通じてそれらの値を変更できるようになります。ここに私が持っているものの内訳があります:

データベースからフォーム データを読み込む、フォームのビュー。保存/適用およびキャンセル用のツールバーのセットアップ。

これはエラーなしでロードされ、私が見つけた joomla のすべてのドキュメントによると、モデルに接続された JTable で JControllerForm インスタンスを初期化することにより、フォームの単純な保存が自動的に機能するはずです。ただし、コードのどこにも最後に s があるビューへの参照がまったくないにもかかわらず (メイン ビューは Tireapi であり、フォームは常に Tireapis にリダイレクトされます)。

そのビューを持つプレース セットがないため、500 エラーが発生します。ドキュメントにはビューのリストが含まれていますが、編集する必要があるのは 1 行だけなので、リストは無意味です。データベース フィールドを作成するのではなく、コンポーネントにパラメータを設定できることは知っていますが、関連するドキュメントを見つけることができません。

私が探しているのは、コンポーネントが存在しないビューへのリダイレクトを停止し、データを適切に保存する方法に関する指示です。サンプルコードを示すだけでなく、関数とその動作方法を説明するドキュメントへのリンクが有益です。

ここにコードの一部を示します。完全に見落としている可能性があるものを自由に指摘してください (私はコンポーネントの作成に慣れていません)。

tireapi.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{}
?>

models/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/view.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ファイルを介してフォームを設定し、データベースから適切なデータを入力して、適切にロードします。ただし、「適用」をクリックすると、保存せずに上記のエラーが表示されたフォームに戻るだけです。

4

2 に答える 2

4

あなたが開いたままにした主な質問は、どこにリダイレクトしたいですか? デフォルトでは、Joomla はリスト ビューにリダイレクトします (リスト ビューを直接指定しない限り、ビュー名に「s」を追加します)。

これは、いくつかの方法でオーバーライドできます。

コントローラー (controllers/tireapi.php) で、独自のリスト ビューを設定します。これを同じビューにすることもできると思います:

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

保存関数をオーバーライドして、保存後に発生するリダイレクトを変更します (再びコントローラーで)。これは、自然に発生するリダイレクトを別のものに変更することで機能します。

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

それらの1つがあなたのためにトリックを行うはずです。

** アップデート

アイテムを最初にチェックアウトするには、設定されていないビューをコンポーネントが処理する方法を変更する必要があります。今はビューを設定するだけですが、代わりにリダイレクトしましょう! 更新された controller.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);
    }
}
?>

注: 複数の人がこれを編集する必要がある場合、これは非常にうまく機能しません。保存後にこのページにリダイレクトする場合、コンポーネントを開くときにシステムがチェックアウトするためです。それは常に最後に編集した人にチェックアウトされるため、次の人はそれを開くことができません。1人で編集すればOKです。

2 番目の注意: チェックアウト システムをハッキングしたくない場合は、保存プロセス中に無視することもできます。これは基本的にハッキングと同じレベルです。

以下は、controllerform.php の save 関数のコピーですlibraries/joomla/application/component/。これは、保存時に通常どおり実行されているものです (継承元のためです。アイテムがチェックアウトされているかどうかのチェックを削除しました。したがって、これをタイヤの tireapi.php コントローラーのparent::save...ビットがある場所に配置すると、代わりに実行され、わざわざアイテムをチェックアウトする必要はありません (つまり、すべてのコメントを無視してください...). (正直なところ、あなたの場合、おそらくもっと多くのアイテムを削除できますが、これが保存時に起こっていることです! )

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->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;
}
于 2013-04-19T20:32:26.133 に答える
0

これは本当の答えではありませんが、あなたの質問も本当の質問ではありません (私はそれを 3 回読まなければなりませんでした)。

複数の「s」が付いているもの (tireapis) は、なんと Joomla! 自動的に行います。それをオーバーライドできます。

コア コンポーネント (com_banners など) を確認することをお勧めします。

あなたがする必要があるのは、リダイレクトを避けることです。同じページにとどまるはずの「保存」ボタンだけが必要です。「保存して閉じる」は、複数のページにリダイレクトします。

于 2013-04-19T18:53:59.953 に答える