web-dev-qa-db-ja.com

カスタムコンポーネント-コントローラからビューへのファイルアップロードのリンク

管理者から入力を受け取り、サイトのフロントエンドにカスタムスタイルビューとして表示するカスタムコンポーネントがあります。フィールドの1つは画像のファイルアップロードであり、コントローラーのアップロードコードをビューにリンクする方法をオンラインで見つけ出すことはできません。私がオンラインで読んだことはすべて、「既存のコアコンポーネントコードを研究する」と基本的に言っていますが、私はそれを無駄にしています。

私の管理コントローラー:

class NewsShowcaseController extends JController
{
    /**
     * display task
     *
     * @return void
     */
    function display($cachable = false, $urlparams = false) 
    {
            // set default view if not set
            $input = JFactory::getApplication()->input;
            $input->set('view', $input->getCmd('view', 'NewsShowcaseAdmin'));

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

    /*
     * The folder we are uploading into
     */
    protected $folder = '';

    /**
     * Upload one or more files
     *
     * @since 1.5
     */
    public function upload()
    {
            // Check for request forgeries
            JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));
            $params = JComponentHelper::getParams('com_media');
            // Get some data from the request
            $files                  = JRequest::getVar('Filedata', '', 'files', 'array');
            $return                 = JRequest::getVar('return-url', null, 'post', 'base64');
            $this->folder   = JRequest::getVar('folder', '', '', 'path');

            // Set the redirect
            if ($return)
            {
                    $this->setRedirect(base64_decode($return) . '&folder=' . $this->folder);
            }

            // Authorize the user
            if (!$this->authoriseUser('create'))
            {
                    return false;
            }
            if (
                    $_SERVER['CONTENT_LENGTH']>($params->get('upload_maxsize', 0) * 1024 * 1024) ||
                    $_SERVER['CONTENT_LENGTH']>(int)(ini_get('upload_max_filesize'))* 1024 * 1024 ||
                    $_SERVER['CONTENT_LENGTH']>(int)(ini_get('post_max_size'))* 1024 * 1024 ||
                    (($_SERVER['CONTENT_LENGTH'] > (int) (ini_get('memory_limit')) * 1024 * 1024) && ((int) (ini_get('memory_limit')) != -1))
            )
            {
                    JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));
                    return false;
            }
            // Input is in the form of an associative array containing numerically indexed arrays
            // We want a numerically indexed array containing associative arrays
            // Cast each item as array in case the Filedata parameter was not sent as such
            $files = array_map( array($this, 'reformatFilesArray'),
                    (array) $files['name'], (array) $files['type'], (array) $files['tmp_name'], (array) $files['error'], (array) $files['size']
            );

            // Perform basic checks on file info before attempting anything
            foreach ($files as &$file)
            {
                    if ($file['error']==1)
                    {
                            JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));
                            return false;
                    }
                    if ($file['size']>($params->get('upload_maxsize', 0) * 1024 * 1024))
                    {
                            JError::raiseNotice(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));
                            return false;
                    }

                    if (JFile::exists($file['filepath']))
                    {
                            // A file with this name already exists
                            JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_FILE_EXISTS'));
                            return false;
                    }

                    if (!isset($file['name']))
                    {
                            // No filename (after the name was cleaned by JFile::makeSafe)
                            $this->setRedirect('index.php', JText::_('COM_MEDIA_INVALID_REQUEST'), 'error');
                            return false;
                    }
            }

            // Set FTP credentials, if given
            JClientHelper::setCredentialsFromRequest('ftp');
            JPluginHelper::importPlugin('content');
            $dispatcher     = JDispatcher::getInstance();

            foreach ($files as &$file)
            {
                    // The request is valid
                    $err = null;
                    if (!MediaHelper::canUpload($file, $err))
                    {
                            // The file can't be upload
                            JError::raiseNotice(100, JText::_($err));
                            return false;
                    }

                    // Trigger the onContentBeforeSave event.
                    $object_file = new JObject($file);
                    $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true));
                    if (in_array(false, $result, true))
                    {
                            // There are some errors in the plugins
                            JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors)));
                            return false;
                    }

                    if (!JFile::upload($file['tmp_name'], $file['filepath']))
                    {
                            // Error in upload
                            JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'));
                            return false;
                    }
                    else
                    {
                            // Trigger the onContentAfterSave event.
                            $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));
                            $this->setMessage(JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($file['filepath'], strlen(COM_MEDIA_BASE))));
                    }
            }

            return true;
    }

}

