PhpStormからCakePHPをGrunt.jsで起動する

先日、第7回PHP関西勉強会でLTをさせて頂きました。

私の中ではLTの構成として

  • GruntとCakePHP
  • PhpStormとGrunt

という二部構成だったのですが、まぁこれが5分で終わるはずもなくほどんど解説すること無く終わってしまったので、フォロー記事を書いてみました。

  • PhpStorm 6.0.3

GruntとCakePHP

まずは第一部、GruntとCakePHPの構成についてです。
  • ・CakePHPのフォルダ構成などに合わせたビルド実行
  • ・CSS/JS/PHP(CTP)の変更監視・LiveReload
  • ・PHP -Sを使ったサーバ起動(PHP5.4 <)
  • ・Apache・nginxへのリバースプロキシ(<PHP5.3)

という処理をGrunt.jsを使って実行させる。という内容です。

Gruntfile.js 一式
https://gist.github.com/kamiyam/6025872
CakePHPフォルダ一式
https://bitbucket.org/kamiyam/grunt-cakephp
</dl>

(function() {
  "use strict";
  var mountFolder, proxySnippet;

  mountFolder = function(connect, point) {
    return connect["static"](require('path').resolve(point));
  };

  proxySnippet = require("grunt-connect-proxy/lib/utils").proxyRequest;

  module.exports = function(grunt) {
    var config, serverProcess, serverStart, verbose;
    config = {
      listen: 3001,
      server: {
        port: 3000,
        start: "php -S localhost:",
        ini: "/usr/local/etc/php/5.4/php.ini",
        root: "app/webroot"
      }
    };
    serverStart = config.server.start + config.server.port + "";
    if (config.server.ini) {
      serverStart = serverStart + " -c " + config.server.ini;
    }
    if (config.server.root) {
      serverStart += " -t " + config.server.root;
    }
    console.log(serverStart);
    verbose = grunt.verbose;
    verbose.subhead(serverStart);
    serverProcess = require('child_process').exec(serverStart);
    serverProcess.stdout.on("data", function(d) {
      return grunt.log.writeln(d);
    });
    serverProcess.stderr.on("data", function(d) {
      return grunt.log.error(d);
    });
    serverProcess.on("exit", function(code) {
      if (code > 0) {
        grunt.log.error("Exited with code: %d.", code);
        return;
      }
      return verbose.ok("Exited with code: %d.", code);
    });
    grunt.initConfig({
      pkg: grunt.file.readJSON("package.json"),
      c: config,
      connect: {
        options: {
          hostname: "localhost",
          port: '<%= c.listen %>',
          middleware: function(connect, options) {
            return [proxySnippet, mountFolder(connect, '.')];
          }
        },
        proxies: [
          {
            context: "/",
            host: "localhost",
            port: '<%= c.server.port %>',
            https: false,
            changeOrigin: false
          }
        ]
      },
      watch: {
        options: {
          livereload: true
        },
        php: {
          files: ["app/View/**/*.php", "app/Config/*.php"]
        },
        ctp: {
          files: ["**/*.ctp"]
        }
        webroots: {
          files: ["app/webroot/**/**.*"]
        }
      },
      open: {
        server: {
          path: "http://localhost:<%= c.server.port %>"
        }
      },
      coffee: {
        grunt: {
          files: {
            "_Gruntfile.js": "Gruntfile.coffee"
          }
        }
      }
    });
    require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
    grunt.registerTask("init", ["coffee:grunt"]);
    return grunt.registerTask("default", ["configureProxies", "connect", "open", "watch"]);
  };

}).call(this);

Gruntで実行している内容は非常に単純です。

Wachタスク(watch:項目)で、CakePHP用に設定したファイルの監視
Gruntと同じプロセスでPHPのビルドインサーバを起動しています。
また、Openタスクで同時にデフォルトのブラウザが起動するはずです。

LiveReload用のブラウザ拡張をインストールしておけば、ファイルの変更を行う度にリロードがかかります。

当然、別のアプリケーションサーバでPHP動かす場合もあるので、リバースプロキシ(proxies:項目)を使ってApacheなどが同時に起動している環境でのLiveReloadも実行出来るようにしています。

PhpStormとGrunt

通常、Grunt.js単体ではターミナルなどから実行しなければならず少し面倒なので、PhpStorm上からショートカットキー(私の環境ではCtrl + returnなど)でGrunt を実行出来るようにします。

PhpStorm では 「Tool」>「Run command...」でコマンドを実行できるのですが、NodeやGruntにパスが通っていない場合があります。
そこで、(例えばMacで)$PATHに設定されているコマンドを実行出来るようにします。

