Strings of Life

PHP/Phalcon/MySQL/JavaScript/RegExp/Ruby/Perl/ActionScript

2014年03月

OhLifeというWebサービスがある。メールの送受信をフックとしたログ記録サービスで、以下のような特徴がある。

  • 1日1回、決まった時間にメールを送ってくる
  • このメールに返信すると、返信内容が記録される
  • OhLifeが送ってくるメールの本文には、過去のログが含まれる

OhLifeの主な機能には満足しているのだけど、一点だけ不満がある。それは、過去のログの選ばれる規則を設定できないこと。個人的な用途としては、前日からの進捗確認に使いたいので、必ず昨日のログを表示してほしい。しかし、OhLifeの過去ログ抽出規則は、「前日・1週間前・1ヶ月前」等があり、古いものが優先されているように思える。

類似サービスも探したのだが、どうも無いみたい。

無いなら作ろう。

ということで、作ってみた(現在、一般公開はしていない)。


サーバはさくらVPSで、OSはDebian Wheezy。メールサーバとしてはPostfixを使用。今回一番ハマったのはPostfixの設定だったり。

Postfixで受け取ったメールをPHPスクリプトに渡す方法としては、 この記事が参考になる。

また、メールをパースする方法としては、ライブラリを使用することにした。最初は illuminate/mailなども検討したのだけど、サンプルコードが探しやすかったので PEAR::Mail_MimeDecodeにした(サンプルコードは この記事を参考にした)。

インストールはComposerで。

{
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear.php.net/"
        }
    ],
    "require": {
        "pear-pear.php.net/Mail_mimeDecode" : "*"
    }
}

メールを受信するプログラムはこんな感じ(受け取ったメールの本文をDBに保存する)。

<?php

require_once __DIR__ . '/vendor/autoload.php';

$raw_mail = file_get_contents('php://stdin'); // メール本文を標準入力から受け取る

$params = [];
$params['include_bodies'] = true;
$params['decode_bodies']  = true;
$params['decode_headers'] = true;
$params['input'] = $raw_mail;
$params['crlf'] = '\r\n';

$mail_data    = Mail_mimeDecode::decode($params);
$mail_address = $mail_data->headers['from'];
$mail_address = trim(substr($mail_address, strpos($mail_address, '<')), '<>');
$charset      = $mail_data->ctype_parameters['charset'];
$mail_body    = mb_convert_encoding($mail_data->body, 'UTF-8', $charset);

try {
    $dbh = require_once __DIR__ . '/db_connection.php'; // PDOオブジェクトを取得

    // メールアドレスからユーザーを取得
    $sql = 'SELECT * FROM users WHERE mail = :mail';
    $stmt = $dbh->prepare($sql);
    $result = $stmt->execute([':mail' => $mail_address]);

    // DBにメール本文を保存
    if (true === $result) {
        $row = $stmt->fetchAll(PDO::FETCH_ASSOC)[0];
        $sql = 'INSERT INTO logs (users_id, body, created_at) VALUES (:users_id, :body, :created_at)';
        $stmt = $dbh->prepare($sql);
        $stmt->bindParam('users_id', $row['id']);
        $stmt->bindParam('body', $mail_body);
        $stmt->bindParam('created_at', date('Y-m-d H:i:s'));
        $stmt->execute();
    }
} catch (Exception $e) {
    error_log($e->getMessage() . PHP_EOL, 3, __DIR__ . '/log/receiver.log');
    exit(1);
}

メール送信機能はmb_send_mail()使えば簡単。あとは、cronにメール送信スクリプトを登録して、定期実行すればOK。

実践 Vagrant
Mitchell Hashimoto
オライリージャパン
2014-02-21





『実践 Vagrant』は、Vagrantの作者であるMitchell Hashimoto氏が自ら著した、Vagrantの解説書。

Vagrantとは何かというと、VirtualBoxを便利に使うためのコマンドラインツール――というのが最初の頃のVagrantだったと思うのだけど、今ではVirtualBoxだけでなくVMWareなどもいけるし、さらにはAmazon EC2のインスタンスをVagrantで操作することもできる。

要は、仮想マシンの設定と操作を便利に行えるツール、と考えると良いと思う。

仮想マシンを簡単に作っては破棄してが出来るようになって、何がうれしいのかというと、環境構築のコストが非常に小さくなること。VMの設定ファイルであるVagrantfileと、VMのセットアップを行うプロビジョニングツールのスクリプトさえ共有すれば、チームで全く同じ環境のVMを簡単に共有できるし、本番環境と同様に動作する開発環境を構築することもできる。

また、チームで開発する場合だけでなく、学習用の環境としても使いやすい。プレーンな状態のOSをさくっと立ち上げて、必要最低限のツールだけをインストールして学習用に使用し、仕事が終わったら破棄しておしまい、みたいなことが簡単にできる。

私の場合、最近は、学習用にはVagrantで作ったVMを使うことがほとんど。学習用の環境はしばらく使ったら捨てるのが前提なのだから、ローカルのOSに入れて環境を汚すより、使い捨ての環境を構築してしまったほうが良い。

共有フォルダやネットワーク関係の設定も、VirtualBoxのGUIで行うより、Vagrantfileで行ったほうがわかりやすい。


