Zend Framework - Carga de archivos

La carga de archivos es uno de los conceptos principales en la programación de formularios. Zend framework proporciona todos los elementos necesarios para cargar archivos a través delzend-form y el zend-inputfilter componente.

Clase FileInput

El componente zend-inputfilter proporciona la clase Zend \ InputFilter \ FileInput para manejar el elemento de entrada del archivo html - <input type = 'file' />. losFileInputes como los otros filtros de entrada con algunas excepciones. Son los siguientes:

  • Dado que PHP guarda los detalles del archivo cargado en $_FILES matriz global, FileInput recopila la información del archivo cargado solo a través de $ _FILES.

  • La validación debe realizarse antes de que la clase FileInput procese los datos. Es el comportamiento opuesto de los otros filtros de entrada.

  • Zend \ Validator \ File \ UploadFile es el validador predeterminado que se utilizará. losUploadFile valida los detalles de entrada del archivo.

Para agregar un tipo de carga de archivo en un formulario, necesitamos usar el tipo de entrada File. El código parcial es el siguiente:

$form->add(array( 
   'name' => 'imagepath', 
   'type' => 'File', 
   'options' => array('label' => 'Picture',), 
));

Otra clase utilizada en la carga de archivos es Zend \ Filter \ File \ RenameUpload. losRenameUploadse utiliza para mover el archivo cargado a la ubicación deseada. La clase parcial para usar el filtro de archivos es la siguiente:

$file = new FileInput('imagepath'); 
$file->getValidatorChain()->attach(new UploadFile());
$file->getFilterChain()->attach( 
   new RenameUpload([ 
      'target'    => './public/tmpuploads/file', 
      'randomize' => true, 
      'use_upload_extension' => true 
   ]));
$inputFilter->add($file);

Aquí, las opciones de RenameUpload son los siguientes:

  • target - La ruta de destino del archivo cargado.

  • randomize - Agregue una cadena aleatoria para evitar la duplicación del archivo cargado.

  • use_upload_extension - Agregue la extensión del archivo al archivo cargado al destino.

Carga de archivos: ejemplo de trabajo

Modifiquemos el módulo tutorial e incluyamos una función de carga de imágenes.

Modificar la tabla de la base de datos

Agreguemos el imagepath columna a la tabla del libro ejecutando el siguiente comando SQL:

ALTER TABLE `book` ADD `imagepath` VARCHAR(255) NOT NULL AFTER 'imagepath';

Actualizar BookForm.php

Agregue el elemento de entrada de archivo para cargar una imagen en el formulario de libro: myapp / module / Tutorial / src / Model / BookForm.php.

Incluya el siguiente código en el __constructmethod de la clase BookForm.

$this->add(array( 
   'name' => 'imagepath', 
   'type' => 'File', 
   'options' => array ('label' => 'Picture',), 
));

Actualizar Book.php

Realice los siguientes cambios en la clase Libro: myapp / module / Tutorial / src / Model / Book.php.

  • Agregar una nueva propiedad imagepath para la foto.

public $imagepath;
  • Actualizar el getInputFilter método como se muestra a continuación -

    • Añade el FileInput filtro para elemento de entrada de archivo.

    • Selecciona el UploadFile validación para validar el elemento de entrada del archivo.

    • Configurar el RenameUpload para mover el archivo cargado al destino adecuado.

La lista de códigos parcial es la siguiente:

$file = new FileInput('imagepath'); 
$file->getValidatorChain()->attach(new UploadFile()); 
$file->getFilterChain()->attach( 
   new RenameUpload([ 
      'target'    => './public/tmpuploads/file', 
      'randomize' => true, 'use_upload_extension' => true 
   ])); 
$inputFilter->add($file);
  • Actualizar el exchangeArray método para incluir el imagepathpropiedad. La ruta de la imagen puede provenir de un formulario o una base de datos. Si la ruta de la imagen proviene de un formulario, el formato será una matriz con la siguiente especificación:

