phpenv + php-build + composer で開発環境作ってみた

以前、php勉強会で最近のphpの開発環境も簡単に構築できるとかという話を聞いていたので、調べながらちょっと開発環境を作ってみた。

Apache install

自分のmac(Mac10.8)ではあらかじめApacheは入っているのですが、せっかくなのでApache installから。

1
2
$ brew tap Homebrew/dupes
$ brew install httpd

ApacheやPHPはhomebrewのFormulaでは管理されてないのですが、Homebrewに新たに追加されたtapコマンド使うことで任意のFormulaを追加できるらしい。
ちなみにtapが使えないときはbrewのupdateが必要。

続いてhttpd.confの設定

/usr/local/Cellar/httpd/2.2.22/etc/apache2/httpd.conf の 155行目付近

1
2
3
4
5
6
7
8
9
10
11
12
13
# ServerName gives the name and port that the server uses to identify itself.

# This can often be determined automatically, but we recommend you specify

# it explicitly to prevent problems during startup.

#

# If your host doesn't have a registered DNS name, enter its IP address here.

#

ServerName localhost:80

DocumentRootを変更するならば、

1
2
3
4
5
6
7
8
9
10
#

# DocumentRoot: The directory out of which you will serve your

# documents. By default, all requests are taken from this directory, but

# symbolic links and aliases may be used to point to other locations.

#
DocumentRoot "/Library/WebServer/Documents/"

php5のモジュールはコメントアウトされているときはコメントアウトを削除しておく

1
LoadModule php5_module libexec/libphp5.so

.phpでphpを実行できるようにMIMEタイプの追加

1
2
3
4
5
<IfModule mime_module>

AddType application/x-httpd-php .php

</IfModule>

indexファイルにindex.phpを使えるように修正

1
2
3
4
5
<IfModule dir_module>

DirectoryIndex index.html index.php

</IfModule>

.htaccessでURLのoverwriteを許可

1
2
3
4
5
<Directory "/usr/local/Cellar/httpd/2.2.22/share/apache2/htdocs">

AllowOverride All

</Directory>

このままでは起動時に
The Log File is not empty, but the Build did not fail. Maybe just warnings got logged. You can review the log in /tmp/php-build.*****.20130204001646.log のようなエラーがでるので、ログ用のディレクトリを追加します。

1
2
$ mkdir /usr/local/Cellar/httpd/2.2.22/var/apache2/log
$ mkdir /usr/local/Cellar/httpd/2.2.22/var/apache2/run

これでApacheの設定はとりあえず終了

1
2
3
4
5
6
7
8
9
10
11
12
13
# 起動
$ sudo apachectl start

# 停止
$ sudo apachectl stop

# 再起動
$ sudo apachectl restart

$ Apache version
$ httpd -v
Server version: Apache/2.2.22 (Unix)
Server built: Aug 24 2012 17:16:58

MySQL install

1
2
$ brew install mysql
$ mysql_install_db --verbose -user=$(whoami) --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp

phpenvinstall

続いてphpenvのインストール。phpenvはrbenvを使って異なるバージョンのphpを管理するツール。

1
2
3
4
5
6
7
8
9
$brew install --HEAD phpenv

# .bashrcなどに追加
$ vi ~/.bashrc
export PATH="$HOME/.phpenv/bin:$PATH"
eval "$(phpenv init -)"

# 設定したPATHの設定を有効にする
$ source ~/.bashrc

php-build install

php-buildは phpのダウンロードからインストールまでを行うツール

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ brew install php-build

Add the following script block to `$HOME/.bashrc`, `$HOME/.zshrc`, or your shell's equivalent configuration file.

Change `5.x.x` to the version of PHP you'd like your shell to default to or remove `php-version 5.x.x &gt;/dev/null`
if you do not wish to have a default version of PHP loaded into your `$PATH`. The large comment block is optional:

###### #

# php-version (activate default PHP version and autocompletion)

# PHP_HOME => should reflect location of compiled PHP versions

# PHPVERSION_DISABLE_COMPLETE=1 => to disable shell completion

###### #

export PHP_VERSIONS=$(dirname $(brew --prefix php))
[ -f $(brew --prefix php-version)/php-version.sh ] &&
source $(brew --prefix php-version)/php-version.sh && php-version 5.x.x >/dev/null
/usr/local/Cellar/php-version/0.9.3: 3 files, 20K, built in 2 seconds