コアcom_mediaコンポーネントの「ファイル」コントローラーからアップロードコードを取得しました。

私の見解:

   class NewsShowcaseViewNewsShowcaseAdmin extends JView
   {
/**
 * News Showcase Admin view display method
     * @return void
     */
    function display($tpl = null) 
    {
            // Get data from the model
            $items = $this->get('Items');
            $pagination = $this->get('Pagination');
            $this->image = $this->get('Image');
            $this->description = $this->get('Description');

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

            // Display the template
            parent::display($tpl);
    }

}

HTML:

            <form name="upload" method="post" enctype="multipart/form-data">
                <input type="file" name="file_upload" />
                <input type="submit" value="Upload Image" />
            </form>

それが私が欠けているものだと思うので、モデルのコードを含めませんでしたか?それをコーディングする方法についてはわかりません。モデルに "get"メソッドがいくつかありますが、これは "set"メソッドですか?または、コントローラーから関数を呼び出して、HTML /ビューからの入力を渡すにはどうすればよいですか?

4
Eric

開始するには、おそらくこれをすべて行うのが最善です: http://docs.joomla.org/J2.5:Developing_a_MVC_Component/Developing_a_Basic_Component 。それは多くの情報ですが、それは間違いなくあなたの多くの質問に答えるのに役立ちます。


フォームから始めましょう。これをコントローラー関数に向けさせるには、いくつかの方法があります。

<form name="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file_upload" />
    <input type="submit" value="Upload Image" />
    <input type="hidden" name="option" value="com_component_name" />
    <input type="hidden" name="task" value="controller.method" />
    <?php echo JHtml::_( 'form.token' ); ?>
</form>

2つの非表示の入力をフォームに追加しました。これら2つのフィールドは、ポストされたデータをルーティングします。最初のものはコンポーネントと一致する必要があります。 2番目は、メソッド名のみにすることもできます(ベースにルーティングする場合はcontroller.phpファイル(コンポーネントのルート)、またはこの「ドット構文」を使用して、コントローラーとメソッドを指定する必要があります。 (あなたにとっては、私にとってはベースコントローラーのように見えるので、おそらくuploadでしょう。)

最後に追加のphpビットを追加すると、CSRFトークンが追加され、CSRF攻撃の防止に役立ちます。詳しくはこちらをご覧ください http://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms 。このトークンを確認する部分は、すでにアップロード機能の上部にあります。


フォーム送信で実際にアップロード関数を実行するようになったので、ファイルを処理する必要があります。

入力にJRequestクラスを使用しないでください。これは非推奨であり、まもなく終了します。ここで概説されているようにJInputを使用します: http://docs.joomla.org/Retrieving_request_data_using_JInput

次の行の前のほとんどすべては、おそらく当面のタスクには必要ありません。それは今あなたが本当に必要としないカスタマイズを可能にします:

$files = array_map( array($this, 'reformatFilesArray'),
    (array) $files['name'], (array) $files['type'], (array) $files['tmp_name'], (array) $files['error'], (array) $files['size']
);

今はJInputを使用しているので、代わりに次のようにできます。

$app = JFactory::getApplication();
$files = $app->input->files->get('file_upload');

$ files配列の残りの部分はすべて機能するはずです。 $ filesがファイルの配列であるか、ファイルの単一レベルの配列であるかを確認する必要があります。後者の場合、foreachは必要ありません。


この質問にはこれで十分です。質問が増えることはほぼ保証できます。この質問はすでにかなり広いので、これについて少しずつ質問しないでください。代わりに、発生している特定の問題について新しい質問を自由に開いてください(すでに多くのリソースがあるため、これらの問題をより具体的に検索します)。

4
David Fritsch