Zend-framework-file-uploading

提供:Dev Guides
移動先:案内検索

Zend Framework-ファイルのアップロード

ファイルのアップロードは、フォームプログラミングの主要な概念の1つです。 Zendフレームワークは、 zend-form および zend-inputfilter コンポーネントを介してファイルをアップロードするために必要なすべてのアイテムを提供します。

FileInputクラス

zend-inputfilterコンポーネントは、htmlファイルの入力要素( <input type = 'file'/> )を処理するZend \ InputFilter \ FileInputクラスを提供します。 FileInput は、いくつかの例外を除いて、他の入力フィルターに似ています。 彼らは次のとおりです-

  • 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 -アップロードされたファイルにファイル拡張子をターゲットに追加します。

ファイルのアップロード-作業例

チュートリアルモジュールを変更して、写真のアップロード機能を追加しましょう。

データベーステーブルを変更する

私たちは、次のSQLコマンドを実行することにより、ブックテーブルに*画像パス*列を追加しましょう-

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

BookForm.phpを更新する

ファイル入力要素を追加して、本のフォームに画像をアップロードします– myapp/module/Tutorial/src/Model/BookForm.php。

BookFormクラスの __ constructmethod に次のコードを含めます。

$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がフォームから来ている場合、形式は次の仕様を持つ配列になります-
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を解析するための部分的なコードリストは次のとおりです-
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* メソッドを変更します。 これは、データ配列 *$ 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の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 でアプリケーションを実行し、新しいレコードを追加します。

結果は、次のスクリーンショットに示すようになります-

フォームページ

新しい本の例

インデックスページ

インデックスページ