# php-buildのPATHを追加

$ vi ~/.bashrc
export PATH=/usr/local/bin:$PATH

# 設定したPATHの設定を有効にする

$ source ~/.bashrc

ダウンロードできるバージョンの確認

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ php-build --definitions
5.2.17
5.3.10
5.3.11
5.3.11RC1
5.3.11RC2
5.3.12
5.3.13
5.3.14
5.3.15
5.3.2
5.3.3
5.3.6
5.3.8
5.3.9
5.3.9RC3
5.3.9RC4
5.3snapshot
5.4.0
5.4.0RC1
5.4.0RC2
5.4.0RC3
5.4.0RC4
5.4.0RC5
5.4.0RC6
5.4.0RC7
5.4.0RC8
5.4.0alpha3
5.4.0beta1
5.4.0beta2
5.4.1
5.4.1RC1
5.4.1RC2
5.4.2
5.4.3
5.4.4
5.4.5
5.4snapshot

php-buildはApacheのモジュールには対応してないようなので、Apacheのモジュールが生成されるように設定を変更します。
/usr/local/share/php-build/default_configure_options に以下を追加します。

1
2
# 以下の1行を追加
--with-apxs2=/usr/local/sbin/apxs

これでphpを自動で展開してモジュールも生成します。適当なphpをホームディレクトリ以下にinstallして展開します。

1
2
3
4
5
$ php-build 5.4.5 ~/.phpenv/versions/5.4.5
[Info]: Loaded pyrus Plugin.
[Info]: Loaded xdebug Plugin.
[Info]: php.ini-production gets used as php.ini
[Info]: Building 5.4.0 into /Users/***/.phpenv/versions/5.4.5

おそらくmake時にいろいろとエラーが出るので、その都度解決してあげる必要があります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## # エラーが出た
## configure: warning: You will need re2c 0.13.4 or later if you want to regenerate PHP parsers. ./configure: line 6372: /usr/local/sbin/apxs: No such file or directory configure: error: Aborting

# 追加
$ brew install re2c

## # エラーが出た
## configure: error: png.h not found.
# 追加
$ brew install libpng

## # エラーが出た
## configure: error: mcrypt.h not found. Please reinstall libmcrypt.
# 追加
$ brew install libmcrypt

# そして改めて
$ php-build 5.4.5 ~/.phpenv/versions/5.4.5
[Info]: Loaded pyrus Plugin.
[Info]: Loaded xdebug Plugin.
[Info]: php.ini-production gets used as php.ini
[Info]: Building 5.4.5 into /Users/**_/.phpenv/versions/5.4.5
[Skipping]: Already downloaded and extracted http://www.php.net/distributions/php-5.4.5.tar.bz2
[Pyrus]: Downloading from http://pear2.php.net/pyrus.phar
[Pyrus]: Installing executable in /Users/_**/.phpenv/versions/5.4.5/bin/pyrus
[XDebug]: Downloading http://xdebug.org/files/xdebug-2.2.0.tgz
[XDebug]: Compiling in /var/tmp/php-build/source/xdebug-2.2.0
[XDebug]: Installing XDebug configuration in /Users/***/.phpenv/versions/5.4.5/etc/conf.d/xdebug.ini
[XDebug]: Cleaning up.
[Info]: The Log File is not empty, but the Build did not fail. Maybe just warnings got logged. You can review the log in /tmp/php-build.5.4.5.20130201001646.log
[Success]: Built 5.4.5 successfully.

ちなみに、後ほどモジュールの切替をおこなうのでインストールしたモジュールは退避させておきます。

1
2
# libphp5.so を退避しておく
$ mv /usr/local/Cellar/httpd/2.2.22/libexec/libphp5.so ~/.phpenv/versions/5.4.5

phpenvで確認

1
2
3
$ phpenv versions
* system (set by /Users/***/.phpenv/version)
5.4.5

system はあらかじめmacに入っているphpです。
php-buildでインストールしたphpはユーザーのホームディレクトリの.phpenvディレクトリに展開されてます。

1
2
3
4
5
6

# ユーザーのホームディレクトリ

