LoginSignup
95
103

More than 5 years have passed since last update.

CakePHP3 で開発環境準備(実務編究極チュートリアル)

Last updated at Posted at 2015-02-22

インストール

まずはcomposerでプロジェクト作成。

sudo php composer.phar create-project --prefer-dist -s dev cakephp/app myApp

途中で以下のように質問されるようになった。

Set Folder Permissions ? (Default to Y) [Y,n]? Y

無事終了したら、パーミッションを変えておく(OSXのみ)

sudo chown -R mymac:staff myApp

ここで一旦 .gitignore を編集してコミットしておく。tmpとlogsをコメントアウトして、
自分の環境でよくあるやつを入れておく。

.gitignore
/vendor/*
/config/app.php
#/tmp/*
#/logs/*

.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
*.swp
*.un~
*~
*BAK

あとはいつものgit処理で。

git init
git add .
git commit -m "Initialize repository"
git remote add origin https://github.com/xxxxxxx/myApp.git
git push -u origin master

pushしたらtmpとlogsのコメントアウトを外しておく。

.gitignore
/tmp/*
/logs/*

一旦サーバー起動してみて動作確認。

cd myApp
bin/cake server

テスト

次に、test(phpunit)ができるようにしておく。
composer.jsonを編集する。
suggest に入っている phpunit と codesniffer を require-dev に移す。

myApp/composer.json
    "require-dev": {
        "d11wtq/boris": "1.0.*",
        "cakephp/debug_kit": "3.0.*-dev",
        "cakephp/bake": "dev-master",
        "phpunit/phpunit": "*",
        "cakephp/cakephp-codesniffer": "*"
    },

composerのアップデートをかける。

sudo php ../composer.phar update

無事入ったら、phpunitの動作確認。

vendor/bin/phpunit

この時点で(もっとそれより早くて構わないが)データベースを準備しておく。
開発用のDBにはテーブル(例:articles)も作っておく。
テスト用のDBは空っぽ(テーブル無し)でよい。

config/app.php を編集してDB接続情報を入れておく。

config/app.php
    'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => 'localhost',
            'username' => 'root',
            'password' => 'password',
            'database' => 'sample_db',
            'encoding' => 'utf8',
            //'timezone' => 'UTC',
            'cacheMetadata' => true,

        ],

        /**
         * The test connection is used during the test suite.
         */
        'test' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => 'localhost',
            'username' => 'root',
            'password' => 'password',
            'database' => 'test_sample_db',
            'encoding' => 'utf8',
            //'timezone' => 'UTC',
            'cacheMetadata' => true,
            'quoteIdentifiers' => false,
        ],
    ],

で、以下のコマンドで、テーブルのモデルをbakeコマンドで自動生成。
(するとtestsディレクトリ以下にテストケースとフィクスチャーも自動生成される)

bin/cake bake model Articles

再びテストしてみる。(以下でテスト結果が出るはず)

vendor/bin/phpunit

ついでにカバレッジも作ってみる。

vendor/bin/phpunit --coverage-html webroot/coverage

webroot/coverage 以下に index.html が生成されるのでブラウザで開いてみる。

コーディング規約

さらにコードスニッッファーの設定をする。
以下のコマンドを打つ。

sudo vendor/bin/phpcs --config-set installed_paths vendor/cakephp/cakephp-codesniffer

さっきbakeで自動生成されたソースファイルを適当にいじる。
(コードスニッッファーにひっかかるようにコーディング規約を違反する)
いじったら、以下で実行。

vendor/bin/phpcs --standard=CakePHP src/

こんな感じに出る。

FILE: ...myApp/src/Model/Table/ArticlesTable.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 24 | ERROR | Space found after object operator
----------------------------------------------------------------------

Time: 343ms; Memory: 6.75Mb

タスクランナー

まずは Grunt をグローバルにインストールする
(が、これは多分やってある人もいるはず。なのでその人は次へ。)

npm install -g grunt-cli

次に初期化する。

npm init

いろいろ質問されるが、適当にエンターして完了。(まじめに入力してもよい)
これで package.json が作られる

次に grunt と grunt-phpunit をインストールする。

npm install grunt --save-dev
npm install grunt-phpunit --save-dev

同じく直下に以下のような Gruntfile.js を作成する。

Gruntfile.js
module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        phpunit: {
            classes: {
                dir: 'tests/TestCase/'
            },
            options: {
                bin: 'vendor/bin/phpunit',
                bootstrap: 'tests/bootstrap.php',
                colors: true
            }
        },
    });

  grunt.loadNpmTasks('grunt-phpunit');

  // Default task(s).
  grunt.registerTask('default', ['phpunit']);
};

で、gruntコマンド実行。

grunt

結果は以下。よさそうである。

Running "phpunit:classes" (phpunit) task
Starting phpunit (target: classes) in tests/TestCase/
PHPUnit 4.5.0 by Sebastian Bergmann and contributors.

Configuration read from /Users/mymac/myApp/phpunit.xml.dist

IIIII

Time: 1.79 seconds, Memory: 8.50Mb

