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.




2016年10月27日木曜日

cakephp3 phpunit 利用時に使える便利なmethodなどについて

PHP Ver 5.6.27
CakePHP Ver 3.1.9


公式ページを見れば記載があるが、少しわかりにくいのでPHPUnitで利用されるファイルやメソッドについて書いておく。


Fixtures:
実際のアプリケーションに使われているデータを破壊することなく テストができる
 ・各フィクスチャで必要なテーブルを作成します
 ・フィクスチャにデータが存在すれば、それをテーブルに投入します
 ・テストメソッドを実行します
 ・フィクスチャのテーブルを空にします
 ・データベースからフィクスチャのテーブルを削除します

記述例(xxxControllerTest.php)
---------------------------------------------------
public $fixtures = [ 'app.user', 'app.article' ];
---------------------------------------------------


setUp method:
テストメソッドの前に毎回呼び出されます
テストされるオブジェクトの生成や、テストのためのデータの初期化に使われます
メールなどの設定はここに記述すると便利
※parent::setUp() を呼び出すことを忘れないでください

記述例(xxxControllerTest.php)
---------------------------------------------------
public function setUp() {
  parent::setUp();

  Email::dropTransport('default');
  Email::configTransport('default', [ 'className' => 'Debug', ]);
}
---------------------------------------------------


tearDown method:
テストメソッドの後に毎回呼び出されます
テストが完了した後のクリーンアップに使われます
※parent::tearDown() を呼び出すことを忘れないでください

記述例 (xxxControllerTest.php)
---------------------------------------------------
public function tearDown() {
  parent::tearDown();
}
---------------------------------------------------


setupBeforeClass method:
クラスのテストメソッドを実行する前に一度だけ呼ばれます
※このメソッドは static でなければなりません

記述例 (xxxControllerTest.php)
---------------------------------------------------
public static function setupBeforeClass() {
  parent::setupBeforeClass();
}
---------------------------------------------------


tearDownAfterClass method: 
クラスのテストメソッドをすべて実行した後に一度だけ呼ばれます
※このメソッドは static でなければなりません

記述例 (xxxControllerTest.php)
---------------------------------------------------
public static function tearDownAfterClass() {
  parent::tearDownAfterClass();
}
---------------------------------------------------

2016年10月13日木曜日

cakephp3 pagenation & meta tag

PHP Ver 5.6.27
CakePHP Ver 3.1.9


ページネーション処理は、Cakephpのデフォルトで準備がされている

まずは、ページネーション使いますよとAppViewのinitializeメソッドで設定

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

$this->loadHelper('Paginator');

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


Controllerのinitializeメソッド内などで、ページネーションの詳細設定を行う

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

$this->loadComponent('Paginator');
$this->paginate = [
                'limit' => 10
        ];

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


limitなどはロードした後に設定

では実際に使ってみる
DBから取得してきたqueryをページネーションを使って表示

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

$this->set('articles', $this->Paginator->paginate($article->getArticlesQuery(), $this->paginate));

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


その後Viewでは気にせず普通にイテレーションしてあげればよい
但し、以下の表示は入れてあげないとページ番号が出てこないので注意

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

<?= $this->Paginator->numbers() ?>

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

ここで記述した内容はあくまで一例で、参考程度に。

詳しくは、以下参照

http://book.cakephp.org/3.0/ja/controllers/components/pagination.html


備考
rel=prevやrel=nextも自動でやってくれる
Viewファイル内で以下のようにheadタグの中に記述

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

<?= $this->Paginator->meta() ?>

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

これだけ。便利ですね~

2016年9月30日金曜日

cakephp3 Trimについて

PHP Ver 5.6.27
CakePHP Ver 3.1.9


入力値の前後にある全角/半角スペースを取り除きたい

cakephp3 の Validation では全角スペースだけが入力された場合などは、notEmpty を指定していても、
普通に通ってしまう。

ということで Trim しなければならないのですが、どこのタイミングで行うか。

調べた結果、公式に載っていました。
http://book.cakephp.org/3.0/ja/orm/saving-data.html#before-marshal

テーブルまたはビヘイビアクラスの beforeMarshal メソッドで行いなさいと。
 
