”;
File uploading is one of the main concept in form programming. Zend framework provides all the necessary items to upload files through the zend-form and the zend-inputfilter component.
FileInput Class
The zend-inputfilter component provides ZendInputFilterFileInput class to handle the html file input element – <input type = ”file” />. The FileInput is like the other input filters with a few exceptions. They are as follows −
-
Since PHP saves the uploaded file details in $_FILES global array, the FileInput gathers the uploaded file information through $_FILES only.
-
Validation needs to be done before the FileInput class processes the data. It is the opposite behavior of the other input filters.
-
The ZendValidatorFileUploadFile is the default validator to be used. The UploadFile validates the file input details.
To add a file upload type in a form, we need to use input type File. The partial code is as follows −
$form->add(array( ''name'' => ''imagepath'', ''type'' => ''File'', ''options'' => array(''label'' => ''Picture'',), ));
Another class used in file uploading is ZendFilterFileRenameUpload. The RenameUpload is used to move the uploaded file to our desired location. The partial class to use file filter is as follows −
$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);
Here, the options of RenameUpload are as follows −
-
target − The destination path of the uploaded file.
-
randomize − Add a random string to prevent duplication of the uploaded file.
-
use_upload_extension − Append the file extension to the uploaded file to the target.
File Upload – Working Example
Let us modify the tutorial module and include a picture upload feature.
Modify the database table
Let us add the imagepath column to the book table by executing the following SQL command −
ALTER TABLE `book` ADD `imagepath` VARCHAR(255) NOT NULL AFTER ''imagepath'';
Update BookForm.php
Add the file input element to upload a picture in the book form – myapp/module/Tutorial/src/Model/BookForm.php.
Include the following code in the __constructmethod of the BookForm class.
$this->add(array( ''name'' => ''imagepath'', ''type'' => ''File'', ''options'' => array (''label'' => ''Picture'',), ));
Update Book.php
Do the following changes in the Book class – myapp/module/Tutorial/src/Model/Book.php.
-
Add a new property imagepath for the picture.
public $imagepath;
-
Update the getInputFilter method as shown below −
-
Add the FileInput filter for file input element.
-
Set the UploadFile validation to validate the file input element.
-
Configure the RenameUpload to move the uploaded file to the proper destination.
-
The partial code listing is as follows −
$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);
-
Update the exchangeArray method to include the imagepath property. The imagepath may come from a form or a database. If the imagepath comes from a form, the format will be an array with the following specification −
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> } }
-
If the imagepath comes from a database, it will be a simple string. The partial code listing to parse an imagepath is as follows −
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; }
The complete listing of the Book model is as follows −
<?php namespace TutorialModel; use ZendInputFilterInputFilterInterface; use ZendInputFilterInputFilterAwareInterface; use ZendFilterFileRenameUpload; use ZendValidatorFileUploadFile; use ZendInputFilterFileInput; use ZendInputFilterInputFilter; 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; } } }
Update BookTable.php
We have updated BookForm and the Book model. Now, we update the BookTable and modify the saveBook method. This is enough to include the imagepath entry in the data array, $data.
The partial code listing is as follows −
$data = array(''author'' => $book->author, ''title'' => $book->title, ''imagepath'' => $book->imagepath );
The complete code listing of the BookTable class is as follows −
<?php namespace TutorialModel; use ZendDbTableGatewayTableGatewayInterface; 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: File upload information will be available in the $_FILES global array and it can be accessed using the Request”s getFiles() method. So, merge both posted data and file upload information as shown below.
$post = array_merge_recursive( $request->getPost()->toArray(), $request->getFiles()->toArray() );
The complete listing of the addAction() method is as follows −
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); }
Update View of the add.phtml
Finally, change the “add.phtml” and include the imagepath file input element as shown below −
echo $this->formRow($form->get(''imagepath''))."<br>";
The complete listing is as follows −
<?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(); }
Run the application
Finally, run the application at http://localhost:8080/tutorial/add and add the new records.
The result will be as shown in the following screenshots −
Form Page
Index Page
”;