本書『実践Vagrant』には、私がVagrant関係で知りたいと思っていたことはほとんど載っていた(設定ファイル、プロビジョニング、ネットワーク、ボックスの作り方、プラグイン等)。ただ、一点、「ボックスはどこで入手すべきか」という情報だけは、得ることができなかった。

この疑問に関しては、最近リリースされたVagrant Cloudが一つの答えなのだろう。


『実践Vagrant』は『Vagrant: Up and Running』の翻訳書だが、原著の刊行から訳書の刊行までに古くなってしまった部分は、訳者が適切に補っている。それだけでなく、原著にはない解説も追加されており、今Vagrantの解説書を買うなら、これしかない、という決定版といえる。Vagrantのバージョンアップの早さを考えると、賞味期限は短い(1年程度?)と思われるため、早めに読むのが吉。






本書の想定読者は以下のような人です。
  • Webアプリ開発を業務として初めて手がけようとするエンジニアの方
  • Webアプリ開発の全体像を知りたい方
  • Web開発の全体的な知識を初学者に学ばせたい方
  • スタートアップ系企業の方からWeb系企業の新人エンジニアの方まで
こういった初心者の人はもちろんですが、「実業務の経験はあるけど、現場がいまいちモダンじゃない…」というPHPerの人にもピッタリな内容だと思います。


第1章「Web技術オーバービュー」は、初心者でなければ読み飛ばしても良いと思います。逆に初心者は、分からないことがあっても気にせず進みましょう。


第2章「Webアプリケーション実践入門」は、本書のハイライト。

PHP編は「初心者向けだから名前空間は使わないように」といった妥協がなく、モダンなスタイルを貫いている点には好感が持てます(遅延静的束縛やトレイトといった機能をさらっと使ってるのもポイントが高い)。

ただ、対象読者がイマイチわからないですね。PHPのオブジェクト指向構文と名前空間を理解していないとついていけない内容なので、PHP初心者向けとは言いがたい。『パーフェクトPHP』のPart2くらいまでは読んでいないと、「動かす」ことはできても、「なぜそう書くのか理解する」ことはできないでしょう。

初心者よりはむしろ、実務でPHP5.3以前のフレームワーク(CakePHP2/CodeIgniter/symfony等)やSmarty+生PHPなどと格闘している人が、PHP5.5時代のモダンな開発スタイルにキャッチアップするのに向いている、という印象です。

PHP編について、誤記と思われる箇所をリストしておきます(書籍内容に関するお問い合わせでも報告済み)。

p.34 12行目
× # apt-get php5-cli
○ # apt-get install php5-cli

p.40
×リスト4 showメソッド(lib/Base/Controller/TimeLine.php)
○リスト4 showメソッド(lib/Controller/TimeLine.php)

p. 47
×リスト22では、クラス定義の前にuse演算子を用いて〜
○リスト6では、クラス定義の前にuse演算子を用いて〜


ついでに、TinitterをMySQLで動かしたい人向けの設定(Ubuntu12.04/MySQL5.5を想定):

sudo apt-get install mysql-server でインストール。

/etc/mysql/my.cnf を編集して以下の設定を追加。
# [client]の下
default-character-set = utf8

# [mysqld]の下
character-set-server = utf8

設定できたら sudo /etc/init.d/mysql restart でMySQL再起動。

あとは適当にテーブルを作って、サンプルコードに含まれるスキーマファイルを読み込み

mysql -u root -p -e 'CREATE DATABASE tinitter;'
mysql -u root -p tinitter < schema.mysql.sql

config.phpの$db_settingsは以下のような感じで。
$db_settings = [
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'tinitter',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci'
];

PHP編を最後までやった感想としては、レイアウトが酷い。これにつきます。ある部分で説明しているコードの実体が次のページにある、といった現象が頻繁に発生しており、読みづらいことこの上ない。Ruby編はまともなレイアウトです。何故PHP編はこんなに混乱したレイアウトなんでしょう。。。

PHP編までで、結構長くなってしまったので、Ruby編とインフラ編の感想はまた今度。

以前書いた記事のフォローです。

上の記事を書いた時点(2013年12月29日)では、ドットインストールの課金方式は「登録日又は月初め〜月終わりまで」で、月末に登録すると損だったのですが、現在は「プレミアム会員への登録日より、翌月の登録日同日の前日」となっています。これにより、「月末に登録すると損」という状況は解消されています。



Cプログラムが実行可能な形式になるまでの流れ(ビルドの流れ)
  1. Cソースコードを作成する
  2. プリプロセス(プリプロセッサがソースコードを書き換える)
  3. コンパイル(Cのソースコードからアセンブラのコードを作る)
  4. アセンブル(アセンブラのコードからマシン語のコードを作る)
  5. リンク(作成したコードとライブラリのコードを結びつける)

プリプロセッサの働き

  • 特定の箇所に特定のファイルを挿入する(#include)
  • 特定の文字列を特定の文字列で置換する(#define)
  • 条件に合わせて、特定の行を削除又は挿入する(#ifdef #else #end)


クロスコンパイルとは:開発マシンとターゲットマシンが異なる場合をいう(Windowsで開発して、家電で動かす、等)

このページのトップヘ