OK, but incomplete, skipped, or risky tests!
Tests: 5, Assertions: 0, Incomplete: 5.

Done, without errors.

コーディング規約の方も同じく設定する。

npm install grunt-phpcs --save-dev

ついでなので、見た目をグラフィカルにしてみる。(以下のプラグインで実行時間の棒グラフ表示が追加になる)

npm install time-grunt --save-dev

Gruntfile.js に追加。

Gruntfile.js
module.exports = function(grunt) {

    require('time-grunt')(grunt);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        phpunit: {
            classes: {
                dir: 'tests/TestCase/'
            },
            options: {
                bin: 'vendor/bin/phpunit',
                bootstrap: 'tests/bootstrap.php',
                colors: true
            }
        },
        phpcs: {
            application: {
                dir: ['src/**/*.php']
            },
            options: {
                bin: 'vendor/bin/phpcs',
                standard: 'CakePHP'
            }
        }
    });

    grunt.loadNpmTasks('grunt-phpunit');
    grunt.loadNpmTasks('grunt-phpcs');

    // Default task(s).
    grunt.registerTask('default', ['phpunit', 'phpcs']);
};

最後に watch を追加して、ファイルに編集があったら自動で実行されるようにしておく。

npm install grunt-contrib-watch --save-dev

以下追加・編集部分のみ。

Gruntfile.js
    grunt.initConfig({
        watch: {
            phpunit: {
                files: ['src/**/*.php', 'src/**/*.ctp', 'tests/TestCase/**/*.php'],
                tasks: ['phpunit'],
                options: {
                    spawn: false,
                },
            },
            phpcs: {
                files: ['src/**/*.php'],
                tasks: ['phpcs'],
                options: {
                    spawn: false,
                },
            },
        }
    });

    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.registerTask('default', ['watch']);

JavaScript設置

JavaScript は Browserify を使ってモジュール単位で開発したいので、その準備をする。
とりあえずソースファイルは、 src/assets/scripts というディレクトリに設置することにして、

mkdir -p src/assets/scripts

その中に main.js と Hello.js をひな形として設置。
(単にHelloを返すだけのHello.jsをmain.jsからrequireして実行してるだけ)

src/assets/scripts/main.js
(function(){
    'use strict';
    var Hello = require('./components/Hello');
    var hello = new Hello();
    console.log(hello.message);
})();
src/assets/scripts/components/Hello.js
function Hello() {
    'use strict';
    this.message = 'Hello!';
}

module.exports = Hello;

これを Browserify で合体して webroot/js 以下に書きだそうという狙いである。

browserifyのgruntプラグインを入れる。

npm install grunt-browserify --save-dev

だがここで jquery も使えた方が便利なので、bower でインストールしておく。

bower init

いろいろ質問されるが、適当にエンターして完了。
bower.json ができる。
引き続きjQueryをインストール

bower install jquery --save

これでjqueryが入ったので、jqueryの場所をpackage.jsonに記述しておく。

package.json
  "browser": {
      "jquery": "./bower_components/jquery/dist/jquery.js"
  }

最後、Gruntfile.js に以下追加。

Gruntfile.js
        browserify : {
            dist : {
                src : 'src/assets/scripts/main.js',
                dest : 'webroot/js/build.js'  // 出力するファイル名
            }
        },
        watch: {
            browserify: {
                files: ['src/assets/**/*.js'],
                tasks: ['browserify'],
                options: {
                    spawn: false,
                },
            },
        }

  grunt.loadNpmTasks('grunt-browserify');

jquery使うぞってことで main.js の上の方に以下を追加。

src/assets/scripts/main.js
var $ = require('jquery');

grunt コマンドを走らせて、watch状態になったら、先ほどのHello.jsを適当に編集してみる。
結果、

Running "watch" task
Waiting...
>> File "src/assets/scripts/components/Hello.js" changed.

Running "browserify:dist" (browserify) task

となって、webroot/js/ 以下に build.js が生成されていれば成功だ。

JavaScriptテスト

qunit は今さら〜ってことなので mocha にしてみる。
まずは npmでインストールする。

npm install -g mocha

テスト用jsの設置先を tests/scripts 以下にする。(新規ディレクトリ作成)

mkdir tests/scripts
vim tests/scripts/test.js

エディターで以下のようなテストスクリプトを保存する。

tests/scripts/test.js
var assert = require("assert");

