動作環境確認をコマンドラインで

動作環境確認用のcheck.phpはコマンドラインでも動くみたい

$ php web/check.php
********************************
*                              *
*  Symfony requirements check  *
*                              *
********************************

php.ini used by PHP: /etc/php5/cli/php.ini

** WARNING **
*  The PHP CLI can use a different php.ini file
*  than the one used with your web server.
*  If this is the case, please ALSO launch this
*  utility from your web server.
** WARNING **

** Mandatory requirements **

  OK        Checking that PHP version is at least 5.3.2 (5.3.2-1ubuntu4.5 installed)
  OK        Checking that the "date.timezone" setting is set
  OK        Checking that cache/ directory is writable
  OK        Checking that the logs/ directory is writable

** Optional checks **

  OK        Checking that the PHP-XML module is installed
  OK        Checking that the token_get_all() function is available
  OK        Checking that the mb_strlen() function is available
  OK        Checking that the iconv() function is available
  OK        Checking that the utf8_decode() is available
  OK        Checking that the posix_isatty() is available


[[WARNING]] Checking that that a PHP accelerator is installed: FAILED
            *** Install a PHP accelerator like APC (highly recommended) ***


[[WARNING]] Checking that php.ini has short_open_tag set to off: FAILED
            *** Set short_open_tag to off in php.ini ***
  OK        Checking that php.ini has magic_quotes_gpc set to off
  OK        Checking that php.ini has register_globals set to off
  OK        Checking that php.ini has session.auto_start set to off

** Optional checks (Propel/Doctrine) **

  OK        Checking that PDO is installed
  OK        Checking that PDO has some drivers installed: mysql, pgsql, sqlite, sqlite2


[[WARNING]] Checking that XSL module is installed: FAILED
            *** Install the XSL module (recommended for Propel) ***

あ、なんか警告でてる...

Symfony2事始め

こんどのPHP MatsuriではSymfony2で何か作ろうと思うので、その下調べ。

ちなみに環境はUbuntu.10.04 & PHP 5.3.2。

Quick Tourに沿ってすすめていく。
http://docs.symfony-reloaded.org/quick_tour/index.html

とりあえず作業ディレクトリを用意。

$ cd ~/public_html
$ mkdir symfony2
$ cd symfony2

sandboxをダウンロード、展開。

$ wget http://symfony-reloaded.org/downloads/sandbox_2_0_PR3.tgz
$ tar xvfz sandbox_2_0_PR3.tgz

「sandbox」というディレクトリができる。

動作環境チェック。
http://localhost/~okonomi/symfony2/sandbox/web/check.phpにアクセス。

php.iniのdate.timezoneの設定と、ログとキャッシュディレクトリのパーミッションでエラーが出たので対応。

$ sudo vi /etc/php5/apache2/php.ini

[Date]                                                                                                                                                                                          
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = Asia/Tokyo   ; <- 追記

$ sudo /etc/init.d/apache2 restart
$ chmod 777 hello/cache hello/logs

ぜんぶチェックが通ったので、いよいよhttp://localhost/~okonomi/symfony2/sandbox/web/index_dev.phpにアクセス。
「Congratulations!」ていうメッセージが表示されればひとまずOKらしい。

ひとまずここまで。現時点で分からないことは

  • ファイル構成
  • Bundleって?
  • 1.xのときにあったmoduleはどこへ?

といったところ。少しずつ理解していこう。

いままでPEARのコマンドにショートカットがあるのを知らなかった

PEARコマンドって

$ pear install ほげほげ

とか

$ pear list-upgrades

とか打ちますが、まあこれで別に疑問に思わなかったんですが、何気なくヘルプを見たら

$ pear help
Commands:
〜省略〜
Usage: pear [options] command [command-options] <parameters>
Type "pear help options" to list all options.
Type "pear help shortcuts" to list all command shortcuts.
Type "pear help <command>" to get the help for the specified command.

ん、「pear help shortcuts」!?

$ pear help shortcuts
Shortcuts:
     b        build
     bun      bundle
     c2       convert
     ca       channel-add
     cc       clear-cache
     cd       cvsdiff
     cde      channel-delete
     cg       config-get
     ch       config-help
     cha      channel-alias
     ci       channel-info
     cli      channel-login
     clo      channel-logout
     coc      config-create
     cs       config-set
     csh      config-show
     ct       cvstag
     cu       channel-update
     d        download
     da       download-all
     di       channel-discover
     fl       list-files
     i        install
     in       info
     l        list
     la       list-all
     lc       list-channels
     li       login
     lo       logout
     lu       list-upgrades
     p        package
     pd       package-dependencies
     pi       pickle
     pv       package-validate
     ri       remote-info
     rl       remote-list
     rpm      makerpm
     rs       run-scripts
     rt       run-tests
     si       sign
     sp       search
     st       shell-test
     sv       svntag
     ua       upgrade-all
     uc       update-channels
     un       uninstall
     up       upgrade

