まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:php

IBM Bluemix で Context Path Route(以下、「コンテキストルーティング」)を行う方法が紹介されていました:
Context path routes for your Bluemix Cloud Foundry apps
https://www.ibm.com/blogs/bluemix/2017/01/context-path-routes-hour-bluemix-cloud-foundry-apps/



コンテキストルーティング」とは URL のパス部分を使ったルーティングの仕組みです。以下の例を使って紹介します。 "myapp.yourbluemix.net" というホストが稼働しており、ここでは色々な機能が稼働しています。例えばメインのポータル機能は http://myapp.yourbluemix.net/ で、ドキュメント管理機能は http://myapp.yourbluemix.net/docs/ 以下で、サーバー管理機能は http://myapp.yourbluemix.net/admin/ 以下で実装されている、といった具合です。ユーザーからは同じホスト名(myapp.yourbluemix.net)にアクセスしており、同一のサーバーを使っているように見えています:
2017020901


コンテキストルーティングを使うと、実際にはより強固&柔軟な構成で実現できます。例えば上記で紹介した3つの機能を全て別々のサーバー上に実装した上で、ユーザーにそれぞれのホストに(異なるホスト名へ)アクセスさせるのではなく、同じホスト名でのアクセスを可能にします。そして URL のパス部分でどのサーバーを使うかのルーティングを定義します。以下の例では /docs 以下にアクセスする場合は mydocs.yourbluemix.net へ、/admin 以下にアクセスする場合は myadmin.yourbluemix.net へ、それ以外は myapp.yourbluemix.net へ、といった具合です:
2017020902


これがコンテキストルーティングです。これを IBM Bluemix 環境のアプリケーションでも行う方法が上記ブログにて紹介されていました。ブログで紹介されていたのは Node.js ランタイムと Python ランタイムを使った方法でした。自分は Node.js と PHP で試してみたところ少し挙動が変わっていたようでした。それがランタイムの種類の違いに起因しているのかどうかは分からないのですが、、自分で動作確認した方法を以下に紹介します。なお実際に以下の手順を実行するには Bluemix アカウントと cf コマンドラインツールが必要になるので、事前に自分の環境にあった cf をダウンロードしてインストールしておいてください。

まずシステム構成、およびルーティングルールを以下のようなものとします:
2017020903

- 2台のランタイムおよびアプリケーションを用意する:
  - dotnsf-cr.mybluemix.net (Node.js)
  - dotnsf-cr-php.mybluemix.net (PHP)
- ユーザーがアクセスする URL は http://dotnsf-cr.mybluemix.net/ 以下のみ
- dotnsf-cr.myblutemix.net/phpapp/ 以下へのアクセスを dotnsf-cr-php.mybluemix.net/phpapp 以下の PHP アプリケーションにルーティングする。それ以外は dotnsf-cr.mybluemix.net の Node.js アプリケーションが処理する
- PHP アプリケーションが稼働する dotnsf-cr-php.mybluemix.net への直接アクセスはエラーとして処理する


Bluemix らしく、2つの異なるランタイムで仮想的な1つのシステムを作ってみることにしました。で、こんなソースコードを用意しました:
https://github.com/dotnsf/BluemixContextRoutingSample


上記サイトよりソースコードをダウンロード&展開するか git clone して入手してください。展開後に manifest.yml をテキストエディタで開き、以下の赤字部分を自分用のものに変更してください:
applications:
# Node.js app
- name: dotnsf-cr
  memory: 256M
  routes:
  - route: dotnsf-cr.mybluemix.net
  path: ./node_app/
# PHP app
- name: dotnsf-cr-php
  memory: 256M
  routes:
  - route: dotnsf-cr.mybluemix.net/phpapp
  path: ./php_app/

Node.js ランタイムには dotnsf-cr 、PHP ランタイムには dotnsf-cr-php という名前を付けており、最終的にはどちらも dotnsf-cr.myblutemix.net という名前でアクセスできるようにコンテキストルーティングを設定する、という内容です(つまりこの1つの manifest.yml で2つのランタイムの定義をしています)。上記の赤字部分を皆様のアプリケーション名に合わせて変えて使ってください。また US-SOUTH 以外のデータセンターを使う場合はドメインを(例えば eu-gb.mybluemix.net などに)適宜変更してください。


こうして作成したソースコードを cf ツールでプッシュします。manifest.yml 内に(2つのランタイムそれぞれを作るための)必要な情報が全て記述されているので1回の "cf push" だけで実行されます:
2017020901