describe('Array', function(){
  describe('#indexOf()', function(){
    it('should return -1 when the value is not present', function(){
      assert.equal(-1, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
    });
  });
});

ここで mocha の動作確認。

mocha tests/scripts/test.js

以下のように出ればOKだ。

  Array
    #indexOf()
      ✓ should return -1 when the value is not present 


  1 passing (10ms)

実際的なテストを追加する。

tests/scripts/test.js
var assert = require("assert");

var Hello = require('../../src/assets/scripts/components/Hello');
var hello = new Hello();

describe('Array', function(){
  describe('#hello()', function(){
    it('should return Hello when we call hello.message', function(){
      assert.equal('Hello!!', hello.message);
    });
  });
});

続いてgruntから実行するのに、 grunt-simple-mocha を入れる。

npm install grunt-simple-mocha --save-dev

Gruntfile.jsに以下を追加。

Gruntfile.js
        simplemocha: {
            options: {
                ui: 'bdd',
                reporter: 'nyan'
            },
            all: { src: ['tests/scripts/**/*.js'] }
        },
        watch: {
            simplemocha: {
                files: ['src/assets/**/*.js', 'tests/scripts/**/*.js'],
                tasks: ['simplemocha'],
                options: {
                    spawn: false,
                },
            },
        }

  grunt.loadNpmTasks('grunt-simple-mocha');

再び、

grunt

して、watch状態になったら、テストファイルを書き換えてみる。
以下のようになれば良い。

Running "watch" task
Waiting...
>> File "tests/scripts/test.js" changed.

Running "simplemocha:all" (simplemocha) task
 4   -_-_-_,------,
 0   -_-_-_|   /\_/\ 
 0   -_-_-^|__( ^ .^) 
     -_-_-  ""  "" 

  4 passing (17ms)

この辺で、だんだんGruntfile.jsが大きくなってきて見づらくなってきたと思う。
それがgruntの弱点だとも言われているが、そもそも先人たちが作り上げた巨大化したGruntfile.jsを最初っからバーンと渡されてこれでやるんだと説明されても、もう既に中身を読む気にならない状態な訳である。
なのでここではこうやって、たらたらと一つずつ設定している。
自分で一つずつ設定していって、最後、消すなら消す、使うなら残す、追加するなら追加する、自分で考えて決めればよい。

コントローラとテンプレート

JavaScriptのテストまでやったが、まだその結合したjsが実際に動いているのかどうか、確認していない。
ということで、ここで再びbakeコマンドを使ってコントローラとテンプレートを作成し、jsファイルを埋め込んでみる。
Articlesモデルは作成済みなので、同じように、

bin/cake bake controller articles
bin/cake bake template articles

とやって、

bin/cake server

でサーバーを起動、 http://localhost:8765/ にアクセスする。

src/Template/Layout/default.ctp を開いて、ヘッダー部分に以下を追加。

src/Template/Layout/default.ctp
    <?= $this->Html->script('build') ?>

http://localhost:8765/articles を開いてみて、コンソールにHelloと出ていればOKである。
動いている。

JavaScript構文チェック

引き続きjshintで構文チェックを行う。

npm install grunt-contrib-jshint --save-dev

Gruntfile.jsに以下を追加。

Gruntfile.js
        jshint: {
            options: {
                jshintrc: true
            },
            files: ['src/assets/**/*.js', 'tests/scripts/**/*.js']
        },
  grunt.loadNpmTasks('grunt-contrib-jshint');

とりあえず実行してみると、

grunt jshint

特に mocha のテストのところでエラーが大量にでる。
.jshintrc ファイルを作成してオプションを設定。
とりあえずこんな感じにしてみた。

{
    "curly": true,
    "eqnull": true,
    "eqeqeq": true,
    "undef": true,
    "expr" : true,
    "globals": {
        "jQuery": true,
        "module": false,
        "require": false,
        "console": false,
        "describe": false,
        "it": false,
        "before": false,
        "beforeEach": false,
        "after": false,
        "afterEach": false
    }
}

watch はさっきのsimplemochaのところに追加しておけばいいだろう。

Gruntfile.js
            simplemocha: {
                files: ['src/assets/**/*.js', 'tests/scripts/**/*.js'],
                tasks: ['simplemocha', 'jshint'],
                options: {
                    spawn: false,
                },
            },

コードの圧縮とsourceMap

grunt-contrib-uglify のインストール。

npm install grunt-contrib-uglify --save-dev

Gruntfileの編集。圧縮して build.min.js を作る。

Gruntfile.js
        uglify: {
            my_target: {
                options: {
                    sourceMap: true
                },
                files: {
                    'webroot/js/build.min.js': ['webroot/js/build.js']
                }
            }
        },
        watch: {
            simplemocha: {
                files: ['src/assets/**/*.js', 'tests/scripts/**/*.js'],
                tasks: ['simplemocha', 'jshint', 'uglify'],
                options: {
                    spawn: false,
                },
            },
        }

    grunt.loadNpmTasks('grunt-contrib-uglify');

テンプレート(レイアウト)の書き換え。

src/Template/Layout/default.ctp
    <?= $this->Html->script('build.min') ?>

Gitリポジトリ

最後にリポジトリに登録する。
.gitignoreにいくつか追加する。

.gitignore
/webroot/coverage/*
/node_modules/*
/bower_components/*

add して commit して pushする。

git add .
git commit -m "Improve project file"
git push origin master

他の開発メンバーは、

git clone https://github.com/xxxxxxxxx/myApp.git
curl -sS https://getcomposer.org/installer | php
cd myApp/
sudo php ../composer.phar install
sudo vendor/bin/phpcs --config-set installed_paths vendor/cakephp/cakephp-codesniffer
npm install
bower install

サーバー起動してみて。

bin/cake server

gruntでwatch開始。

grunt

以上終了。さあ、作るぞと。

95
103
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
95
103