PHP」カテゴリーアーカイブ

CentOS7にphpenv/php-buildを入れてPHPのバージョンを自在に切り替える

前提

以下の環境で動作確認

要素 バージョン
CentOS 7.3.1611
git 1.8.3.1
phpenv 1.1.1-2

概要

Dockerで構築したほぼ空っぽのCentOS7に対し、各種パッケージをインストール後、phpenv/php-buildをインストールし、PHPのバージョンを自在に切り替えたお話。PHPのバージョンを上げたり下げたりすることを容易に行うことが目的。

本記事ではほぼ空っぽのCentOS7を利用しているので、色々な基本となるパッケージの導入も行ってるが、多くの環境では既に入っているものが殆どなので必要に応じてインストールする形で問題ない。

phpenv/php-buildとは

phpenv: PHPの複数のバージョンを一元管理し、バージョンの切り替えを容易に行うためのツール
php-build: phpenvで使用するPHPのインストールツール

下準備

ツールはGithubで公開されてるのでgitが必要。ファイルの書き換えなどでvimを使う。パッケージのダウンロードにwgetを使う。

$ yum install -y git vim wget

CentOS7の標準リポジトリだけだと足りないので、EPELを追加する。

$ yum install epel-release

EPELリポジトリを有効にする(デフォルトで有効になってる?)

$ vim /etc/yum.repos.d/epel.repo
enabled=1

PHPに依存するパッケージ、コンパイルに必要パッケージなどなどを纏めてドン(元々入ってるものが多数、不要なものもあるかも)
PHPのバージョンによっては依存モジュールが異なる場合がある模様。その都度エラーメッセージが出るのでインストールすればよい。

$ yum install -y yum install gcc bison libxml2 libxml2-devel openssl-devel libcurl-devel libjpeg-turbo-devel libpng-devel libmcrypt-devel readline-devel libtidy-devel libxslt-devel bzip2 bzip2-devel libicu-devel  gcc-c++ tidyp make re2c file libtool-ltdl-devel autoconf automake patch mysql-devel

phpenvのインストール

Githubから本体を落とす。/usr/srcあたりに置くのが定石なのでそこでclone

$ cd /usr/src
$ git clone https://github.com/CHH/phpenv.git

本体の中にインストールスクリプトが含まれているのでそれを実行する

$ cd phpenv/bin/
$ ./phpenv-install.sh
Installing phpenv in /root/.phpenv
remote: Counting objects: 2620, done.
remote: Total 2620 (delta 0), reused 0 (delta 0), pack-reused 2620
Receiving objects: 100% (2620/2620), 491.71 KiB | 368.00 KiB/s, done.
Resolving deltas: 100% (1640/1640), done.
Success.

export PATH="/root/.phpenv/bin:$PATH"
eval "$(phpenv init -)"

Add above line at the end of your ~/.bashrc and restart your shell to use phpenv.

これでphpenvは使えるようになったが、コマンドですぐに利用できるようにパスを通す。
以下をbashrcなりに追記する

export PATH="/root/.phpenv/bin:$PATH"
eval "$(phpenv init -)"

bashrcを再読込

$ source ~/.bashrc

phpenvが読めることを確認

$ phpenv --version
rbenv 1.1.1-2-g615f844

php-buildのインストール

PHPをインストールするためのphp-buildを取得し、phpenvのプラグインディレクトリに配置する。こちらもGithubから取得できるので以下の手順でCone

$ git clone https://github.com/CHH/php-build.git ~/.phpenv/plugins/php-build

以下コマンドでインストール可能なPHPの一覧が出てくるので、これが出ればOK

$ phpenv install --list
(中略)
  7.1.0
  7.1.1
  7.1.2
  7.1.3
  7.1.4
  7.1.5
  7.1.6
  7.1.7
  7.1.8
  7.1snapshot
  7.2.0beta1
  7.2.0beta2
  7.2snapshot
  master

最新のPHPをインストールする

前項でインストール可能なPHPの一覧を確認した所、開発段階の7.2までインストール可能になっているが、今回は安定版の最新版である7.1.8をインストールする。

インストール時間が長い。その上インストールログがあんまり出ないので固まったとも思ってしまうが、気長に待てば終わるか、エラーメッセージがちゃんと出るので待機する。(本環境では11分程度)

