Загрузка файлов является одной из основных концепций в программировании форм. 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 проверяет детали ввода файла.
Поскольку PHP сохраняет данные загруженного файла в глобальном массиве $ _FILES , FileInput собирает информацию о загруженном файле только через $ _FILES.
Проверка должна быть выполнена до того, как класс FileInput обработает данные. Это противоположное поведение других входных фильтров.
Zend \ Validator \ File \ UploadFile — это используемый по умолчанию валидатор. UploadFile проверяет детали ввода файла.
Чтобы добавить тип загрузки файла в форму, нам нужно использовать тип ввода 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 — добавьте расширение файла к загруженному файлу к цели.
target — целевой путь к загруженному файлу.
randomize — добавить случайную строку, чтобы предотвратить дублирование загруженного файла.
use_upload_extension — добавьте расширение файла к загруженному файлу к цели.
Загрузка файла — рабочий пример
Давайте изменим учебный модуль и добавим функцию загрузки изображений.
Изменить таблицу базы данных
Давайте добавим столбец imagepath в таблицу book, выполнив следующую команду SQL:
ALTER TABLE `book` ADD `imagepath` VARCHAR(255) NOT NULL AFTER 'imagepath';
Обновление BookForm.php
Добавьте элемент ввода файла для загрузки изображения в виде книги — myapp / module / Tutorial / src / Model / BookForm.php.
Включите следующий код в __constructmethod класса BookForm.
$this->add(array( 'name' => 'imagepath', 'type' => 'File', 'options' => array ('label' => 'Picture',), ));
Обновление Book.php
Сделайте следующие изменения в классе Book — myapp / module / Tutorial / src / Model / Book.php.
-
Добавьте новое свойство imagepath для картинки.
Добавьте новое свойство imagepath для картинки.
public $imagepath;
-
Обновите метод getInputFilter, как показано ниже —
-
Добавьте фильтр FileInput для элемента ввода файла.
-
Установите проверку UploadFile для проверки элемента ввода файла.
-
Сконфигурируйте RenameUpload для перемещения загруженного файла в нужное место назначения.
-
Обновите метод 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 . Путь к изображению может исходить из формы или базы данных. Если путь к изображению происходит из формы, форматом будет массив со следующей спецификацией:
Обновите метод exchangeArray, чтобы включить свойство 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 выглядит следующим образом:
Если 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; }
Полный список модели книги выглядит следующим образом:
<?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'); } } } }
Обновите addAction в TutorialController.php : Информация о загрузке файла будет доступна в глобальном массиве $ _FILES, и к ней можно получить доступ с помощью метода 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(); }
Запустите приложение
Наконец, запустите приложение по адресу http: // localhost: 8080 / tutorial / add и добавьте новые записи.
Результат будет таким, как показано на следующих скриншотах:
Форма страницы
Главная страница