array(1) { 
   ["imagepath"] => array(5) { 
      ["name"]     => string "myimage.png" 
      ["type"]     => string "image/png"           
      ["tmp_name"] => string 
         "public/tmpuploads/file_<random_string>.<image_ext>" 
      ["error"]    => int <error_number> 
      ["size"]     => int <size> 
   } 
}
  • Si la ruta de la imagen proviene de una base de datos, será una cadena simple. La lista de código parcial para analizar una ruta de imagen es la siguiente:

if(!empty($data['imagepath'])) { 
   if(is_array($data['imagepath'])) { 
      $this->imagepath = str_replace("./public", "", $data['imagepath']['tmp_name']); 
   } else { 
      $this->imagepath = $data['imagepath']; 
   } 
} else { 
   $data['imagepath'] = null; 
}

La lista completa de Book El modelo es el siguiente:

<?php  
namespace Tutorial\Model;  
use Zend\InputFilter\InputFilterInterface; 
use Zend\InputFilter\InputFilterAwareInterface;  
use Zend\Filter\File\RenameUpload; 
use Zend\Validator\File\UploadFile; 
use Zend\InputFilter\FileInput; 
use Zend\InputFilter\InputFilter;  

class Book implements InputFilterAwareInterface { 
   public $id; 
   public $author; 
   public $title; 
   public $imagepath;  
   protected $inputFilter;  
   public function setInputFilter(InputFilterInterface $inputFilter) { 
      throw new \Exception("Not used");
   }  
   public function getInputFilter() { 
      if (!$this->inputFilter) { 
         $inputFilter = new InputFilter(); 
         $inputFilter->add(array( 
            'name' => 'id', 
            'required' => true, 
            'filters' => array( 
               array('name' => 'Int'), 
            ), 
         )); 
         $inputFilter->add(array( 
            'name' => 'author', 
            'required' => true, 
            'filters' => array( 
               array('name' => 'StripTags'), 
               array('name' => 'StringTrim'), 
            ), 
            'validators' => array( 
               array( 
                  'name' => 'StringLength', 
                  'options' => array( 
                     'encoding' => 'UTF-8', 
                     'min' => 1, 
                     'max' => 100, 
                  ), 
               ), 
            ), 
         )); 
         $inputFilter->add(array( 
            'name' => 'title', 
            'required' => true, 
            'filters' => array( 
               array('name' => 'StripTags'), 
               array('name' => 'StringTrim'), 
            ),  
            'validators' => array( 
               array( 
                  'name' => 'StringLength', 
                  'options' => array( 
                     'encoding' => 'UTF-8', 
                     'min' => 1, 
                     'max' => 100, 
                  ), 
               ), 
            ), 
         ));  
         $file = new FileInput('imagepath'); 
         $file->getValidatorChain()->attach(new UploadFile()); 
         $file->getFilterChain()->attach( 
            new RenameUpload([ 
               'target'    => './public/tmpuploads/file', 
               'randomize' => true, 
               'use_upload_extension' => true 
            ])); 
            $inputFilter->add($file);  
            $this->inputFilter = $inputFilter; 
      } 
      return $this->inputFilter; 
   }  
   public function exchangeArray($data) { 
      $this->id = (!empty($data['id'])) ? $data['id'] : null; 
      $this->author = (!empty($data['author'])) ? $data['author'] : null; 
      $this->title = (!empty($data['title'])) ? $data['title'] : null; 
      
      if(!empty($data['imagepath'])) { 
         if(is_array($data['imagepath'])) { 
            $this->imagepath = str_replace("./public", "", 
               $data['imagepath']['tmp_name']); 
         } else { 
            $this->imagepath = $data['imagepath']; 
         } 
      } else { 
         $data['imagepath'] = null; 
      } 
   } 
}

Actualizar BookTable.php

