- Zend Framework 教程
- Zend Framework - 首页
- Zend Framework - 简介
- Zend Framework - 安装
- 骨架应用
- Zend Framework - MVC 架构
- Zend Framework - 概念
- Zend Framework - 服务管理器
- Zend Framework - 事件管理器
- Zend Framework - 模块系统
- 应用结构
- Zend Framework - 创建模块
- Zend Framework - 控制器
- Zend Framework - 路由
- Zend Framework - 视图层
- Zend Framework - 布局
- 模型与数据库
- 不同的数据库
- 表单与验证
- Zend Framework - 文件上传
- Zend Framework - Ajax
- Cookie 管理
- Session 管理
- Zend Framework - 认证
- 邮件管理
- Zend Framework - 单元测试
- Zend Framework - 错误处理
- Zend Framework - 工作示例
- Zend Framework 有用资源
- Zend Framework - 快速指南
- Zend Framework - 有用资源
- Zend Framework - 讨论
Zend Framework - 文件上传
文件上传是表单编程中的一个主要概念。Zend Framework 提供了通过zend-form 和 zend-inputfilter 组件上传文件所需的所有必要项。
FileInput 类
zend-inputfilter 组件提供 Zend\InputFilter\FileInput 类来处理 html 文件输入元素 – <input type = 'file' />。FileInput 与其他输入过滤器类似,但有一些例外。它们如下所示:
由于 PHP 将上传的文件详细信息保存在$_FILES 全局数组中,因此 FileInput 仅通过 $_FILES 收集上传的文件信息。
FileInput 类处理数据之前需要进行验证。这与其他输入过滤器的行为相反。
Zend\Validator\File\UploadFile 是要使用的默认验证器。UploadFile 验证文件输入详细信息。
要在表单中添加文件上传类型,我们需要使用 input 类型File。部分代码如下所示:
$form->add(array( 'name' => 'imagepath', 'type' => 'File', 'options' => array('label' => 'Picture',), ));
另一个用于文件上传的类是 Zend\Filter\File\RenameUpload。RenameUpload 用于将上传的文件移动到我们想要的位置。使用文件过滤器的部分类如下所示:
$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);
这里,RenameUpload 的选项如下:
target - 上传文件的目标路径。
randomize - 添加随机字符串以防止上传文件重复。
use_upload_extension - 将文件的扩展名附加到上传文件的目标。
文件上传 - 工作示例
让我们修改 tutorial 模块并包含一个图片上传功能。
修改数据库表
让我们通过执行以下 SQL 命令向 book 表添加imagepath 列:
ALTER TABLE `book` ADD `imagepath` VARCHAR(255) NOT NULL AFTER 'imagepath';
更新 BookForm.php
在 book 表单中添加文件输入元素以上传图片 – myapp/module/Tutorial/src/Model/BookForm.php。
在 BookForm 类的__construct 方法中包含以下代码。
$this->add(array( 'name' => 'imagepath', 'type' => 'File', 'options' => array ('label' => 'Picture',), ));
更新 Book.php
对 Book 类进行以下更改 – myapp/module/Tutorial/src/Model/Book.php。
为图片添加一个新的属性imagepath。
public $imagepath;
更新getInputFilter 方法,如下所示:
为文件输入元素添加FileInput 过滤器。
设置UploadFile 验证以验证文件输入元素。
配置RenameUpload 将上传的文件移动到正确的目标位置。
部分代码清单如下:
$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);
更新exchangeArray 方法以包含imagepath 属性。imagepath 可能来自表单或数据库。如果 imagepath 来自表单,则格式将是一个具有以下规范的数组:
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> } }
如果 imagepath 来自数据库,它将是一个简单的字符串。解析 imagepath 的部分代码清单如下:
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; }
Book 模型的完整清单如下:
<?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; } } }
更新 BookTable.php
我们已经更新了BookForm 和Book 模型。现在,我们更新BookTable 并修改saveBook 方法。这足以将 imagepath 条目包含在数据数组$data 中。
部分代码清单如下:
$data = array('author' => $book->author, 'title' => $book->title, 'imagepath' => $book->imagepath );
BookTable 类的完整代码清单如下:
<?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'); } } } }
更新 TutorialController.php 中的 addAction:文件上传信息将在$_FILES 全局数组中可用,并且可以使用Request's getFiles() 方法访问它。因此,合并发布的数据和文件上传信息,如下所示。
$post = array_merge_recursive( $request->getPost()->toArray(), $request->getFiles()->toArray() );
addAction() 方法的完整列表如下:
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); }
更新 add.phtml 的视图
最后,更改“add.phtml”并包含如下所示的 imagepath 文件输入元素:
echo $this->formRow($form->get('imagepath'))."<br>";
完整列表如下:
<?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(); }
运行应用程序
最后,在https://127.0.0.1:8080/tutorial/add 运行应用程序并添加新记录。
结果将如以下屏幕截图所示:
表单页面
索引页面