タイミングはこれでOK。
しかし、ここに記載されている通り デフォルトのメソッド Trim だけを行ってしまうと
全角スペースは対応できない。

ってことで、全角スペースにも対応した Trim メソッドを作成することに。

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

    public static function mb_trim($str) {
        return trim(preg_replace('/[  ]+$/u', '', preg_replace('/^[  ]+/u', '', $str)));
    }
----------------------------------
 
これで良いかと思いきや、半角スペース - 垂直タブ - 全角スペースみたいな入力を
されてしまうと対応できないんですね・・・
対応が難しそうなので、このメソッドは暫定でこのままにしておいて、後々考えようと
思います。 

2016年9月23日金曜日

cakephp3 開発機と本番機でDBの向き先を変える -- custom db connection --

PHP Ver 5.6.27
CakePHP Ver 3.1.9


cakePHPでは、Unit用と通常利用するDBの設定が別々に設定されている。

しかし、一般的には開発機と本番機は別なので、本番機にアップする際に、いちいち設定を変更しないといけない。
そいつはミスする元凶になりそうだし、面倒だなぁ

ってことで、Unit用、開発機用、本番機用の3種類設定を行い、自動的に切り替えるようにしようと思い立つ。

既存のdefault・test以外にDBの向き先を変える方法

まずは、app.phpに設定を加える(ここでは開発機用の設定をdivとして追加)

通常はこんな感じ 
----------------------------------------------
'Datasources' => [

    'default' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Mysql',
        'persistent' => false,
        'host' => '本番機',
        'log' => false, 'quoteIdentifiers' => false,
    ],
    'test' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Mysql',
        'persistent' => false,
        'host' => 'localhost',
        'log' => false,
    ],
],
----------------------------------------------

これに以下の内容を追加する

----------------------------------------------
     'div' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Mysql',
        'persistent' => false,
        'host' => '開発機',
        'log' => false,
    ],
----------------------------------------------

で、切り替える様にコードを改修
 通常Modelの各Tableクラスは

Cake\ORM\Table

を継承しているけど、CustomTableみたいなクラスを作成してModelの各Tableクラスはこの新しく作成したクラスを継承して、CustomTableクラスで既存のTableクラスを継承する。
(要は、間に一枚かますってこと)

で、切り替えを行うために、既に準備されている”defaultConnectionName”というメソッドで向き先を設定してあげる。

と、新しく作成するファイルはこんな感じになる 
----------------------------------------------
class CustomTable extends Table  {

    public static function defaultConnectionName() {
        if (Configure::read('debug')) {
            if (Unitだったら) {
                return 'test';
            } else {
                return 'div';
            }
        } else {
            return 'default';
        }
    }
}
----------------------------------------------

これで、設定ファイルをいちいち設定しなくても良くなる

しかし、const.phpのdebug設定は都度変えないといけない。
その対応は後々考えることに・・・

2016年9月15日木曜日

Google Translateを使用してサイトを多言語化 -- use Google Translate For Localization --

  • Google Translate 登録画面へアクセス(事前にGoogleアカウント取得)
    • https://translate.google.com/manager/website/
    1. 「今すぐウェブサイトに追加」 ボタン押下
    2. ウェブサイトの URLを入力
    3. ウェブサイトの言語を選択
    4. 「次へ」 押下
    5. 翻訳する言語を選択
      1. すべての言語を選択すると一般的に使われない言語が多いので、言語を指定を選ぶことをおすすめ
    6. 表示モード選択
    7. 詳細設定選択
    8. 「コードを取得」 ボタンを押下 
    9. 表示されたHTMLをWebサイトに貼り付け

2016年8月30日火曜日

cakephp3 Cache

PHP Ver 5.6.27
CakePHP Ver 3.1.9


画像やJavascript、CSSをキャッシュしたい場合は、以下のように設定

app.php
-------------------------------------------
    'Asset' => [
        'timestamp' => true, // 画像,JS,CSSのキャッシュを無効にする(デバッグモードのときのみ)
    ],

-------------------------------------------
デバッグモード時に限らず、常にクエリストリングを付けたい場合 : 'force'