Laradockを使ってCakePHP3+Xdebug+VS Codeの開発環境を構築する。

CakePHP3で作りたいものがあったので、CakePHP3の開発環境を簡単にDockerを使って構築しようと思い立った。最初は自分でdocker-compose.ymlを作成してコンテナを起動してみたけど、どうしてもXdebugでデバッグができなかった。

たまたまLaradockという本来はLaravelフレームワーク用のDockerコンテナキットを見つけた。最後にcomposerでLaravelの代わりにCakePHPをインストールできるらしいからLaradockを使ってみた。LAMP関連(今回はAではなくnginxだけど)のコンテナが全部入りだから(MySQLだけではなくて、PostgreSQLやSQL Serverもある)、自分でdocker-compose.ymlを書くよりはいいだろうと思った。

参考までにこれから構築していく自分の環境は以下の通りである。ここにLaradockを使ってCakePHP3+Xdebug+VS Codeの開発環境を構築する。。

Windows 10 Pro 64 bit
Docker version 17.12.0-ce, build c97c6d6
docker-compose version 1.18.0, build 8dd22a96

以下はいろいろと参考にしたサイトからつまみ食いしなから設定を行った部分を抜き出してまとめていく。

Laradockの設定は、こちらのサイトを途中まで参考にした。

PHPフレームワーク「Laradock」で、手軽にLaravel+Dockerな開発環境を構築する

gitのcloneでLaradockをインストールしている。次にLaradockでCakePHP3に関する設定を行うには、こちらのサイトを参考にした。

LaradockでPHPフレームワーク(Laravel・CakePHP)とCMS(WordPress・Drupal・baserCMS)の開発環境(nginx・php-fpm・mysql)を構築する

.envをコピーして設定して、これでインストール完了ですと言えないのは、コピー&ペーストインストールのいつものこと。このままではphpMyAdminからMySQLコンテナに接続できないとか、細かい問題があった。そしてXdebugでPHPのデバッグをやりたかったので、いろいろ設定を追加していく。

まずは、上記の2つのサイトを参考にしてLaradockをインストールする。自分のところでは、今までの作業でディレクトリはこのようになっている。

 /laradock-test
 ├── laradock
 └── src

.envの設定だが、設定の一番のポイントはポート番号を重ならないこと。既にローカルでPHP+Xdebugが動いていたようなので、ポート番号の指定で嵌まった。使っていないポート番号を設定しておく。以下に今回設定した.envのnginx, MySQL, phpMyAdminの設定を上げておく。

 ### NGINX
 NGINX_HOST_HTTP_PORT=8082
 NGINX_HOST_HTTPS_PORT=443
 NGINX_HOST_LOG_PATH=./logs/nginx/
 NGINX_SITES_PATH=./nginx/sites/
 NGINX_PHP_UPSTREAM_CONTAINER=php-fpm
 NGINX_PHP_UPSTREAM_PORT=9000

## MYSQL
 MYSQL_VERSION=5.7
 MYSQL_DATABASE=default
 MYSQL_USER=default
 MYSQL_PASSWORD=secret
 MYSQL_PORT=3333
 MYSQL_ROOT_PASSWORD=root
 MYSQL_ENTRYPOINT_INITDB=./mysql/docker-entrypoint-initdb.d

### PHP MY ADMIN
 # Accepted values: mariadb - mysql
 PMA_DB_ENGINE=mysql
 # Credentials/Port:
 PMA_USER=default
 PMA_PASSWORD=secret
 PMA_ROOT_PASSWORD=secret
 PMA_PORT=8083

使っていない別のポート番号に設定し直しておく。MYSQL_VERSIONは元の設定の8.0だと認証で失敗してしまったので、8.0ではく5.7に設定したら認証ができた。こちらは何か別のよい方法があるかもしれない。

WORKSPACEとPHP_FPM の設定は以下の通り。修正した箇所だけを上げておく。

 ### WORKSPACE
 WORKSPACE_INSTALL_XDEBUG=true

 ### PHP_FPM
 PHP_FPM_INSTALL_XDEBUG=true
 PHP_FPM_INSTALL_INTL=true

Xdebugを使うのでWORKSPACE_INSTALL_XDEBUGとPHP_FPM_INSTALL_XDEBUGをtrueにして(PHP_FPM_INSTALL_XDEBUGだけでもいいかも?)、PHP_FPM_INSTALL_INTLはCakePHP3で必要なのでtrueにしておく。