おおお

$ pear lu
Channel pear.ethna.jp: No upgrades available
Channel pear.php.net: No upgrades available

おおおお

というわけでもう「install」とか「upgrade-all」とかだらだらと入力する日々にはさよならして、これからはもっと有意義な人生を送ろうと思います。

DB接続設定を連想配列で

ひさしぶりにEthnaで小ネタ。

etc/sample-ini.php

<?php
$config => array(
//...snip...

    // @see http://pear.php.net/manual/ja/package.database.db.intro-connect.php
    'dsn' => array(
        'phptype'  => 'mysql',
        'username' => 'rw_user',
        'password' => 'password',
        'hostspec' => 'master',
        'database' => 'database',
    ),
    'dsn_r' => array(
        array(
            'phptype'  => 'mysql',
            'username' => 'ro_user',
            'password' => 'password',
            'hostspec' => 'slave1',
            'database' => 'database',
        ),
        array(
            'phptype'  => 'mysql',
            'username' => 'ro_user',
            'password' => 'password',
            'hostspec' => 'slave2',
            'database' => 'database',
        ),
    ),

//...snip...
);
?>


app/Sample_Controller.php

<?php

class Sample_Controller extends Ethna_Controller
{
//...snip...

    // @override
    function _prepareDSN()
    {
        $r = array();

        foreach ($this->db as $key => $value) {
            $config_key = "dsn";
            if ($key != "") {
                $config_key .= "_$key";
            }
            $dsn = $this->config->get($config_key);
            if (is_array($dsn) && is_int(key($dsn))) {
                // 種別1つにつき複数DSNが定義されている場合はアクセス分岐
                $dsn = $this->_selectDSN($key, $dsn);
            }
            $r[$key] = $dsn;
        }
        return $r;
    }

//...snip...
}
?>

Ethna_Controller::_prepareDSN()をオーバーライドして、DSNが配列だったときの判定を追加。(「is_int(key($dsn))」のところ)

Openpearをローカルで動かす(未完)

id:cocoitiさんのエントリを参考に、Openpearをローカルで動かしてみました。
openpear いれてみた - 個々一番のHTTP通信

作業環境はこんな感じです。

作業ディレクトリ
~/work/github/Openpear
web公開ディレクトリ
~/public_html/openpear

作業ディレクトリからweb公開ディレクトリにシンボリックリンクはって、http://localhost/~okonomi/openpear/みたいなURLでアクセスできるようにします。

あと、あらかじめMySQLでデータベースを作っておきます。今回はこんな感じで。

host
localhost
dbname
openpear
user
root
password
なし

それとrhacoはPDOでデータベースアクセスするので、これもインストールしておきます。

sudo aptitude install php5-mysql


さて、まずはclone。

cd ~/work/github
git clone git://github.com/nequal/Openpear.git
ln -s ~/work/github/Openepar ~/public_html/openpear

githubからソース落としてきて、シンボリックリンクはります。

次に初期設定。

cd Openpear
mkdir work
php setup.php