↑まずは Node.js アプリケーションである dotnsf-cr のプッシュから始まります


2017020902

↑Node.js アプリケーションのビルドが行われている様子です


2017020903

↑ Node.js アプリケーションのプッシュが完了した様子です。そして間髪をいれずそのまま PHP アプリケーションである dotnsf-cr-php のプッシュが始まります。


2017020904

↑途中でルーティング処理が行われている様子が確認できます。


2017020905

↑PHP アプリケーションのプッシュも終わりました。dotnsf-cr-php という名前のアプリケーションですが、その URL が dotnsf-cr.myblutemix.net/phpapp に設定されていることがわかります。


この状態でダッシュボードを確認するとこのようになっているはずです。Node.js と PHP 2つのランタイムが追加されて実行中になっています。これらのルーティング先はどちらも同じものになっていることを確認してください。
2017020909


この状態で http://dotnsf-cr.mybluemix.net/ にアクセスすると Node.js 内の public/index.html が表示されます:
2017020906


また https://dotnsf-cr.mybluemix.net/about にアクセスすると、Node.js の app.js 内で定義された内容に従ったメッセージが表示されます:
2017020907


一方、http://dotnsf-cr.mybluemix.net/phpapp/ にアクセスすると、このパスの場合は PHP ランタイムにルーティングされ、PHP ランタイム内の index.php が表示されるはずです:
2017020908


というわけで、Bluemix でもコンテキストルーティングが実現できることが確認できました。他のランタイム環境でも、3種類以上であってもルーティングの設定だけで同様に実現できると思います。

前回、LAMP 環境を構築した IBM LinuxONE サーバーを使って、PHP のメジャーな MVC フレームワークの1つであるCakePHP の環境を整えてみます:
IBM LinuxONE コミュニティクラウド上で LAMP 環境を作る


