2016年12月22日木曜日

CakePHP3 ファイルアップロード -- file upload --

PHP Ver 5.6.27
CakePHP Ver 3.1.9


 ■ 前提
  自前でファイルアップロードを作りたい方向けに記述しています。
  CakePHP3 では、有名なファイルアップロード関連のプラグインがありますので、プラグインでもいいって方は、そちらの方が良いかもしれません。
一応、一つご紹介

cakephp-simple-upload

-----------------------------------------------

では、本題へ。
Controllerに実装することもできるのですが、それでは美しくないってことで、ModelクラスのbeforeSaveというメソッドに処理させます。
beforeSaveメソッドについては、こちらを 参照

 == Model ==
     public function beforeSave($event, $entity, $options)
    {
        // entityにファイルが指定されているかどうか
        if ($entity->has('upload_file')) {
            $upload_file = $entity->get('upload_file');
            // ファイルが正しくアップロードされているか
            if ($upload_file['error'] === UPLOAD_ERR_OK && $upload_file['size'] !== 0) {
              
                // ファイルを保存する
                $file = new File($upload_file['tmp_name']);
                $file->copy('/example/dest/upload_file');
            } else {
                // ファイルが指定されていなかった場合、上書きされてしまわないようにする
                $entity->unsetProperty('upload_file');
            }
        }
    }

今回はDB保存する直前に動作するbeforeSaveで処理しましたが、インクリメントされたIDをファイル名に入れたいなど思われる方は、afterSaveメソッドで処理させると良いかもしれません。

最後に問題が、この指定方法だとファイルアップロードに失敗した場合のエラーハンドリングがうまくできないんですよね。
どなたかご教授頂けると幸いです。


 ===================================================

 ■ Premise

  It is written for those who want to make file upload on their own.

  In CakePHP 3, there is a famous plugin related to file uploading, so if you can plugin it may be better there.

  Once, one introduction

cakephp-simple-upload

-----------------------------------------------

 Then, to the main subject.

 It can also be implemented in Controller, but let's say that it is not beautiful and that it is handled by the Model class beforeSave method.

 For the beforeSave method, see here

 == Model ==

     public function beforeSave($event, $entity, $options)
    {
        // Whether a file is specified for entity
        if ($entity->has('upload_file')) {
            $upload_file = $entity->get('upload_file');
            // Is the file uploaded correctly?
            if ($upload_file['error'] === UPLOAD_ERR_OK && $upload_file['size'] !== 0) {
               
                // Save the file
                $file = new File($upload_file['tmp_name']);
                $file->copy('/example/dest/upload_file');
            } else {
                // Do not overwrite if file is not specified
                $entity->unsetProperty('upload_file');
            }
        }
    }


 This time it processed with beforeSave which operates just before saving the DB, but if you think that you want to include the incremented ID in the file name, it may be better to process it with the afterSave method.

 Finally, if the problem is this specification method, error handling can not be done well if the file upload fails, right?

 I hope someone can take a professor.