.envの設定の最後として、CakePHP3のインストール先のディレクトリも設定しておく。

# Point to your code, will be available at `/var/www`.
APPLICATION=../src/

nginxのドキュメントルートを修正する。設定するファイルは以下のファイルである。

.\laradock\nginx\sites\default.conf

こちらのrootの設定を、CakePHP3のリモート側のドキュメントルートのディレクトリに設定する。今回のプロジェクト名をmycakephpとしておく。

root /var/www/mycakephp/webroot;
ここで一度Docker composeを実行してコンテナを起動しておく。
docker-compose up -d nginx mysql phpmyadmin

workspaceコンテナにログインして、composerを使ってCakePHP3をインストールしておく。こちらは参考サイトの通り。

LaradockでCakePHPの開発環境(nginx・php-fpm・mysql)を構築する

ここではサイトに書いてある通り、以下のコマンドでプロジェクトmycakephpでCakePHP3をインストールした。

 $ composer self-update && composer create-project --prefer-dist cakephp/app mycakephp

nginxからCakePHP3のサイトを参照できるかチェックする。OKならCakePHP3の初期画面が見えるはず。

データベースの接続の設定を.\src\mycakephp\config\app.phpにしておく。

'Datasources' => [

    'default' => [
       :
    'host' => 'mysql',
       :
    'username' => 'default',
    'password' => 'secret',
    'database' => 'default',
       :

このような感じで.envのMySQLの設定に合わせておけば、データベースに接続が成功はずである。

phpMyAdminも確認しておく。こちらも.envのMySQLの設定通りにすればログインできてMySQLの中を参照できるはずである。もちろん、MySQLのパスワードは適当なものに変えること。

サーバ:mysql
ユーザ名: root
パスワード: root

MySQL Workbenchからも接続を確認できた。以下の接続情報でWindowsローカルで接続できた。

Hostname:localhost
Port: 3333
Username: root
password: root

最後にXdebugの設定である。Xdebugのコンテナ側の設定ファイルは次の2つである。同じ内容でコピーすれば大丈夫だった。

.\laradock\php-fpm\xdebug.ini
.\laradock\workspace\xdebug.ini

自分が設定した内容は以下の通りである。とりあえずプロフィラの設定も含めて設定しておく。

 xdebug.remote_host=172.27.7.81
 xdebug.remote_port=9002
 xdebug.idekey=Listen for XDebug

 xdebug.remote_autostart=1
 xdebug.remote_enable=1
 xdebug.remote_connect_back=0
 xdebug.cli_color=1
 xdebug.profiler_enable=1
 xdebug.profiler_output_dir="/var/www/mycakephp/tmp"

 xdebug.remote_handler=dbgp
 xdebug.remote_mode=req

 xdebug.var_display_max_children=-1
 xdebug.var_display_max_data=-1
 xdebug.var_display_max_depth=-1

ここでわからなかったのはxdebug.remote_hostの値だった。結論としてはこちらはWindowsの場合、

ipconfig

で表示されるDocker側の仮想スイッチのアドレスの値を設定しておく。Googleさんに「xdebug リモートデバッグ」で検索して、よく出てくるサイトに書かれている$_SERVER[‘HTTP_X_REAL_IP’]とか$_SERVER[‘REMOTE_ADDR’]の値ではないので注意すること。

docker-compose stop
docker-compose build php-fpm workspace

でphp-fpmとworkspaceのイメージをビルドしなおす。ビルドできたら、

docker-compose up -d nginx mysql phpmyadmin

をDocker Composeを再度実行する。nginxのドキュメントルートにphpinfo()を書いたファイルを置いてアクセスしてみて、正しくxdebugが設定されているかを確認しておく。

クライアント側の開発環境はマイクロソフトのVisual Studio Code(VS Code)を使っている。あらかじめVS Codeの拡張機能であるPHP Debugをインストールしておく。次にVS Codeのデバッグの構成ファイル(launch.json)を修正する。launch.jsonは以下のように設定した。

{
  "version": "0.2.0",
  "configurations": [

   {
    "name": "Listen for XDebug",
    "type": "php",
    "request": "launch",
    "port": 9002,
    "pathMappings": {
      "/var/www":"${workspaceRoot}/src"
     },
    "ignore": [
      "**/vendor/**/*.php"
    ]
   },
   {
    "name": "Launch currently open script",
    "type": "php",
    "request": "launch",
    "program": "${file}",
    "cwd": "${fileDirname}",
    "port": 9002
   }
  ]
 }

portは、xdebug.iniのxdebug.remote_portと同じ値にする。以下のように設定するように言っているサイトもあるが、

      "serverSourceRoot": "/var/www",
      "localSourceRoot": "${workspaceRoot}/src"

serverSourceRoot、localSourceRootとも今後推奨されない設定のようなので、pathMappingsにしておく。pathMappingsの設定は、

"pathMappings": {
    "リモートディレクトリ":"ローカルディレクトリ" 
    },

のようにリモートとローカルのパスをマッピングする設定である。ドキュメントをよく読まずにリモートとローカルを反対にしてしまったので動かなくて悩んだ。こちらはnginxのドキュメントルートのディレクトリではないことに注意する。ドキュメントルートディレクトリ外のファイル(例えば、.\src\mycakephp\src\Controller\AppController.php)をデバックしようとしたときに、pathMappingsにルートディレクトリに設定してしまうとソースファイルが見つからないと言ってくる。そこでソースファイルを格納しているディレクトリを設定しておく。

ignoreの設定をしておかないと、以下のような例外が途中で発生する。どうしてかは不明である。

例外が発生しました

Aura\Intl\Exception: Package 'default' with locale 'ja-JP' is not registered.

.\src\mycakephp\webroot\index.php とかに適当にブレークポイントを設定して、Listen for XDebug”の構成でデバッグを行う。ブレークポイントを設定したところで止まるかとチェックする。後はステップオーバーでプログラムが進むか、ステップインで別のソースを参照できるか、または変数の中身を参照できるかをチェックして完了。

以上でLaradock+CakePHP3+XdebugでVS Codeを使って快適にデバッグができるようになった。以上、再度開発環境を構築する際に忘れないようにメモを残しておく。

追記

同じ設定をMacでやってみたら、niginxコンテナが起動できなかった。原因不明・・

.\laradock\nginx\sites\default.conf にゴミが入っていたのが原因だった。dockerのログを見たら原因がわかった。

無事にMacでCakePHP3のトップページを参照できた。ただしデバッグできない。

Macでもデバッグができるようなった。ただし、xdebug.ini に

xdebug.remote_host=docker.for.mac.localhost

を設定すればOKのようだ。情報はこちらのサイトから。

PHP on Laradock w/ Visual Studio Code(VS Code)でデバッグ環境 (特にon Mac)

ただし、MacでDockerはとても遅い。ブラウザが表示し終わるのに時間がかかる。こちらは問題になっているようで、将来改善されるのかな?

追記2

VS CodeのターミナルからDocker Composeすると、IO Errorが出る。普通にPower Shellで実行するとうまく行く。これは、issuesに上がっているから周知の問題なのかな?

追記3

MySQLのコンテナが起動できなかったので、解決策はこちらから

LaradockでMySQLがどうしても立ち上がらない人あつまれー!

CakeEmailでメール本文が文字化けする

とっても悩んで解決したのでメモを残しておく。

CakePHPのCakeEmailを初めて使ってみたら、送信したメールの本文が文字化けする。今までQdmailを使っていたので、そんな現象には合わなかった。

Googleさんに聞いてみると

CakeEmailを使っていて本文が文字化けたらとりあえずcharsetを疑ってみる

なんて書いてあるけど、charsetにISO-2022-JPを設定しても現象は変わらない。今度はメールヘッダがも文字化けする。

しかたないので、CakeEmailをNetBeansのデバッガで追ってみる。CakeEmailの_encodeString()メソッド辺りに見当をつけてブレークポイントを設定する。デバッグしてみると何とmb_convert_encoding()を処理する前にreturnしていた。

原因はmb_convert_encoding()関数が存在しないことだった。つまり、mbstringモジュールをインストールしていないことが、そもそもの原因である。

php.iniにmbstringモジュールを読み込んであげて、mbstringモジュールの設定を適当にしてphpinfo()でmbstringがサポートされていることを確認する。

今度は文字化けせずにメールを送れた。

WindowsのローカルPCに開発環境にPHPをインストールしたままで動かしたのが原因かもしれない。

PHP 5.6 にアップデートする

ここのサーバーにインストールされているPHPを5.6にアップデートする。今さら遅いくらいですが。本当なら7にアップデートすればいいのですが・・・。

remiのレポジトリを変更すれば簡単にできました。詳しくはこちらのサイトを参照のこと。この通りにやりました。

WordPressの固定ページの中に投稿最新一覧を表示する

お客さんのWordPressサイトでカテゴリごとに投稿の最新一覧を表示している固定ページがあります。いい加減手作業で更新するのも面倒になってきましたので、プログラムで対応します。

Googleさんに聞いてみるとショートコードを登録して呼び出すようなことをみなさん書いています。何と皆さん出しているPHPのコードはすべて同じです。所謂コピペ記事です。何か気持ち悪い状態になっています。さて、誰がオリジナルなんでしょうか?

しかしながら、WordPressって固定ページ内にPHPのプログラムを書けないのでしたね。今ごろ気が付きました。

そのコードをコピペしてもいいのですが、2つのカテゴリの記事一覧を表示したいので、2つコピペしなければいけませんし、第一コピペコピペで気持ち悪いです。パラメーターを渡して切り替えなんて改造すればいいのですが、それも面倒ということで、何か別の方法を探します。

What’s New Generator というよさげなプラグインが見つかりました。早速インストールして試してみます。しかし、カテゴリのフィルターが1つで固定されてしまうので、2つのカテゴリの最新一覧を並べることができません。惜しいですがこれでありません。

次に当たったのは、Shortcodes Ultimateです。基本的にショートコードでWordPressのいろいろな部分にアクセスできるのですが、今回は投稿のカテゴリ別にタイトルだけを最新3件の記事を一覧に表示します。具体的には、

[su_posts template="templates/teaser-loop.php" posts_per_page="3" tax_term="8"]

なんて書いてしまいます。出力されるタイトルがHTMLのコードのh2タグで吐き出してしまいますので、この辺りは本当なら修正しないといけないのでしょう。CSSで指定してデザインを合わせて作業完了です。

 

#baserCMS で管理者ページにログインできないときの対応メモ

今のお客さんのIRサイトをリニューアルをしたいという案件で、以前テストで作成したbaserCMSのテストサイトを復活させます。テストサイトはvagrant+VirtualBoxでローカルのPCに作成しています。

久しぶりにvagrant upでサーバーを起動してきます。Vagrantで起動したらberkshelfでのmysqlのChefのクックブックの仕様が変わって動かないというトラブルがありましたが、これは自分でレシピを作って対応します。後はMySQLのバックアップを投入すれば、今まで作成したサイトにはアクセスできます。しかし、baserCMSの管理者ページにはログインできません。

ここでNetBeansのデバッガを使ってログインの処理を追っていきます。ログインが成功した後のリダイレクトの処理以降がうまくいっていないようです。管理者ページのトップにリダイレクトしようとして、どういう訳か遷移しません。

調べてみるとCakePHPのエラーログを見ろとあります。ログには

2015-08-18 11:16:43 Warning: Warning (2): Unknown: Failed to write session data
(files). Please verify that the current setting of session.save_path is correct
(/vagrant/app/tmp/sessions) in [Unknown, line 0]

なんて書かれています。セッションデータをうまく書き込まれていないようです。

Googleさんにセッションデータがなぜ書き込めないかを聞いてみると、Vagrantの同期フォルダの権限の設定が間違っているとのこと。こちらのページのsynced_folderの設定を行うとうまく行きました。オーナーとグループをapacheにすればよさそうです。

baserCMSのGitHubにVagarantFileのサンプルがありますが、こちらのsynced_folderの設定のままだと、私のところではうまくセッションの書き込みができませんでした。今までうまくいっていましたがどうしてなのだろうか?

以上、2日位悩んだ結果のメモです。まずはCakePHPで何かあったらログを読めということでしょうか。いつも基本を忘れます。

CakePHPのDebugKitプラグインでのエラー

CakePHPを2.6.3にバージョンアップしたら、コントローラーでセットした値がビューに渡っていない。色々調べてみるとDebugKitプラグインでエラーをしている。

Could not load class DebugKitLogListenerLog

このエラーメッセージから調べると、GitHubのDebugKitのissusが見つかった。

https://github.com/cakephp/debug_kit/issues/144

APP/Plugin/DebugKit/Lib/Panel/LogPanel.phpの25行目を

'engine' => 'DebugKit.DebugKitLogListener',

'engine' => 'DebugKit.DebugKitLog',

にする。これでエラーがなくなった。

#CakePHP 3を試してみました。

環境を作ってインストールできたので、CakePHP 3を試してみました。試したみたと言ったけど、簡単にいつものブログのデータベースを作って、ControllerとModelをBakeして、使用している値をダンプしてみる。あとは、CakePHP3のドキュメントを読んでみる。

つまるところ、大幅に変わったMVCのModelの部分が肝かな。ModelがTable ObjectEntitiesになって、ORMがどう関わってくるというところが大事か。それとコントローラーとTable ObjectEntities、ビューがどう関しているかをもっと理解しなくてはいけない。

CakePHP3のドキュメントTable ObjectEntitiesを訳しながら読み進めていたけど、これはおもしろぞ。

Berkshelf のWindowsへのより簡単なインストール方法。

以前、Berkshelf のインストールが面倒、と書きましたが、もっと簡単なイントール方法が紹介されていました。紹介されていたのは、「CakePHPで学ぶ継続的インテグレーション」という本です。ここで、ChefDK(Chef Development Kit)を利用する方法が書かれています。

ChefDKを使えば、Rubyやgemをインストールことなく、ChefやBerkshelfなどのChefに関連するツールをまとめてWindows上にインストールできます。面倒なRuby関連のツールをChefDKでWindowsに簡単にでききます。これでChefを使いたいだけなのに、Ruby関連のインストールと格闘しなければいけない、なんてことがなくなります。

#PHP のis_file()で必ずfalseが返ってしまう

タイトル通り、PHP のis_file()で必ずfalseが返ってしまうということで、丸半日悩んだこと。原因は簡単なことでした。簡単なことだけど、どうせ忘れるので、覚え書きを書いておきます。

ファイルが存在するのに、is_file()で必ずfalseが返ってしまいます。調べてみたら、フルパスでファイルを指定しろとか言われます。最初からフルパスの指定です。

ローカルのVagrantで動かしているサーバー上では、正しくtrueが返ります。テストサーバーで使用している実サーバーではfalseになってしまいます。両方ともCentOSでバージョンも同じ。PHPもバージョンも同じです。

$path_name = Configure::read('Pdf.upload_dir') . $fileName;
if( is_file($path_name) ){
    :
    :

このようなCakePHPのコードです。デバックすると正しくパスからファイル名が設定されています。

ふと気なったのは、ファイル名の後ろに空白が入っていた。まさかと思ってtrim()で空白をカットしてみる。

するとうまくいった。だけど、どうしてローカルで動いていたかは謎です。

phpMyAdminでログインできない問題。#php

テストサーバーを作りたくて、いろいろとインストールします。しかし、phpMyAdminがログインできない問題に遭遇。「phpMyAdmin ログインできない」でGoogleさんに聞いた結果のサイトに書いてある通り phpMyAdmin の config.inc.php の設定ファイルを変えてもダメ、MySQLの認証を設定設定してもダメ。

しかたないので、一旦phpMyAdminを削除して、再度インストール。これもダメ。phpMyAdminの最新版をソースからダウンロードしてインストール。こちらはMySQLが古いと怒られてダメ。もうダメダメです。

ふと、Apahceのエラーログを見てみると、

[Tue Sep 23 16:46:03 2014] [error] [client 192.168..xxx.xxx] PHP Warning:  Unknown: POST Content-Length of 104 bytes exceeds the limit of -1048576 bytes in Unknown on line 0, referer: http://192.168..xxx.xxx/phpmyadmin/index.php

というのが出ていた。Unknown: POST Content-Length of というのをまたまた Googleさんに聞いてみると、php.ini の post_max_size の値が小さいとのこと。今、設定している post_max_size の値を確認してみる。すると、

; Maximum size of POST data that PHP will accept.
; http://www.php.net/manual/en/ini.core.php#ini.post-max-size
post_max_size = 3232323232323232323232323232323232323232323232323232323232323232M

となっていた。こらー誰が設定した???

post_max_size = 32M

に設定すると、無事にphpMyAdminにログインできた。phpMyAdminの問題というよりも、PHPの問題。やはり、ログを見ることは大事。