.phpenv/
|--versions
|--5.4.5

そしてphpのバージョンを切替え

1
2
3
4
5
6
7
8
$ phpenv global 5.4.5

# バージョン確認
$ php -v
PHP 5.4.5 (cli) (built: Feb 1 2013 00:21:44)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
with Xdebug v2.2.0, Copyright (c) 2002-2012, by Derick Rethan

これでphpのバージョンは切替りました。
では、DocumentRoot にphpinfo()を実行するファイルをおいて、バージョンが切替っていることを確認。

が、こちらでは変わってない。
これは、phpenvはApacheのphpモジュールの切替えを行わないので、Apacheのphpは切り替わってません。
ということで、Apacheのモジュール切替スクリプト(rbenv-apache-version)を追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# ~/.phpenv/libexec/rbenv-apache-version
# !/usr/bin/env bash

set -e
[ -n "$RBENV_DEBUG" ] && set -x

# Provide rbenv completions
if [ "$1" = "--complete" ]; then
echo system
exec rbenv-versions --bare
fi

RBENV_VERSION="$1"
RBENV_ON_FILE="${RBENV_ROOT}/versions"
APACHE_ROOT="/usr/local/Cellar/httpd/2.2.22"
APACHE_MODULE_PATH="${APACHE_ROOT}/libexec"

# Make sure the specified version is installed.
RBENV_PREFIX_PATH="${RBENV_ROOT}/versions/${RBENV_VERSION}"
if [ ! -d "$RBENV_PREFIX_PATH" ]; then
echo "rbenv: version '${RBENV_VERSION}' not installed" >&2
exit 1
fi

PHP_MODULE_PATH="$RBENV_PREFIX_PATH/libphp5.so"

if [ ! -f "$PHP_MODULE_PATH" ]; then
echo "apache module not found \'${PHP_MODULE_PATH}'" >&2
exit 1
fi

if [ ! -d "$APACHE_MODULE_PATH" ]; then
echo "Directory not found \'${APACHE_MODULE_PATH}'" >&2
exit 1
fi

echo "copy ${PHP_MODULE_PATH} to ${APACHE_MODULE_PATH}"
cp "$PHP_MODULE_PATH" "$APACHE_MODULE_PATH"

echo "Restarting apache..."
sudo apachectl restart

実行権限を付与して、phpの切替えとApacheのモジュールの切替えを行います。

1
2
3
4
5
6
chmod 755 /Users/**_/.phpenv/libexec/rbenv-apache-version
$ phpenv global 5.4.5
$ phpenv apache-version 5.4.5
copy /Users/_**/.phpenv/versions/5.4.5/libphp5.so to /usr/local/Cellar/httpd/2.2.22/libexec
Restarting apache...
Password:

Apacheが再起動して、モジュールが読込まれるとphpのバージョン切替ができます。
ちなみにphp5.4.0からはビルトインサーバーもあるので、そちらを使えばApacheのモジュール切替は不要です。

1
2
3
4
5
6
# 適当なディレクトリにおいて
$ php -S localhost:8080
PHP 5.4.5 Development Server started at Fri Feb 1 01:48:54 2013
Listening on localhost:8080
Document root is /Users/***/YOUR-APP-DIR
Press Ctrl-C to quit.

composer install

composer は 外部ライブラリの依存管理ツール(PHP 5.3.2 or above)。
rubyでいうところのbundler、nodeでいうところのnpmみたいなものらしい。
登録されているパッケージはPackagistで検索できます。また、自身で作成したパッケージも登録できます。

1
2
3
4
5
6
7

# globalにインストール
$ brew tap josegonzalez/homebrew-php
$ brew install josegonzalez/php/composer

# vendorを作成するディレクトリでphp archiveファイル(composer.phar)をダウンロード
$ curl -s https://getcomposer.org/installer | php

外部ライブラリはカレントディレクトリのcomposer.jsonで管理されます。
jsonファイルで定義したパッケージをautoloadしてくれます。

以下のような感じです。

1
2
3
4
YOUR_PROJECT_DIR
|-- vendor
|-- composer.json
|-- composer.phar

phpのユニットテストフレームワークphpunitと、インテグレーションテストフレームワークcodeceptionをインストールしてみようと思います。
composer.jsonを別個で作成してもいいですが、対話式のパッケージ作成コマンドもあります。今回は対話式のパッケージ作成コマンドで
composer.jsonを作成してみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
$ composer init

Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

