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

ファイルのアップロードは、フォームプログラミングの主要な概念の1つです。Zend Frameworkは、ファイルをアップロードするために必要なすべてのアイテムを提供します。zend-form そしてその zend-inputfilter 成分。

FileInputクラス

zend-inputfilterコンポーネントは、htmlファイル入力要素を処理するためのZend \ InputFilter \ FileInputクラスを提供します– <input type = 'file' />。ザ・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 −アップロードしたファイルの拡張子をターゲットに追加します。

ファイルのアップロード–実例

チュートリアルモジュールを変更して、画像のアップロード機能を含めましょう。

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

追加しましょう imagepath 次のSQLコマンドを実行してbookテーブルに列を追加します-

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 写真のために。

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プロパティ。イメージパスは、フォームまたはデータベースから取得できます。イメージパスがフォームからのものである場合、フォーマットは次の仕様の配列になります-

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(!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 model。今、私たちは更新します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'); 
         } 
      } 
   } 
}

Update addAction in the TutorialController.php:ファイルのアップロード情報は、 $_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(); 
}

アプリケーションを実行する

最後に、でアプリケーションを実行します http://localhost:8080/tutorial/add 新しいレコードを追加します。

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

Form Page

Index Page