core path[/home/okonomi/work/github/Openpear/core/]: 
install application: 
application url [http://localhost/Openpear]: http://localhost/~okonomi/openpear
working directory [/home/okonomi/work/github/Openpear/work/]: 
application mode: dev

setup.phpをCLIで実行します。いろいろ聞かれます。

install application
?
application url
公開するURL?
working directory
ここにログとかが出力されるみたい
application mode
devにするとworking directoryにログが出力されたりする?


次は設定。
__settings__.phpに、__settings__.php.defaultを参考にDB接続設定を書いておきます。

<?php

// DB Settings
def("org.rhaco.storage.db.Dbc@org.openpear.flow.parts.Openpear",
    "type=org.rhaco.storage.db.module.DbcMysql,host=localhost,dbname=openpear,user=root,password=,encode=utf8");

最後に作業ディレクトリのパーミッションを調整します。
apacheの実行ユーザーが書き込めるようにしておくと、はじめてOpenpearにアクセスした時に必要なパッケージを自動的にインストールしてくれます。

chgrp -R www-data .
chmod -R g+w .

http://localhost/~okonomi/openpear/にアクセスしてページが表示されたら成功!

あと、

php setup.php -log on -level debug

ってしとくとwork/logにログが出力されました。


今のままだとほかのページを見ようとすると404になってしまうので、mod_rewriteの設定をします。

php setup.php -htaccess /~okonomi/openpear

.htaccessが生成されます。これで他のページも見られるはず。


これでとりあえずページを見ることはできるようになりました。
まだユーザー登録できない状態なので、次はここを解決しないとなー。
解決できたらまた書きます。

関西アンカンファレンスに参加しました

先週行われた関西アンカンファレンスで、Ethnaについて発表しました。資料はgithubにあげています。

okonomi/kansaiun-docs · GitHub

最近のバージョン(2.3.5〜2.5.0)でどういう機能が入ったかを簡単に解説してみました。

はじめにちょっとアンケートとってみたんですが、

1. Ethnaを知っている
4分の3以上
2. Ethnaを使ったことがある
半分くらい
3. Ethnaを今も使っている
1人

こんな結果になりました。

で、今も使っているという方はEthnaで作られたプロジェクトの保守をされているということでした(ちなみにバージョンは2.3.2)。
懇親会でもちらほら話がでましたが、ちょっとまえのプロジェクトではEthnaが多かったみたいです。このごろはCakePHPとかsymfonyが多いんですかねー?
あと、はじめて触ったフレームワークEthnaだっていうひとも結構いるような感触でした。


というようなことをいいつつ、実は2.5.0をはじめて触ったのが前日という突貫ぶりで結果はごらんのありさまというか、デモがうまく動かなかったり言いたいこと半分くらいしか言えなかったりでしたが、アンカンファレンスのゆるい空気に紛れて発表させていただきました。

スライドとか作ってる暇なかったので(そもそも作ったことない...)Emacsのorg-modeを使って発表したんですが、意外と好評?だったみたいで良かったです。


いろんなジャンルの人がいて(サーバのひと、デザイナーさん、組み込みやさんなど)普段聞けない/聞かない話が聞けてよかったです。
関西にもいろんな人がいるんだなと、あたりまえなことを改めて実感したりしました。
次回があればまた参加したいです!

Net_UserAgent_MobileにNet_UserAgent_Mobile_UserIDを組み込んでみた

Net_UserAgent_MobileのソースがGitHubで公開されています。

iteman/net-useragent-mobile · GitHub

これをforkして、Net_UserAgent_Mobile_UserIDを組み込んでみました。(Net_UserAgent_Mobile_UserIDについてはこちら→Net_UserAgent_Mobile_UserIDをリリースしました - okonomiの日記

okonomi/net-useragent-mobile · GitHub

やったこと

Net_UserAgent_Mobileには、getUID()というUID取得メソッドが用意されています。この中身をNet_UserAgent_Mobile_UserIDに丸投げするようにしました。

<?php

abstract class Net_UserAgent_Mobile_Common
{
    // 省略


    public function getUID()
    {
        if (is_null($this->_userid)) {
            require_once 'Net/UserAgent/Mobile/UserID.php';
            $this->_userid = Net_UserAgent_Mobile_UserID::factory($this);
        }

        return $this->_userid->getRawData();
    }


    // 省略
}

Net_UserAgent_Mobile_UserIDでキャリアごとの処理を吸収するので、Net_UserAgent_Mobile_Commonの各サブクラスでUID取得処理を個別に書かなくてもよくなりました。

いままでNet_UserAgent_MobileではNULLGWDOCOMOのアレとかが取得できなくて実務では使いたくても使えなかったんですが、Net_UserAgent_Mobile_UserIDはUID判別・取得を独自に追加できるのでそんな問題も解決できるかなーと思います。

<?php
/*
id=aa-12345みたいな形式を認識するようにする
*/

require_once 'Net/UserAgent/Mobile/UserID.php';
require_once 'Net/UserAgent/Mobile/UserID/Abstract.php';
require_once 'Net/UserAgent/Mobile.php';

class Hoge extends Net_UserAgent_Mobile_UserID_Abstract
{
    public function getID()
    {
        if (array_key_exists('id', $_REQUEST)) {
            return $_REQUEST['id'];
        } else {
            return null;
        }
    }

    public function validateID($id)
    {
        return preg_match('/^[a-z}{2}\-[0-9]{5}$/', $id);
    }

    protected function _parseID($id)
    {
        return array(
            substr($id, 0, 2),
            substr($id, 3),
        );
    }
}

// 独自処理を登録
Net_UserAgent_Mobile_UserID::setUserIDModules('DoCoMo', new Hoge());

$_SERVER['HTTP_USER_AGENT'] = 'DoCoMo/2.0 F05A(c100;TJ)';
$_REQUEST['id'] = 'ab-12345';
$ua =& Net_UserAgent_Mobile::singleton();
$uid = $ua->getUID(); // ab-12345