まず、Info.plistを編集します。


$ vim /Applications/Phpstorm.app/Contents/Info.plist

LSEnvironment という項目を追加します。


<key>LSEnvironment</key>
<dict>
    <key>PATH</key>
    <string>[Your Path Value]</string>
</dict>

"[Your Path Value]"の部分は自身の環境の値を貼り付けます。

私の環境では rbenv や nodebrew を使っているので、そこへのパスが重要になります。


$ echo $PATH
/Users/xxxxx/.rbenv/shims:/Users/xxxxx/.rbenv/bin:/Users/xxxxx/.nodebrew/current/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

次に、下記コマンドを実行します。


$ /System/Library/Frameworks/CoreServices.framework/Frameworks/
LaunchServices.framework/Support/lsregister -v -f /Applications/PhpStorm.app

lsregister: processing /Applications/PhpStorm.app

(via. http://ify.io/getting-webstorm-external-tools-to-work-on-webstorm-on-osx/ )

これでPhpStormにPATHが通っているはずです。
(※この仕組みについて自分ではいまいち理解できていないですが・・・)

注意点を一つ。OS上のPATHの値を変更したら、Info.plist の値を変更して上記コマンドを再実行する必要があります。

これで、PhpStorm上からgruntへのパスが通り実行出来る状態です。

次にgruntの実行をキーボードショートカットで割り当てられるようにします。

「Preferences」 > 「External Tools」 から 画面中央下の「+」でGruntコマンドを設定します。

「Program:項目」には 「grunt」
「Working directory:項目」 には 「$ProjectFileDir$/」 か 「$FileDir$/」
プロジェクトフォルダ直下に必ずGruntfile.jsがあるなら、$ProjectFileDir$ で
プロジェクトフォルダ以下、階層の下の方に配置されるなら、$FileDir$で

「Parameters:項目」が空なのは grunt [task] の [task]を省略(デフォルト起動)しているからで、「test」や「server」など自分が作ったタスクあればそのタスク名を入れればOKです。

「Preferences」 > 「Keymap」で任意のショートカットを割り当てます。

この設定が完了したらPhpStormから設定したショートカットを押すとGrunt(今回の設定だとサーバ)が起動するようになっています。

次に、LiveReload用の拡張機能があるので自分の使うブラウザのものをチョイス
How do I install and use the browser extensions?

Chromeなど メニューから LiveReload の ボタンをクリックして白丸から黒丸に。(中央の白丸が黒丸の場合はそのまま)

Live Reload

.ctpファイルや app/config フォルダの .php ファイルを変更、保存するとブラウザのリロードが掛かるはずです。
また、PhpStormのコンソール内を選択した状態で cmd + r を押すと、gruntの再実行(サーバの再起動)が実行されます。

ここで、注意すべきはgruntを二重に起動すると当然ポートが塞がれているので、サーバ起動出来ません。

左側の ■ ボタン選択 -> × ボタン で一つ閉じましょう。

Arias c (Composer)

PhpStormからComposerを使う設定手順です。 (※今回CakePHP用のものは使っていません)

プロジェクトにComposerをダウンロードします。


$ cd path/to/project
$ curl -sS https://getcomposer.org/installer | php 
#!/usr/bin/env php
All settings correct for using Composer
Downloading...

Composer successfully installed to: /grunt-cakephp/composer.phar
Use it: php composer.phar

PhpStorm 「Preferences」 > 「Command Line Tool Support」 から 画面中央下の「+」でComposerコマンドを設定します。

Composer を選択

先程ダウンロードした composer.phar へのパスを設定します。

すると、composer.phar に対してエイリアス c が割り当てられます。

「Tools」 -> 「Run Command」 「c」で composer.phar が実行出来ます。

「c init」 を実行すると、composer.json が生成されます。


{
  "require": {
    "cakephp/debug_kit": "2.2.*@dev",
    "cakedc/migrations": "dev-develop"
  },
  "require-dev": {
    "phpunit/phpunit": "3.7.*"
  },
  "config": {
    "vendor-dir": "app/Vendor/"
  }
}

CakePHP用に「config:項目」でパスを設定。

「c install」で記述したPHPUNITなどがダウンロードされます。

ということで、PhpStorm上でCakePHPを開発する設定と環境を作ってみました。
PhpStorm上からgrunt.jsを実行したり、Composerを使ってライブラリのダウンロードが行えるようになりました。

まだまだ、色々触っている所なのでもっと良い設定があるかもしれませんので、ご存知でしたら教えて下さい。