it-swarm.dev

Componente personalizzato: collegamento del caricamento del file dal controller alla vista

Ho un componente personalizzato che prende input dall'amministratore e lo visualizza come una vista personalizzata sul front-end del sito. Uno dei campi è un caricamento di file per un'immagine e non riesco a capire/trovare online come collegare il codice di caricamento del controller alla vista. Tutto ciò che ho letto online dice sostanzialmente "Studia il codice componente esistente" e l'ho fatto senza risultati.

Il mio controller di amministrazione:

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

}

Ho preso il codice di caricamento dal controller "file" del componente core com_media.

La mia opinione:

   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>

Non ho incluso alcun codice per il modello perché presumo che sia il pezzo che mi manca? Non sono sicuro di come procedere per codificarlo però. Ho alcuni metodi "get" nel mio modello, ma sarebbe un metodo "set"? O come posso chiamare una funzione dal controller e passargli l'input dall'HTML/vista?

4
Eric

Per iniziare, probabilmente sarebbe meglio passare attraverso tutto questo: http://docs.joomla.org/J2.5:Developing_a_MVC_Component/Developing_a_Basic_Component . Sono molte informazioni, ma sicuramente aiuteranno a rispondere a molte delle tue domande.


Cominciamo con il modulo. Ci sono alcuni pezzi che puoi fare per fare in modo che puntino alla funzione del controller:

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

Ho aggiunto due input nascosti al modulo. Questi due campi instradano i dati inviati. Il primo dovrebbe corrispondere al tuo componente. Il secondo può essere solo un nome di metodo (se si sta instradando alla base controller.php nella directory principale del componente) oppure utilizzare questa "sintassi punto" per specificare il controller e il metodo. (Probabilmente il tuo caso sarebbe solo upload poiché mi sembra il controller di base.)

Il bit php aggiuntivo alla fine aggiunge un token CSRF per aiutare a prevenire gli attacchi CSRF. Puoi leggere di più qui: http://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms . La parte per verificare questo token è già nella parte superiore della funzione di caricamento.


Ora che stai effettivamente eseguendo la tua funzione di caricamento per l'invio del modulo, dobbiamo elaborare il file.

Non preoccuparti di usare la classe JRequest per l'input. È deprecato e andrà via presto. Utilizzare JInput come indicato qui: http://docs.joomla.org/Retrieving_request_data_using_JInput .

Praticamente tutto prima della riga seguente non è probabilmente necessario per l'attività in corso. Permette la personalizzazione che non ti serve davvero per ora:

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

Poiché ora stiamo usando JInput, possiamo invece farlo in questo modo:

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

Credo che tutto il resto dell'interazione sull'array $ files dovrebbe funzionare. Dovrai verificare se $ files è un array di file o solo un array a livello singolo di un file. In quest'ultimo caso, non è necessario il foreach.


Questo dovrebbe essere sufficiente per questa domanda. Posso quasi garantire che avrai altre domande. Questa domanda è già abbastanza ampia, quindi non continuare a fare domande su questo. Invece, sentiti libero di aprire nuove domande sui problemi specifici che stai riscontrando (oltre a cercare più specificamente su questi problemi, perché ci sono già molte risorse su questo.)

4
David Fritsch