it-swarm.com.de

Benutzerdefinierte Komponente - Verknüpfen des Dateiuploads vom Controller zur Ansicht

Ich habe eine benutzerdefinierte Komponente, die Eingaben vom Administrator entgegennimmt und diese als benutzerdefinierte Ansicht im Front-End der Site anzeigt. Eines der Felder ist ein Datei-Upload für ein Bild, und ich kann nicht online herausfinden, wie der Controller-Upload-Code mit der Ansicht verknüpft werden kann. Alles, was ich online gelesen habe, besagt im Grunde: "Bestehenden Kernkomponentencode studieren", und das habe ich ohne Erfolg getan.

Mein Admin-Controller:

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;
    }

}

Ich habe den Upload-Code vom "Datei" -Controller der com_media-Kernkomponente genommen.

Meine Sicht:

   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>

Ich habe keinen Code für das Modell angegeben, weil ich davon ausgehe, dass dies das Teil ist, das mir fehlt? Ich bin mir nicht sicher, wie ich es programmieren soll. Ich habe einige "get" -Methoden in meinem Modell, aber wäre dies eine "set" -Methode? Oder wie rufe ich eine Funktion vom Controller auf und übergebe sie der Eingabe aus der HTML/Ansicht?

4
Eric

Zu Beginn ist es wahrscheinlich am besten, all dies durchzugehen: http://docs.joomla.org/J2.5:Developing_a_MVC_Component/Developing_a_Basic_Component . Es ist eine Menge Information, aber es wird definitiv helfen, viele Ihrer Fragen zu beantworten.


Beginnen wir mit dem Formular. Es gibt ein paar Dinge, die Sie tun können, um auf die Controller-Funktion hinzuweisen:

<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>

Ich habe dem Formular zwei versteckte Eingaben hinzugefügt. Diese beiden Felder leiten die gebuchten Daten weiter. Der erste sollte zu Ihrer Komponente passen. Der zweite kann entweder nur ein Methodenname sein (wenn Sie an die Basis weiterleiten controller.php-Datei im Stammverzeichnis Ihrer Komponente) oder verwenden Sie diese "Punktsyntax", um den Controller und die Methode anzugeben. (Ihr Fall wäre wahrscheinlich nur upload, da das für mich wie der Basis-Controller aussieht.)

Das zusätzliche PHP-Bit am Ende fügt einen CSRF-Token hinzu, um CSRF-Angriffe zu verhindern. Sie können hier mehr darüber lesen: http://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms . Der Teil, der auf dieses Token geprüft werden soll, befindet sich bereits oben in der Upload-Funktion.


Nachdem Sie Ihre Upload-Funktion tatsächlich für die Formularübermittlung aktiviert haben, müssen wir die Datei verarbeiten.

Kümmere dich nicht darum, die Klasse JRequest für die Eingabe zu verwenden. Es ist veraltet und wird bald verschwinden. Verwenden Sie JInput wie hier beschrieben: http://docs.joomla.org/Retrieving_request_data_using_JInput .

Ziemlich alles, was vor der folgenden Zeile steht, ist für die anstehende Aufgabe wahrscheinlich nicht erforderlich. Es ermöglicht Anpassungen, die Sie momentan nicht wirklich benötigen:

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

Da wir jetzt JInput verwenden, können wir dies stattdessen folgendermaßen tun:

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

Ich glaube, der ganze Rest der Interaktion auf dem $ files-Array sollte funktionieren. Sie möchten prüfen, ob $ files ein Array von Dateien oder nur ein Array einer Datei auf einer Ebene ist. Im letzteren Fall brauchen Sie das foreach nicht.


Das sollte für diese Frage reichen. Ich kann fast garantieren, dass Sie weitere Fragen haben. Diese Frage ist bereits ziemlich weit gefasst, fragen Sie also nicht weiter nach. Sie können stattdessen gerne neue Fragen zu den spezifischen Problemen, die Sie haben, stellen (und auch gezielt nach diesen Problemen suchen, da hierfür bereits viele Ressourcen zur Verfügung stehen).

4
David Fritsch