# パッケージ名
Package name (<vendor>/<name>) [kazu69/t]: kazu69/TEST_APP

# パッケージの説明
Description []: This app is TEST_APP

# パッケージの作者名
Author [kazu69 <*********@gmail.com>]:

# 安定性の説明 dev, alpha, beta, RC, and stable
Minimum Stability []: dev

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]?

# 必要なパッケージとバージョン
Search for a package []: Codeception
Would you like to define your dev dependencies (require-dev) interactively [yes]?

# 開発環境でパッケージに必要なパッケージとバージョン
Search for a package []: Codeception

# search は非常に遅い
Found 33 packages matching Codeception/Codeception

[0] Codeception/Codeception 1.0.9
[1] Codeception/Codeception 1.0.10
[2] Codeception/Codeception 1.0.11
[3] Codeception/Codeception 1.0.12
[4] Codeception/Codeception 1.0.13
[5] Codeception/Codeception 1.0.14
[6] Codeception/Codeception 1.1.0
[7] Codeception/Codeception 1.1.2
[8] Codeception/Codeception 1.1.3
[9] Codeception/Codeception 1.1.4
[10] Codeception/Codeception 1.1.5
[11] Codeception/Codeception 1.0.10
[12] Codeception/Codeception 1.0.11
[13] Codeception/Codeception 1.0.12
[14] Codeception/Codeception 1.0.13
[15] Codeception/Codeception 1.0.14
[16] Codeception/Codeception 1.0.9
[17] Codeception/Codeception 1.1.0
[18] Codeception/Codeception 1.1.2
[19] Codeception/Codeception 1.1.3
[20] Codeception/Codeception 1.1.4
[21] Codeception/Codeception 1.1.5

Enter package # to add, or a "[package] [version]" couple if it is not listed []: 0
Search for a package []: phpunit/phpunit

# search は非常に遅い
Found 33 packages matching phpunit/phpunit

[0] phpunit/phpunit 3.7.0
[1] phpunit/phpunit 3.7.1
[2] phpunit/phpunit 3.7.10
[3] phpunit/phpunit 3.7.2
[4] phpunit/phpunit 3.7.3
[5] phpunit/phpunit 3.7.4
[6] phpunit/phpunit 3.7.5
[7] phpunit/phpunit 3.7.6
[8] phpunit/phpunit 3.7.7
[9] phpunit/phpunit 3.7.8
[10] phpunit/phpunit 3.7.9
[11] phpunit/phpunit-mock-objects 1.2.0
[12] phpunit/phpunit-mock-objects 1.2.1
[13] phpunit/phpunit-mock-objects 1.2.2
[14] phpunit/phpunit-selenium 1.2.10
[15] phpunit/phpunit-selenium 1.2.11
[16] phpunit/phpunit-selenium 1.2.9
[17] phpunit/phpunit-story 1.0.1
[18] phpunit/phpunit 3.7.11
[19] phpunit/phpunit 3.7.12
[20] phpunit/phpunit 3.7.13
[21] phpunit/phpunit-mock-objects 1.2.3
[22] phpunit/phpunit-selenium 1.2.12
[23] phpunit/phpunit-selenium dev-master
[24] phpunit/phpunit-story dev-master
[25] phpunit/phpunit-mock-objects 1.2.x-dev
[26] phpunit/phpunit-mock-objects dev-master
[27] phpunit/phpunit-mock-objects 1.3.x-dev
[28] phpunit/phpunit 3.7.x-dev
[29] phpunit/phpunit dev-master
[30] phpunit/phpunit 3.8.x-dev
[31] phpunit/phpunit dev-refactoring
[32] phpunit/phpunit dev-symfony-2.2

Enter package # to add, or a "[package] [version]" couple if it is not listed []: 0
Search for a package []:

{
"name": "kazu69/TEST_APP",
"description": "This app is TEST_APP",
"require-dev": {
"codeception/codeception": "1.0.9",
"phpunit/phpunit": "3.7.0"
},
"minimum-stability": "dev",
"authors": [
{
"name": "kazu69",
"email": "*********@gmail.com"
}
],
"require": {

}

}

