Ethna 2.3.7とEthna 2.5.0preview5を共存させるとethnaコマンドがバグる
先日のEthna_Plugin_Debugtoolbarのインストールで、すでにインストールしてるEthna 2.3.7はそのままにしてEthna 2.5.0preview5をインストールしたらethnaコマンドがちゃんと動かなった。
再現手順
再現手順は以下のとおり。
以降長いので略記。
2.3.7な環境で、
$ ethna -v Ethna 2.3.7
プロジェクトを作成して、
$ ethna add-project sample
そのプロジェクトに2.5.0p5をインストール。
$ cd sample $ ethna pear-local channel-discover pear.ethna.jp $ ethna pear-local install -a http://pear.ethna.jp/pear/Ethna-2.5.2009062201.tgz $ bin/ethna -v Ethna 2.5.0-preview5 (using PHP 5.2.6-3ubuntu4.1)
インストールした2.5.0p5のethnaコマンドを引数なしで実行すると、
$ bin/ethna Fatal error: Cannot redeclare class Ethna_Plugin_Handle_AddAction in /usr/share/php/Ethna/class/Plugin/Handle/Ethna_Plugin_Handle_AddAction.php on line 143 Call Stack: 0.0037 89304 1. {main}() /home/okonomi/public_html/blog/sample/lib/Ethna/bin/ethna_handle.php:0 0.1453 3294016 2. Ethna_Plugin_Handle_Help->perform() /home/okonomi/public_html/blog/sample/lib/Ethna/bin/ethna_handle.php:66 0.1457 3294864 3. Ethna_Handle->getHandlerList() /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle/Help.php:38 0.1457 3294864 4. Ethna_Plugin->getPluginList() /home/okonomi/public_html/blog/sample/lib/Ethna/class/Ethna_Handle.php:80 0.2917 6312800 5. Ethna_Plugin->getPlugin() /home/okonomi/public_html/blog/sample/lib/Ethna/class/Ethna_Plugin.php:115 0.2917 6312800 6. Ethna_Plugin->_getPlugin() /home/okonomi/public_html/blog/sample/lib/Ethna/class/Ethna_Plugin.php:93 0.2917 6312800 7. Ethna_Plugin->_loadPlugin() /home/okonomi/public_html/blog/sample/lib/Ethna/class/Ethna_Plugin.php:145 0.2918 6312800 8. Ethna_Plugin->_includePluginSrc() /home/okonomi/public_html/blog/sample/lib/Ethna/class/Ethna_Plugin.php:176
ずぎゃーん。
原因を探る
どうやらプラグインをリストアップするときに何か失敗してるみたい。ソースを追いかけてみる。
Ethna_PluginクラスのgetPluginList()では、$src_registryの内容を元にgetPlugin()を呼んでプラグインをロードしてる。
試しに$src_registryの値をprint_rしてみると、
<?php Array ( [Handle] => Array ( [Help] => Array ( [0] => Ethna_Plugin_Handle_Help [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => Help.php ) [AddAction] => Array ( [0] => Ethna_Plugin_Handle_AddAction [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddAction.php ) [AddActionTest] => Array ( [0] => Ethna_Plugin_Handle_AddActionTest [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddActionTest.php ) [AddAppManager] => Array ( [0] => Ethna_Plugin_Handle_AddAppManager [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddAppManager.php ) [AddAppObject] => Array ( [0] => Ethna_Plugin_Handle_AddAppObject [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddAppObject.php ) [AddEntryPoint] => Array ( [0] => Ethna_Plugin_Handle_AddEntryPoint [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddEntryPoint.php ) [AddProject] => Array ( [0] => Ethna_Plugin_Handle_AddProject [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddProject.php ) [AddTemplate] => Array ( [0] => Ethna_Plugin_Handle_AddTemplate [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddTemplate.php ) [AddTest] => Array ( [0] => Ethna_Plugin_Handle_AddTest [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddTest.php ) [AddView] => Array ( [0] => Ethna_Plugin_Handle_AddView [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddView.php ) [AddViewTest] => Array ( [0] => Ethna_Plugin_Handle_AddViewTest [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => AddViewTest.php ) [ClearCache] => Array ( [0] => Ethna_Plugin_Handle_ClearCache [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => ClearCache.php ) [CreatePlugin] => Array ( [0] => Ethna_Plugin_Handle_CreatePlugin [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => CreatePlugin.php ) [I18n] => Array ( [0] => Ethna_Plugin_Handle_I18n [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => I18n.php ) [MakePluginPackage] => Array ( [0] => Ethna_Plugin_Handle_MakePluginPackage [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => MakePluginPackage.php ) [PearLocal] => Array ( [0] => Ethna_Plugin_Handle_PearLocal [1] => /home/okonomi/public_html/blog/sample/lib/Ethna/class/Plugin/Handle [2] => PearLocal.php ) [Ethna_Plugin_Handle_AddAction] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddAction [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddAction.php ) [Ethna_Plugin_Handle_AddActionTest] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddActionTest [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddActionTest.php ) [Ethna_Plugin_Handle_AddAppManager] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddAppManager [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddAppManager.php ) [Ethna_Plugin_Handle_AddAppObject] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddAppObject [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddAppObject.php ) [Ethna_Plugin_Handle_AddEntryPoint] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddEntryPoint [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddEntryPoint.php ) [Ethna_Plugin_Handle_AddProject] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddProject [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddProject.php ) [Ethna_Plugin_Handle_AddTemplate] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddTemplate [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddTemplate.php ) [Ethna_Plugin_Handle_AddTest] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddTest [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddTest.php ) [Ethna_Plugin_Handle_AddView] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddView [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddView.php ) [Ethna_Plugin_Handle_AddViewTest] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_AddViewTest [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_AddViewTest.php ) [Ethna_Plugin_Handle_ChannelUpdate] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_ChannelUpdate [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_ChannelUpdate.php ) [Ethna_Plugin_Handle_ClearCache] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_ClearCache [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_ClearCache.php ) [Ethna_Plugin_Handle_InfoPlugin] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_InfoPlugin [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_InfoPlugin.php ) [Ethna_Plugin_Handle_InstallPlugin] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_InstallPlugin [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_InstallPlugin.php ) [Ethna_Plugin_Handle_ListPlugin] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_ListPlugin [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_ListPlugin.php ) [Ethna_Plugin_Handle_MakePluginPackage] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_MakePluginPackage [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_MakePluginPackage.php ) [Ethna_Plugin_Handle_PearLocal] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_PearLocal [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_PearLocal.php ) [Ethna_Plugin_Handle_UninstallPlugin] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_UninstallPlugin [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_UninstallPlugin.php ) [Ethna_Plugin_Handle_UpgradePlugin] => Array ( [0] => Ethna_Plugin_Handle_Ethna_Plugin_Handle_UpgradePlugin [1] => /usr/share/php/Ethna/class/Plugin/Handle [2] => Ethna_Plugin_Handle_UpgradePlugin.php ) ) )
なんかクラス名とか重複してる?
$src_registryを組み立ててるのはsearchAllPluginSrc()から呼ばれてる_searchPluginSrc()で、引数の$typeと$nameが$src_registryの配列のキーになってる。で、$nameはプラグインのファイル名からつくられてる。
そういえばプラグインのファイル名の命名規則が変更されたんだった。そのあたりに原因が?
命名規則の変更を吸収するようなコードを1行追加してみた。
<?php /** * 指定された $type のプラグイン (のソース) をすべて検索する * * @access public * @param string $type プラグインの種類 */ function searchAllPluginSrc($type) { // 後で見付かったもので上書きするので $this->appid_list の逆順とする $name_list = array(); $ext = $this->ctl->getExt('php'); foreach($this->_dirlist as $dir) { $files = glob($dir . DIRECTORY_SEPARATOR . $type . DIRECTORY_SEPARATOR . "/*." . $ext); if (!$files) { $this->logger->log(LOG_DEBUG, 'cannot open plugin directory: [%s/%s]', $dir, $type); continue; } $this->logger->log(LOG_DEBUG, 'plugin directory opened: [%s]', $dir); foreach ($files as $plugin_file) { $plugin_name = substr(basename($plugin_file), 0, - strlen($ext) - 1); + $plugin_name = preg_replace("/^[A-Z]+_Plugin_{$type}_(.+)/i", '$1', $plugin_name); $name_list[$plugin_name] = 0; } } foreach (array_keys($name_list) as $name) { // 冗長だがもう一度探しなおす $this->_searchPluginSrc($type, $name); } } // }}}
で、実行。
$ bin/ethna usage: ethna [option] [command] [args...] available options are as follows: -v, --version show version and exit available commands are as follows: add-action add-action-test add-app-manager add-app-object add-entry-point add-project add-template add-test add-view add-view-test clear-cache create-plugin help i18n make-plugin-package pear-local
おお、うまくいった!
さて
今回の対応が正しいのかよく分からないですが、起こった問題と対応方法を書いてみました。
こういうのってチケット投げた方がいいのかなー…?
Ethna 2.5.0 preview5とEthna_Plugin_Debugtoolbar 0.9.0を試してみたの続き
昨日の日記の続き。
Ethna_Plugin_Debugtoolbar 0.9.1がリリースされたので、id:sotarokさんの仕事のはやさにビビりつつ早速アップデートしてみました。
Ethna_Plugin_Debugtoolbar 0.9.1 をリリース - 肉とご飯と甘いもの @ sotarok
まずはパッケージを更新。
$ bin/ethna pear-local upgrade openpear/Ethna_Plugin_Debugtoolbar
ひとまずここでプロジェクトのページにアクセスしてみる。うん、問題なく動く。
次にビュークラスを修正。$hasDefaultHeaderの定義が要らなくなったので削除。
最後はテンプレート。smarty_debug.tplがパッケージに同梱されたので、手動で配置したものと入れ替え。
$ cd template $ rm smarty_debug.tpl $ ln -s ../lib/.pear/data/Ethna_Plugin_Debugtoolbar/data/lib/smarty_debug.tpl ./
これでアップデート完了!
Ethna 2.5.0 preview5とEthna_Plugin_Debugtoolbar 0.9.0を試してみた
ちょっとまえにEthna_Plugin_Debugtoolbarがリリースされたということで、いい機会なのでEthna 2.5.0 preview5といっしょに試してみた。
Ethna 2.5.0 preview5をインストールするにあたって、すでにインストールしてるEthna 2.3.7を上書きしたくないので、次のような手順でやってみた。
- Ethna 2.3.7でダミープロジェクトを作成
- ダミープロジェクトにEthna 2.5.0 preview5をインストール
- ダミープロジェクト内のEthna 2.5.0 preview5で改めてプロジェクトを作成
- プロジェクトにEthna 2.5.0 preview5をインストール
$ ethna add-project dummy $ cd dummy $ ethna pear-local channel-discover ethna.jp $ ethna pear-local install http://pear.ethna.jp/pear/Ethna-2.5.2009062201.tgz $ cd .. $ dummy/bin/ethna add-project sample $ cd sample $ ../dummy/bin/ethna pear-local channel-discover ethna.jp $ ../dummy/bin/ethna pear-local install -a http://pear.ethna.jp/pear/Ethna-2.5.2009062201.tgz
これでEthna 2.5.0 preview5によって作られたプロジェクトにEthna 2.5.0 preview5がインストールされた。
このプロジェクトにEthna_Plugin_Debugtoolbarをインストール。
$ bin/ethna pear-local channel-discover openpear.org $ bin/ethna pear-local install openpaer/Ethna_Plugin_Debugtoolbar $ cd www $ ln -s ../lib/.pear/data/Ethna_Plugin_Debugtoolbar/data/www ./Debugtoolbar
このプロジェクトにブラウザでアクセスするとdebugtoolbarが表示…はまだされない。
Ethna_Plugin_Debugtoolbar 0.9.0 をリリース - 肉とご飯と甘いもの @ sotarokのHow to useのとおりにapp/Sample_Controller.phpとetc/sample-ini.phpを修正する。
再度ブラウザでアクセス。…まだdebugtoolbarは表示されない。
lib/Ethna/extlib/Plugin/Filter/Debugtoolbar.phpを見てみると
<?php function postFilter() { if (!$this->ctl->view->hasDefaultHeader) { return null; } $this->init(); $this->dumpInfo(); $this->dumpConfig(); $this->dumpActionForm(); $this->smartyDebug(); }
ていうコードがあるので、ビュークラスに$hasDefaultHeaderの定義を追加してみる。
<?php class Sample_View_Index extends Sample_ViewClass { var $hasDefaultHeader = true;
ページの下になんかでた!どうやらdebugtoolbarが素のまま出てるみたい。
出力されたページ内容でここが気になる。
<link rel="stylesheet" href="/Debugtoolbar/css/ether.css" type="text/css" />
CSSのパスがおかしい?
これを出力してるのはlib/Ethna/extlib/Plugin/Filter/Debugtoolbar.phpのこのへん
<?php function init() { $url = $this->config->get('url'); if (substr($url, -1) != '/') { $url .= '/'; } // jquery がロードされてるかどうか調べる // なければ google.load // めんどくせー常にloadでいい? echo <<<EOL <link rel="stylesheet" href="{$url}Debugtoolbar/css/ether.css" type="text/css" /> <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.load("jquery", "1.2"); </script> <script type="text/javascript" src="{$url}Debugtoolbar/js/jquery.cookie.js"></script> EOL;
etc/sample-ini.phpの'url'は空っぽなので、ここの$urlは「/」になってしまう。
etc/sample-ini.phpを修正。
$config = array(
// site
'url' => './',
こうすればCSSのパスは「./Debugtoolbar/css/ether.css」になって正しくなるはず。
再度ページにアクセス。ページの上にdebugtoolbarが表示された!
でもエラーログが出てる。
Sample[3194](WARNING): Smarty._fetch_resource_info(/lib/Smarty/Smarty.class.php:1415): [PHP] E_USER_WARNING: Smarty error: unable to read resource: "/home/okonomi/public_html/blog/sample/template/smarty_debug.tpl" in /home/okonomi/public_html/blog/sample/lib/Smarty/Smarty.class.php on line 1093
smarty_debug.tplが見つからないらしい。でもそんなファイルはEthna_Plugin_Debugtoolbarのインストールディレクトリにもopenpearのリポジトリにもない…。ググったらnequalさんとこのリポジトリがでてきたのでそこからダウンロードさせてもらった。
$ wget -O template/smarty_debug.tpl http://svn.nequal.jp/public/library/Ether_Suite/trunk/template/smarty_debug.tpl
するとエラーログもなくなってちゃんと動作するようになった!
rhaco2でhello, world
なにやらrhacoがおもしろそう。ちょっと試してみた。無謀にも絶賛開発中のrhaco2で!
実行環境の確認。
$ uname -a Linux thinkpad 2.6.28-11-generic #42-Ubuntu SMP Fri Apr 17 01:57:59 UTC 2009 i686 GNU/Linux $ apache2 -V Server version: Apache/2.2.11 (Ubuntu) Server built: Apr 1 2009 16:03:38 Server's Module Magic Number: 20051115:21 Server loaded: APR 1.2.12, APR-Util 1.2.12 Compiled using: APR 1.2.12, APR-Util 1.2.12 Architecture: 32-bit Server MPM: Prefork threaded: no forked: yes (variable process count) Server compiled with.... -D APACHE_MPM_DIR="server/mpm/prefork" -D APR_HAS_SENDFILE -D APR_HAS_MMAP -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) -D APR_USE_SYSVSEM_SERIALIZE -D APR_USE_PTHREAD_SERIALIZE -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT -D APR_HAS_OTHER_CHILD -D AP_HAVE_RELIABLE_PIPED_LOGS -D DYNAMIC_MODULE_LIMIT=128 -D HTTPD_ROOT="" -D SUEXEC_BIN="/usr/lib/apache2/suexec" -D DEFAULT_PIDLOG="/var/run/apache2.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_LOCKFILE="/var/run/apache2/accept.lock" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types" -D SERVER_CONFIG_FILE="/etc/apache2/apache2.conf" $ php --version PHP 5.2.6-3ubuntu4.1 with Suhosin-Patch 0.9.6.2 (cli) (built: Apr 23 2009 14:35:05) Copyright (c) 1997-2008 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies with Xdebug v2.0.4, Copyright (c) 2002-2008, by Derick Rethans
$ svn co https://rhaco.svn.sourceforge.net/svnroot/rhaco/trunk/ rhaco2 $ svn info rhaco2 パス: rhaco2 URL: https://rhaco.svn.sourceforge.net/svnroot/rhaco/trunk リポジトリのルート: https://rhaco.svn.sourceforge.net/svnroot/rhaco リポジトリ UUID: 838d834a-3123-0410-b9a5-8bcc0e2cc032 リビジョン: 4627 ノード種別: ディレクトリ 準備中の処理: 特になし 最終変更者: rhaco 最終変更リビジョン: 4627 最終変更日時: 2009-05-29 17:40:15 +0900 (金, 29 5月 2009)
r4627だった。
__settings__.phpを作成。
<?php require_once dirname(__FILE__).'/rhaco2/rhaco2'; application_settings(__FILE__, 'http://localhost/');
index.phpを作成。
<?php require_once '__settings__.php'; $flow = new Flow(); $flow->output('index.html');
templates/index.htmlを作成。
hello, rhaco2.
http://localhost/にアクセスすると「hello, rhaco2.」と表示される。
ひとまず今日はここまで!
Net_UserAgent_Mobile_UserIDをリリースしました
携帯電話の固有IDを扱うライブラリをopenpearでリリースしました。
Net_UserAgent_Mobile_UserID \ Package \ Openpear
先日公開された「携帯各キャリアの固有IDについて (全キャリア対応) - ぱらめでぃうす」がすばらしかったので、このまとめをもとにPEARパッケージをでっちあげてみました。
基本的な使い方はこんな感じです。
<?php require_once 'Net/UserAgent/Mobile/UserID.php'; try { $userid = Net_UserAgent_Mobile_UserID::factory(); } catch (Net_UserAgent_Mobile_UserID_Exception $e) { var_dump($e->getMessage()); exit; } // ID本体 echo $userid->getID(); // 接頭文字 echo $userid->getPrefix(); // 解析前のデータ echo $userid->getRawData();
以下のような値が取得されます。
SoftBank
種類 | 接頭文字 | ID本体 |
---|---|---|
UID | なし | 英数16桁 |
端末シリアル番号 | SN | 英数11桁or15桁 |
e-mobile
種類 | 接頭文字 | ID本体 |
---|---|---|
UID | u | 英数17桁 |
先頭の固定文字を接頭文字としてID本体と分離してますが、余計なお世話かもしれません..。
ほかにユーザーIDの判定方法を差し替えたりなど。
<?php require_once 'Net/UserAgent/Mobile/UserID.php'; require_once 'Net/UserAgent/Mobile/UserID/Abstract.php'; // ?id=aa-12345みたいなの 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());
バリデーションだけ単体で使うこともできます。
<?php require_once 'Net/UserAgent/Mobile/DoCoMo/ImodeID.php'; if (Net_UserAgent_Mobile_ImodeID::validateID('xxxxxxx')) { echo "ok"; } else { echo "ng"; }
Net_UserAgent_MobileでもユーザーIDは取得できるんですが、インターフェースが統一されてたらうれしいかなーとか、NDAな処理は呼出し側で追加できたらいいなーとか、そんな感じで作ってみました。
プロジェクトを作ったらまずやること
Ethna 2.3.6で
$ ethna add-project sample
した後。
ローカルと本番サーバで配置するパスが違ったり、本番サーバに勝手にPEARパッケージをインストールすると他のプロジェクトに影響したりするかもしれないので、
- プロジェクトの外のファイルに依存しない
- 絶対パスは排除
な方向で。
ディレクトリ構成をいじる
$ mv sample project $ mkdir sample $ mv project sample/ $ mv sample/project/www/* sample $ rm -r sample/project/www
こうなる。
. `-- sample |-- css |-- js `-- project |-- app | |-- action | |-- action_cli | |-- action_xmlrpc | |-- filter | |-- plugin | | |-- Filter | | `-- Validator | |-- test | `-- view |-- bin |-- etc |-- lib |-- locale | `-- ja | `-- LC_MESSAGES |-- log |-- schema |-- skel |-- template | `-- ja `-- tmp
エントリポイントのrequire_onceのパスをいじる。
sample/index.php
<?php require_once dirname(__FILE__).'/project/app/Sample_Controller.php'; // ここ Sample_Controller::main('Sample_Controller', 'index'); ?>
pear-localの設定
$ cd sample/project
$ ethna pear-local
プロジェクト内にPEARの設定ファイルが作成される。「ethna pear-local config-show 」して、フルパスになってるものを相対パスに変更、あとdownload_dirをlibからtmpに変更。
$ ethna pear-local config-set bin_dir bin
$ ethna pear-local config-set doc_dir lib/.pear/doc
$ ethna pear-local config-set ext_dir lib/.pear/ext
$ ethna pear-local config-set php_dir lib
$ ethna pear-local config-set cache_dir tmp/.pear/cache
$ ethna pear-local config-set data_dir lib/.pear/data
$ ethna pear-local config-set download_dir tmp/.pear/download
$ ethna pear-local config-set temp_dir tmp/.pear/temp
$ ethna pear-local config-set test_dir lib/.pear/test
必要なPEARパッケージをインストール
$ ethna pear-local channel-update pear.php.net Updating channel "pear.php.net" Update of Channel "pear.php.net" succeeded $ ethna pear-local channel-discover pear.ethna.jp Adding Channel "pear.ethna.jp" succeeded Discovery of channel "pear.ethna.jp" succeeded $ ethna pear-local install -a pear downloading PEAR-1.7.2.tgz ... Starting to download PEAR-1.7.2.tgz (302,744 bytes) .....................done: 302,744 bytes downloading Archive_Tar-1.3.2.tgz ... Starting to download Archive_Tar-1.3.2.tgz (17,150 bytes) ...done: 17,150 bytes downloading Structures_Graph-1.0.2.tgz ... Starting to download Structures_Graph-1.0.2.tgz (30,947 bytes) ...done: 30,947 bytes downloading Console_Getopt-1.2.3.tgz ... Starting to download Console_Getopt-1.2.3.tgz (4,011 bytes) ...done: 4,011 bytes downloading XML_RPC-1.5.1.tgz ... Starting to download XML_RPC-1.5.1.tgz (32,215 bytes) ...done: 32,215 bytes install ok: channel://pear.php.net/Archive_Tar-1.3.2 install ok: channel://pear.php.net/Structures_Graph-1.0.2 install ok: channel://pear.php.net/Console_Getopt-1.2.3 install ok: channel://pear.php.net/XML_RPC-1.5.1 install ok: channel://pear.php.net/PEAR-1.7.2 PEAR: Optional feature webinstaller available (PEAR's web-based installer) PEAR: Optional feature gtkinstaller available (PEAR's PHP-GTK-based installer) PEAR: Optional feature gtk2installer available (PEAR's PHP-GTK2-based installer) PEAR: To install optional features use "pear install pear/PEAR#featurename" $ ethna pear-local install -a ethna/ethna WARNING: "pear/DB" is deprecated in favor of "pear/MDB2" downloading Ethna-2.3.6.tgz ... Starting to download Ethna-2.3.6.tgz (183,262 bytes) ......................................done: 183,262 bytes downloading DB-1.7.13.tgz ... Starting to download DB-1.7.13.tgz (132,246 bytes) ...done: 132,246 bytes downloading Smarty-2.6.22.tgz ... Starting to download Smarty-2.6.22.tgz (69,414 bytes) ...done: 69,414 bytes downloading simpletest-1.0.1.tgz ... Starting to download simpletest-1.0.1.tgz (273,378 bytes) ...done: 273,378 bytes install ok: channel://pear.ethna.jp/Ethna-2.3.6 install ok: channel://pear.php.net/DB-1.7.13 install ok: channel://pear.ethna.jp/Smarty-2.6.22 install ok: channel://pear.ethna.jp/simpletest-1.0.1
コントローラのインクルードパス設定をいじる
sample/project/app/Sample_Controller.php
<?php $app = BASE . "/app"; $lib = BASE . "/lib"; //ini_set('include_path', implode(PATH_SEPARATOR, array($app, $lib)) . PATH_SEPARATOR . ini_get('include_path')); ini_set('include_path', implode(PATH_SEPARATOR, array($app, $lib)));
プロジェクト内のファイルだけ参照するようにする。
できあがり。
GUIでHello, World
いろんなGUIライブラリで、「Hello, World」ていうタイトルのウィンドウを表示するサンプル。
環境はVista/VC2008Express。
GTK+
#include <gtk/gtk.h> #include <windows.h> int main(int argc, char *argv[]) { gtk_init(&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title((GtkWindow *)window, "Hello, World"); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
gtkmm
#include <gtkmm.h> #include <windows.h> int main(int argc, char *argv[]) { Gtk::Main kit(argc, argv); Gtk::Window window; window.set_title("Hello, World"); Gtk::Main::run(window); return 0; }
Qt
#include <QtGui/QApplication> #include <QtGui/QWidget> #include <windows.h> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setWindowTitle("Hello, World"); window.show(); return app.exec(); }
wxWidgets
#include <wx/wx.h> class MyApp: public wxApp { virtual bool OnInit() { wxFrame *frame = new wxFrame(NULL, -1, wxT("Hello, World")); frame->Show(); SetTopWindow(frame); return true; } }; IMPLEMENT_APP(MyApp);
WTL
#include <atlbase.h> #include <atlapp.h> CAppModule _Module; #include <atlwin.h> class CMyWindow: public CWindowImpl<CMyWindow> { public: DECLARE_WND_CLASS(_T("Hello")); private: BEGIN_MSG_MAP(CMyWindow) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) END_MSG_MAP() LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL &) { PostQuitMessage(0); return 0; } }; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { _Module.Init(NULL, hInstance); CMessageLoop loop; _Module.AddMessageLoop(&loop); CMyWindow window; window.Create(NULL, CWindow::rcDefault, _T("Hello, World"), WS_OVERLAPPEDWINDOW | WS_VISIBLE); int ret = loop.Run(); _Module.RemoveMessageLoop(); _Module.Term(); return ret; }
ほかにeGUIを試そうとしたけど、リソースエディタ必須みたいな感じだったのでサンプルだけ動かして挫折。