$ phpenv install 7.1.8
[Info]: Loaded extension plugin
[Info]: Loaded apc Plugin.
[Info]: Loaded composer Plugin.
[Info]: Loaded github Plugin.
[Info]: Loaded uprofiler Plugin.
[Info]: Loaded xdebug Plugin.
[Info]: Loaded xhprof Plugin.
[Info]: Loaded zendopcache Plugin.
[Info]: php.ini-production gets used as php.ini
[Info]: Building 7.1.8 into /root/.phpenv/versions/7.1.8
[Downloading]: https://secure.php.net/distributions/php-7.1.8.tar.bz2
[Preparing]: /tmp/php-build/source/7.1.8
[Compiling]: /tmp/php-build/source/7.1.8
[xdebug]: Installing version 2.5.5
[xdebug]: Compiling xdebug in /tmp/php-build/source/xdebug-2.5.5
[xdebug]: Installing xdebug configuration in /root/.phpenv/versions/7.1.8/etc/conf.d/xdebug.ini
[xdebug]: Cleaning up.
[Info]: Enabling Opcache...
[Info]: Done
[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.7.1.8.20170815015550.log
[Success]: Built 7.1.8 successfully.

PHP7.1.8がインストールできたので、この環境で利用するデフォルトのPHPを7.1.8に設定する

$ phpenv global 7.1.8

PHP7.1.8が利用できる状態になったことが確認できる

$ php -v
PHP 7.1.8 (cli) (built: Aug 15 2017 02:06:59) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.1.8, Copyright (c) 1999-2017, by Zend Technologies
    with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans

古いPHPをインストールし、切り替える

開発内容によっては意図的に古いPHPを使用せざるを得ない場面もある。そんな場合にphpenvは効果的。ここではPHP5.2.17(デフォルトでインストールできる最も古いPHP)をインストールする。

$ phpenv install 5.2.17
[Info]: Loaded extension plugin
[Info]: Loaded apc Plugin.
[Info]: Loaded composer Plugin.
[Info]: Loaded github Plugin.
[Info]: Loaded uprofiler Plugin.
[Info]: Loaded xdebug Plugin.
[Info]: Loaded xhprof Plugin.
[Info]: Loaded zendopcache Plugin.
[Info]: php.ini-production gets used as php.ini
[Info]: Building 5.2.17 into /root/.phpenv/versions/5.2.17
[Downloading]: https://git.php.net/?p=web/php-distributions.git;a=blob;f=php-5.2.17.tar.bz2;h=90d654f7b9c60320f6228194ed1d2f12976a3a59;hb=bed93a30bbc2104f6e88e6ef142891a4c289502f
[Info]: Applying patches: /root/.phpenv/plugins/php-build/bin/../share/php-build/patches/gmp.c.patch /root/.phpenv/plugins/php-build/bin/../share/php-build/patches/xp_ssl.c.patch /root/.phpenv/plugins/php-build/bin/../share/php-build/patches/zip_direct.c.patch /root/.phpenv/plugins/php-build/bin/../share/php-build/patches/php-5.4.6-libxml2-2.9.patch
[Preparing]: /tmp/php-build/source/5.2.17
[Compiling]: /tmp/php-build/source/5.2.17
[xdebug]: Installing version 2.2.7
[xdebug]: Compiling xdebug in /tmp/php-build/source/xdebug-2.2.7
[xdebug]: Installing xdebug configuration in /root/.phpenv/versions/5.2.17/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.2.17.20170815021852.log
[Success]: Built 5.2.17 successfully.

versionsコマンドを叩くと、以下のようにインストール済みのPHP一覧と、デフォルトに設定されたバージョン(7.1.8)が確認できる

$ phpenv versions
  5.2.17
* 7.1.8 (set by /root/.phpenv/version)

globalコマンドでバージョンを切り替えると

$ phpenv global 5.2.17

デフォルトが変わり

$ phpenv versions
* 5.2.17 (set by /root/.phpenv/version)
  7.1.8

5.2.17が利用できる状態になる

$ php --version
PHP 5.2.17 (cli) (built: Aug 15 2017 02:23:16)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies
    with Xdebug v2.2.7, Copyright (c) 2002-2015, by Derick Rethans

備考

phpenv installで、以下のようなエラーが出て

-----------------
|  BUILD ERROR  |
-----------------

Here are the last 10 lines from the log:

何らかの対応を行った後は、中途半端にデータが残っている可能性のある下記ディレクトリを削除しておいたほうが無難な模様

$ rm /tmp/php-build -rf

所感

  • これまでrbenv(ruby),pyenv(python),nodenv(node)を使ってきたが、それ比べて導入に一番苦労した。依存が多すぎる。
  • 同様に一番インストールにも時間がかかる。コンパイルが長すぎる
  • いくつかのバージョンを一度入れてしまえば後は他の言語と同様なので容易
  • apacheとか関連モジュールは結局バージョンに依存してしまうからあんまり効果的でないのかも
  • 他言語含めて、anyenvというのを使えばまとめて出来たりするらしい。今度調べたい。

[Laravel] Exceptionをcatchできない

LaravelのController内で以下のように例外を補足するコードを書いても例外を補足できなかった

try {
  hoge();
} catch (Exception $e) {
  var_dump($e);
  exit;
}

散々ハマってPHPの例外処理の仕様まで追ったが、結果的に以下の修正で解決した。

try {
  hoge();
} catch (\Exception $e) {
  var_dump($e);
  exit;
}

namespace内のExceptionを待ち受けるか、全体のExceptionを待ち受け取るかの違い。

[Laravel] 対話的にプログラムを実行する

概要

laravelのtinkerを用いて対話的にプログラムを実行する。tinkerはRuby on Railsで言うところのrails consoleで、Laravelを用いた環境に対するプログラムの発行を行うツールである

起動

artisanのあるディレクトリに移動し、以下のコマンドで起動できる

$ php artisan tinker
Psy Shell v0.8.6 (PHP 5.6.30-12~ubuntu16.04.1+deb.sury.org+1 — cli) by Justin Hileman

PHPプログラムの実行

tinkerを起動すると、対話的にプログラムを実行することができる

>>> 5 + 2
=> 7
>>> 2 ** 8
=> 256

当然PHPの標準ライブラリを利用することも可能

>>> strlen('hogehoge');
=> 8
>>> array_map(function($n) { return $n * 10; } , [2,4,6,8,10]);
=> [
     20,
     40,
     60,
     80,
     100,
   ]

複数行に跨ぐことも可能。書きづらいので基本的にワンライナーであるべきだとは思う。

>>> function sayHello($name) {
...   return "Hello, $name";
... }
>>> sayHello('sasaki');
=> "Hello, sasaki"

LaravelModelの操作

Userモデルが存在する時、tinkerを用いてUserの作成と取得を行う。

作成

>>> $user = new App\User();
=> App\User {#703}
>>> $user->email = 'hogehoge@fugafuga.com';
=> "hogehoge@fugafuga.com"
>>> $user->password = md5('hogehoge');
=> "329435e5e66be809a656af105f42401e"
>>> $user->save();
=> true

取得

>>> $user = new App\User();
=> App\User {#703}
>>> $user->first();
=> App\User {#714
     id: 1,
     email: "hogehoge@fugafuga.com",
     name: "",
     created_at: "2017-07-11 11:37:49",
     updated_at: "2017-07-11 11:37:49",
     deleted_at: null,
   }

所感

  • DBの内容確認したいけどSQL書くのが面倒という時にも使えそう
  • 実装したロジックの動作確認の戦力になりそう
  • Laravel関係なくPHPの簡単な動作確認なんかにも使えそう

PHPでタイマー制御

【内容】
特定の期間内、処理を変更する。

【用途】
稼働中のサービスでメンテナンスを行う時や、
深夜等の業務時間外に処理を変更したい場合。

//規定期間開始の年月日・時間
$s_time_stamp = mktime(15,0,0,12,30,2016);
//規定期間終了の年月日・時間
$e_time_stamp = mktime(10,0,0,1,4,2017);
//現在時間の取得
$now_time = time();
//2016年12月30日 15時0分0秒~2017年1月4日 10時0分0秒の間、true側の処理を行う
if ($now_time >= $s_time_stamp && $now_time <= $e_time_stamp) {
  //規定期間内の処理

}else{
  //規定期間外の処理

}

ほぼ同じ内容で、トリガーとする日時以降か以前かで処理を分ける場合は下記の通り。

//規定時間を設定(下記の場合は、2017年2月20日 0時0分0秒以降の処理)
$trigger_time_stamp = mktime(0,0,0,2,20,2017);
//現在時間を設定
$now_time = time();
if ($now_time >= $trigger_time_stamp) {
  //規定時間後の処理

}else{
  //規定時間前の処理

}

WordPressでFormを用いてPOSTすると404になる問題

1時間ほど悩まされたので備忘録を残します。

基本的にプラグインを導入すれば目的を果たすことができるWordPressだが、やむを得ずFormを自前で用意してデータをPOSTしたい場合がある。

その際に、以下のようなよくあるFormを用いたところ、Submit後に404が返却される問題があった。




<form action="<?php the_permalink();?>" method="post">
  <input id="userid" type="text" name="userid" />
  <input id="name" type="text" name="name" />
  <input id="address" type="text" name="address"/>
  <button type="submit">お申込み</button>
</form>



原因を調べてみると、上記コードの以下の部分に問題があったようだ

<input id="name" type="text" name="name" />

どうやら、WordPressでは画面の遷移先の決定に$_POST[‘name’]を用いているらしく、自前のFormから送信されたnameと衝突してしまい、正しい画面遷移が行えなくなってしまったらしい。

そのため、今回の場合は以下のように修正することで正常にPOSTできることを確認した

<input id="name" type="text" name="username" />

参考