Hemos actualizado BookForm y el Book model. Ahora, actualizamos elBookTable y modificar el saveBookmétodo. Esto es suficiente para incluir la entrada imagepath en la matriz de datos,$data.

La lista de códigos parcial es la siguiente:

$data = array('author' => $book->author, 'title'  => $book->title, 
   'imagepath' => $book->imagepath 
);

La lista de códigos completa del BookTable la clase es la siguiente:

<?php  
namespace Tutorial\Model;  
use Zend\Db\TableGateway\TableGatewayInterface;  

class BookTable {  
   protected $tableGateway; 
   public function __construct(TableGatewayInterface $tableGateway) { 
      $this->tableGateway = $tableGateway; 
   }  
   public function fetchAll() { 
      $resultSet = $this->tableGateway->select(); 
      return $resultSet; 
   }  
   public function getBook($id) { 
      $id  = (int) $id; 
      $rowset = $this->tableGateway->select(array('id' => $id)); 
      $row = $rowset->current(); 
      if (!$row) { 
         throw new \Exception("Could not find row $id"); 
      } 
      return $row; 
   }  
   public function saveBook(Book $book) { 
      $data = array ( 
         'author' => $book->author,
         'title'  => $book->title, 
         'imagepath' => $book->imagepath 
      );  
      $id = (int) $book->id; 
      if ($id == 0) { 
         $this->tableGateway->insert($data); 
      } else { 
         if ($this->getBook($id)) {  
            $this->tableGateway->update($data, array('id' => $id)); 
         } else { 
            throw new \Exception('Book id does not exist'); 
         } 
      } 
   } 
}

Update addAction in the TutorialController.php: La información de carga de archivos estará disponible en el $_FILES matriz global y se puede acceder mediante el Request's getFiles()método. Por lo tanto, combine los datos publicados y la información de carga de archivos como se muestra a continuación.

$post = array_merge_recursive( 
   $request->getPost()->toArray(), 
   $request->getFiles()->toArray() 
);

La lista completa de addAction() El método es el siguiente:

public function addAction() { 
   $form = new BookForm(); 
   $form->get('submit')->setValue('Add');  
   $request = $this->getRequest(); 
   if ($request->isPost()) { 
      $book = new Book(); 
      $form->setInputFilter($book->getInputFilter()); 
      $post = array_merge_recursive( 
         $request->getPost()->toArray(), 
         $request->getFiles()->toArray() 
      );  
      $form->setData($post);   
      if ($form->isValid()) { 
         $book->exchangeArray($form->getData());  
         $this->bookTable->saveBook($book);  
         
         // Redirect to list of Tutorial 
         return $this->redirect()->toRoute('tutorial'); 
      } 
   }  
   return array('form' => $form); 
}

Actualizar vista de add.phtml

Por último, cambie "add.phtml" e incluya el elemento de entrada del archivo imagepath como se muestra a continuación:

echo $this->formRow($form->get('imagepath'))."<br>";

La lista completa es la siguiente:

<?php 
$title = 'Add new Book'; 
$this->headTitle($title); 
?> 
<h1><?php echo $this->escapeHtml($title); ?></h1> 
<?php  
if(!empty($form)) {  
   $form->setAttribute('action', $this->url('tutorial', array('action' => 'add'))); 
   $form->prepare();  
   echo $this->form()->openTag($form); 
   echo $this->formHidden($form->get('id')); 
   echo $this->formRow($form->get('author'))."<br>"; 
   echo $this->formRow($form->get('title'))."<br>"; 
   echo $this->formRow($form->get('imagepath'))."<br>"; 
   echo $this->formSubmit($form->get('submit')); 
   echo $this->form()->closeTag(); 
}

Ejecutar la aplicación

Finalmente, ejecute la aplicación en http://localhost:8080/tutorial/add y agregue los nuevos registros.

El resultado será el que se muestra en las siguientes capturas de pantalla:

Form Page

Index Page