Do you confirm generation [yes]?
Would you like the vendor directory added to your .gitignore [yes]?

という感じでcomposer.jsonを作成できます。
そのほかのcliのコマンドはドキュメントにまとまってました。

必要なパッケージをインストールします

1
2
3
4
5
$ composer install
Loading composer repositories with package information
Installing dependencies
Nothing to install or update
Generating autoload files

composer.lockとvendorディレクトリが作成されます。
パッケージはvendorディレクトリにインストールされます。
また、vendorにautoload.phpが作成されます。

1
2
3
4
5
6
7
8
YOUR_PROJECT_DIR
|-- .gitignore
|-- composer.json
|-- composer.phar
|-- composer.lock
|-- vendor
|-- autoload.php
|-- composer/

インストールしたライブラリを読込むのはこのautoload.phpをrequireすればいいということなので、とても簡単です。

1
require 'vendor/autoload.php';

composer.lockファイルが生成された段階で、composer.jsonを変更した場合はupdateする必要があります。

1
2
# インストールではなくupdate
$ php composer.phar update

これまでのphpでの外部ライブラリ管理法とちがって、なんだかスッキリした感じです。

Codeception setup

折角なので、、インストールしたCodeceptionのQuickStartだけやってみます。
正直、Codeceptionについてまだ調べてないので、半分妄想レベル。
CodeceptionはPHP製のフルスタックのテストフレームワーク。
受け入れテスト、機能テスト、単体テストがこれだけでできる。Selenium, Mink, ZombieJSなどフロントのテスト機能もオールインワンっぽい。BehatやPHPUintをまとめて使えるようなもの。

ということで、やってみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# dowunload
$ wget http://codeception.com/codecept.phar

# codeception.yml と テストディレクトリ作成
$ php codecept.phar bootstrap

File codeception.yml written - global configuration
tests/unit created - unit tests
tests/functional created - functional tests
tests/acceptance created - acceptance tests
tests/unit.suite.yml written - unit tests suite configuration
tests/functional.suite.yml written - functional tests suite configuration
tests/acceptance.suite.yml written - acceptance tests suite configuration
Building initial Guy classes
/YOUR_PROJECT_DIR/tests/acceptance/WebGuy.php generated sucessfully. 25 methods added
/YOUR_PROJECT_DIR/tests/functional/TestGuy.php generated sucessfully. 9 methods added
/YOUR_PROJECT_DIR/tests/unit/CodeGuy.php generated sucessfully. 25 methods added

Bootstrap is done. Check out /tests directory

# テストを作成
$ php codecept.phar generate:cept acceptance Welcome
Test was generated in WelcomeCept.php

生成したテストファイルを編集

1
2
3
4
$I = new WebGuy($scenario);
$I->wantTo('ensure that frontpage works');
$I->amOnPage('/');
$I->see('Home');

PhpBrowserのURLを自身のアプリのURLに変更

1
2
3
4
5
6
7
8
class_name: WebGuy
modules:
enabled:
- PhpBrowser
- WebHelper
config:
PhpBrowser:
url: 'http://localhost/'

テスト実行する。
MinkベースのPhpBrowserというモジュールがinputの入力、リンククリックなどのUIテスト、post、getなどのアクセステストをするらしい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ php codecept.phar run

Suite acceptance started
Trying to ensure that frontpage works (WelcomeCept.php) - Failed

Suite functional started

Suite unit started

Time: 0 seconds, Memory: 9.75Mb

There was 1 failure:

* * *

1) Couldn't ensure that frontpage works in WelcomeCept.php
Guy couldn't see "Home": 'Home' in It works!.
Failed asserting that response contains "home". Response was saved to 'log' directory.

Scenario Steps:
2\. I see "Home"
1\. I am on page "/"

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

という感じでした。phpunitでテストを書くよりもわかりやすいのかな?と感じました。

というわけで、ザザーっと最近のphpの開発環境周りを見てきました。
なんか、自動化されてて思っていたより便利になってる気がします。

参考記事

MacでApache、MySQL、PHPの環境を作る
モダンなPHP開発環境を構築する
phpenv+php-build+pyrusでの複数バージョンPHP管理など
PHPの外部ライブラリの管理にComposerを使う
codeception blog

Comments