まず CakePHP を動かす場合の PHP 設定を行います。/etc/php.ini を適宜変更するのですが、最低限やっておかないといけないのが、タイムゾーンの設定です。/etc/php.ini を編集して、以下の設定を加えます([Date] カテゴリ内でコメントアウトされている Date.timezone の設定からコメントを外し、"Asia/Tokyo" に設定して保存します:
$ sudo vi /etc/php.ini

  :
  :
[Date]
Date.timezone = "Asia/Tokyo"
  :
  :

また CakePHP では PHPUnit というモジュールを使うことになるので、これもインストールしておきます。前回の LAMP 環境構築時に pear もインストールしているので、pear を使って PHPUnit を導入します:
$ sudo pear install pear/PHPUnit

次に MySQL の設定を行います。まずは文字コードの設定を変更して、デフォルトで UTF-8 を使えるようにします:
$ sudo vi /etc/my.ini

[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8



今回は CakePHP 専用のデータベース(cakedb)を新たに作成し、その中に商品情報を格納するマスターテーブル(items)と、商品カテゴリを格納するマスターテーブル(categories)を定義することにします:
$ mysql -u root -p

mysql> create database cakedb default character set utf8;
mysql> use cakedb
mysql> create table items( id int primary key auto_increment, name varchar(50), category_id int, created datetime default null, modified datetime default null );
mysql> create table categories( id int primary key auto_increment, name varchar(50), created datetime default null, modified datetime default null );
mysql> quit

1つのデータベースと、2つのテーブルを作りました。必要に応じてこれらにアクセスできるユーザーなどを追加しましょう。

これら2つのマスターテーブルを操作できるような環境を CakePHP で作ることにしましょう。ここは必須ではありませんが、データベースを操作する上では phpMyAdmin があると便利です。IBM LinuxONE コミュニティクラウドのサーバーに phpMyAdmin 環境を導入する場合の手順はこちらの記事を参考にしてください:
IBM LinuxONE コミュニティクラウド上に phpMyAdmin を導入する


ではいよいよメインディッシュの CakePHP 環境を構築します。PHP 5.3 でも動くよう、CakePHP のバージョンは 2.x を使うことにします。またこれも Apache HTTPD のドキュメントルートがデフォルトのままの /var/www/html であるとして作業を紹介します:
$ https://github.com/cakephp/cakephp/archive/2.9.4.zip
$ sudo /bin/bash
# cd /var/www/html
# unzip ~linux1/2.9.4.zip
# mv cakephp-2.9.4 cakephp
# chmod 777 -R cakephp/app/tmp
# chmod 755 cakephp/lib/Cake/Console/cake
# cd cakephp/app/Config
# vi core.php

  :
  :
/**
 * A random string used in security hashing methods.
 */
        Configure::write('Security.salt', 'ABCDabcd1234');

/**
 * A random numeric string (digits only) used to encrypt/decrypt strings.
 */
        Configure::write('Security.cipherSeed', '1234567890');
  :
  :

最後の cakephp/app/Config/core.php の編集作業では 'Security.salt' の値と、'Security.cipherSeed' の値はデフォルトの(既知の)値のままだと危ないのでランダムな値に書き換えました。

続けて(カレントディレクトリが cake/app/Config/ の状態で)、更にデータベースの設定ファイルを用意して、自分の環境に合わせた設定を行います:
# cp database.php.default database.php
# vi database.php

  :
  :
class DATABASE_CONFIG {

        public $default = array(
                'datasource' => 'Database/Mysql',
                'persistent' => false,
                'host' => 'localhost',
                'login' => 'root',
                'password' => 'P@ssw0rd',
                'database' => 'cakedb',
                'prefix' => '',
                //'encoding' => 'utf8',
        );
  :
  :

↑具体的にはユーザー名(login)、パスワード(password)、データベース(database)の値を書き換えます。


CakePHP 自体はここまでの設定で動くはずです。必要に応じて DebugKit などの便利なプラグインを cakephp/app/Plugin/ 以下に追加で導入してください。DebugKit の導入に関してはこちらを参照ください:
https://github.com/cakephp/debug_kit/tree/2.2


ブラウザで http://(IPアドレス)/cakephp/ にアクセスすると、CakePHP のホーム画面が表示されます。緑と黄色のバーが並んでいる状態であれば、少なくとも設定は間違っていないことになります。下図では DebugKit まで導入して、全て緑になっている状態です:
2017010603

 

IBM LinuxONE コミュニティクラウド上に LAMP 環境のサーバーを作り、そのデータベースを管理するための phpMyAdmin を導入します。LAMP 環境を作るまでの手順は以下を参照してください:


LAMP 環境が出来てしまえば phpMyAdmin は普通に導入できるのでは・・・ と考える人がいるかもしれません。ほぼ正解ですが一点だけ注意点があります。

2017/Jan/06 時点では、IBM LinuxONE コミュニティクラウドの RHEL 6.x で提供されている PHP のバージョンは 5.3.3 です。一方で phpMyAdmin の最新バージョンは 4.6.5.2 ですが、こちらは PHP 5.5 以上を動作環境としています。つまり現時点の LinuxONE 環境では phpMyAdmin 最新バージョンの動作条件を満たすことができないのでした。

というわけで、PHP 5.3.3 でも動作できるバージョンの phpMyAdmin 4.0.x を用意する必要があります。この一点だけが注意点なのでした。


では改めて、こちらの手順を参考に IBM LinuxONE コミュニティクラウド上に作った仮想サーバーに SSH でログインします:
2017010403


では phpMyAdmin 4.0.x(2017/Jan/06 時点の最新版は 4.0.10.18)を導入します。Apache HTTP サーバーのドキュメントルートはデフォルトの /var/www/html であると仮定して、以下を実行します:
$ wget https://files.phpmyadmin.net/phpMyAdmin/4.0.10.18/phpMyAdmin-4.0.10.18-all-languages.zip
$ sudo /bin/bash
# cd /var/www/html
# unzip ~linux1/phpMyAdmin-4.0.10.18-all-languages.zip
# mv phpMyAdmin-4.0.10.18-all-languages phpMyAdmin
# exit

これで http://(IPアドレス)/phpMyAdmin/ にアクセスすれば phpMyAdmin にアクセスできます。必要に応じて認証をつけた上で運用してください:
2017010602



この記事の続きです:


IBM LinuxONE コミュニティクラウド上に作った仮想サーバーにいわゆる "LAMP"(=Linux + Apache HTTPD + MySQL + PHP) 環境を構築してみます。まずは上記記事を参考に仮想サーバーを作り、SSH でリモートログインします:
2017010403


ミドルウェアの導入作業を伴うため、ルート権限を持ったユーザーにスイッチしておきます:
$ sudo /bin/bash
#


LAMP 環境に必要なミドルウェアや言語環境をまとめて導入します(赤字はコメント):
# yum install httpd -y (Apache HTTP サーバー)
# yum install mysql-server mysql -y (MySQL)
# yum install php php-mbstring php-mysql php-gd php-pear php-xml php-devel -y (PHP)

また以下は LAMP 環境構築においては必須ではありませんが、使うことも多いというか、あると便利だと思うので必要に応じて導入しておいてください:
# yum install screen -y (screen)
# yum install git -y (git)
# yum install java-1.8.0-ibm-devel -y (JDK 1.8)

ミドルウェアを起動する前にファイアウォールの設定を行います。デフォルトの LinuxONE では iptables によるファイアウォールが有効になっており、このままでは http(s) によるアクセスができません。今回の環境では iptables を無効にしておきましょう:
# /etc/init.d/iptables stop
# chkconfig iptables off

あらためて各ミドルウェアを起動し、また自動起動設定をしておきます:
# /etc/init.d/httpd start
# /etc/init.d/httpd mysqld
# chkconfig httpd on
# chkconfig mysqld on
# exit
$

この時点で Apache HTTP サーバーが動いています。iptables の解除が成功していれば http://(IPアドレス)/ にアクセスすることができるようになっているはずです:
2017010601


さて、MySQL に関しては root のパスワードを設定しておきましょう。この例では P@ssw0rd というパスワードにしていますが、ここは必要に応じて変えてください:
$ mysql -u root

mysql> set password for root@localhost=PASSWORD('P@ssw0rd');
mysql> exit

これで LinuxONE 上でも LAMP の環境が作れました! ちなみに PHP のバージョンは 5.3.3 が導入できます:
$ php -v
PHP 5.3.3 (cli) (built: Dec 15 2015 04:50:47)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

2017 年もよろしくお願いします。 m(__)m

さて、2017年1月1日は日曜日でした。ということは2017年1月はいきなり「13日の金曜日」を迎えることになります。

13日の金曜日は「不吉の象徴」のように言われていますが、ではこの「13日の金曜日」はどのくらい珍しいのでしょうか? 2017年の(コードの)書き初めの意味でプログラミングで調べてみることにしました。

調べる内容は「13日は何曜日になることが多いのか?」を調べて、その中で金曜日が平均とくらべてどの程度珍しいのか/珍しくないのかを調べてみることにします。

この計算をするには、うるう年を意識する必要があります。くわしくはウィキペディアあたりを調べていただきたいのですが、うるう年は400年周期で計算する必要があります。簡単に説明すると、こんなルールです:
 (1) 4 年に一度(西暦で 4 で割り切れる年)がうるう年である
 (2) ただし 100 でも割り切れる年は例外としてうるう年ではない
 (3) ただし 400 でも割り切れる年は例外の例外としてうるう年である

というわけで、今回は西暦 2000 年 1 月から、西暦 2399 年 12 月まで、一ヶ月毎に各 13 日が何曜日になっているのかを調べることにします。そして各曜日ごとに何回ずつ発生していたのかを最終的に出力します。こういうことはプログラミングが手っ取り早いですよね。今回は PHP を使うことにしました。以下の内容を f13.php という名前で保存します:
<?php

//. タイムゾーンを設定
date_default_timezone_set('Asia/Tokyo');

//. 配列を初期化
$w = array(7);
for( $i = 0; $i < 7; $i ++ ){
  $w[$i] = 0;
}

//. 2000年1月から2399年12月までの13日が何曜日か調べる
for( $y = 2000; $y < 2400; $y ++ ){
  for( $m = 1; $m <= 12; $m ++ ){
    $t = mktime( 0, 0, 0, $m, 13, $y );
    $n = date( 'w', $t );
    $w[$n] ++;
  }
}

//. 結果を出力
for( $i = 0; $i < 7; $i ++ ){
  echo( "w[$i] = $w[$i]\n" );
}
?>

最後に結果を出力しますが、配列の 0 番目が日曜日、 1 番目が月曜日、2 番目が火曜日、・・・という出力結果になります。つまり金曜日は 5 番目です。

また 400 年間(400 x 12 = 4800 ヶ月間)で7つの結果に振り分けられるので、仮に平坦化されているとすると、4800 / 7 = 685.71... なので、各曜日ごとに 685 回から 686 回現れることになります。

さて、実行結果はというと・・・
# php -f f13.php
w[0] = 687
w[1] = 685
w[2] = 685
w[3] = 687
w[4] = 684
w[5] = 688
w[6] = 684

400 年間の中で 688 回の 13 日の金曜日が見つかったことになります。金曜日は平均以上どころか最頻出曜日だったことがわかりました。


というわけで、「『13 日の金曜日』は滅多にない不吉な日」ではなく、「13 日といえば金曜日」といえるほど、最も頻出のパターンだったことになります。


このページのトップヘ