PHP で MVC モデリングの Hello world

近年は MVC というと PHP の Mojavi とか Java の Struts 等の MVC フレームワークが取りざたされます。しかし MVC フレームワークと聞くと何か難しい、MVC も概念は分かるけど使うのは難しい、という人もいるんじゃないでしょうか。
 
というわけで、フレームワークを一切使わず、MVC モデルの Hello, world 的スクリプトを PHP で書いてみました。
 
名前を入力してその人に挨拶する、次のようなコードがあります。これを MVC の構造に変えてみましょう。

nameform.php:
<html>
<head><title>名前入力</title></head>
<body>
   <form action=”” method=”POST”>
       名前:<input type=”text” name=”name”><br>
       <input type=”submit” value=”挨拶”><br>
   </form>
   <?php
      if(!empty($_POST[‘name’])){
          $name = htmlspecialchars($_POST[‘name’]);
          echo “こんにちは、$name!!”;
      }
   ?>
</body>
</html>

これに簡単な MVC モデルを適用すると、次のようになります。

nameform.php:
<?php
    // 挨拶プログラム(Controller)
    
    // 機能部分を読み込み
    require_once ‘include/greeting.inc’;
    // 挨拶を実行し、出力用に特殊文字をエスケープする。
    $result = htmlspecialchars( greet() );
    // 結果を表示。
    require_once ‘template/nameform.html’; // View を呼び出し。
?>

include/greeting.inc:
<?php
  //
  // 挨拶プログラムの Model (ドメイン固有)
  //
  
  require_once dirname(__file__).’/request.inc’; // パラメータ取得用
  /**
   * 名前を取得し、挨拶する。
   * @return string 挨拶の言葉。処理できなかった場合空文字
   * @access public
   */
  function greet(){
      $name = get_parameter(‘name’);
      if($name){
          return greet_to($name);
      } else {
          return;
      }
  }
  
  /**
   * 指定した相手に挨拶する。
   * @param string $name 相手
   * @param string 挨拶の言葉
   * @access private
   */
  function greet_to($name){
      echo “こんにちは、$name!!”;
  }
?>

include/request.inc
<?php
//
// パラメータ操作用ユーティリティファイル (非ドメイン固有 Model)
//
/**
 * 指定した名前を持つリクエストパラメータを取得する。
 * 存在しない場合は空文字を返す。
 * @access public
 * @param string $key 取得したいパラメータの識別名
 * @return string パラメータの中身。存在しない場合空文字
 */
function get_parameter($key){
    return empty($_POST[$key])? : $_POST[‘key’];
}
?>

template/nameform.html:
<!– 名前入力フォーム(view) –>
<html>
<head><title>名前入力</title></head>
<body>
    <form action=”” method=”post”>
        名前:<input type=”text” name=”name”><br>
        <input type=”submit” value=”挨拶”><br>
    </form>
    <!– 処理結果 –>
    $result
    ?>
</body>
</html>

どうでしょう?
PHP のコード(モデル、コントローラ)と HTML デザイン(ビュー)がしっかり分離できているのが確認できると思います。また、メインルーチン(コントローラ)と関数(モデル)が別ファイルに分けられていて、関数はさらに汎用的なもの(共通モデル)と挨拶プログラム固有と思われるもの(ドメイン固有モデル)とに分けています。
 
この程度であればメリットは感じず、ただ書く量が増えるだけに感じると思いますが、これが数百行を超えると大きく変わってきます。
 
– ビューとコントローラを分けることでデザイナとプログラマの作業分担をしやすくなる。
– コントローラとモデルを分けることで同じ処理を行う時にコピーペーストを行う必要がなくなる。
– さらにモデルをドメイン固有モデルと共通モデルとに分ける事で、他のシステムで使い回しても影響がない部品(=共通モデル)が明確になり、再利用性が高まる。
 
感覚が掴めそうな方は、サンプルに挙げた挨拶プログラムを基本として、次のように改善していってみましょう。
 
– ビューに PHP コードでなく Smarty を使うようにする。その場合、htmlspecialchars はやめ、代わりに Smarty の ${result|escape} など escape 修飾子を利用するといいでしょう。
– モデルを関数ではなくクラスにする。
– コントローラに処理を書いていく時は、処理を関数として抽出できないか目を光らせておきましょう。抽出できそうな時はドメイン固有モデルとして抽出、移動しましょう。
– ドメイン固有モデルが増えてきた時は、汎用的な共通モデルにできないか考えましょう。つまり、モデルのコードを一切変更することなく、他のシステムで利用可能かどうか考えましょう。他のシステムでも有用な機能があるのに、他のシステムで使うには変更の必要がありそうなときは、変更せずに済む方法を実装し、共通モデルにすることも検討してみましょう。(内部パラメータの setter を用意する、設定ファイルを読み込めるようにするなど)
 
なお、PHP での MVC モデリングについては Zend コーディング指針の MVC の項も参考になります。
 
参考:
Smarty(日本語マニュアル)

iptables -F でネットにつながらなくなりました

Q. リモートからネットワーク設定作業をしており、いざと言うときのために、

sleep 300 && iptables -F

を裏で実行するようにしましたが、iptables -F を実行した瞬間にネットに一切つながらなくなりました。何が原因ですか?
 
A.iptables -F はデフォルトポリシー以外の全てのルールを消去します。
iptables -F を実行した直後はデフォルトポリシーだけの状態になるため、
たとえば iptables-save が次のように始まるような場合…

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

このように、INPUT DROP の設定になっている場合、もし iptables -F を実行すると、入力パケット(INPUT)を常に破棄(DROP)してしまうため、外部から(ping = ICMP すら)一切つながらなくなってしまいます。
 
こういう環境で作業する場合、代替として次のようにして確実に繋げる設定を復旧させるとよいでしょう。

sleep 300 && ( iptables-restore < iptables-free )

あるいは、環境に依存しますが例えば次のようにして /etc/sysconfig/iptables の状態を復元するのもいいでしょう。

sleep 300 && /etc/init.d/network restart

Apache httpdの現在のプロセス数、TCP 接続本数を調べる

ab(Apache Bench) コマンドなどを実行する場合など、HTTP サーバのパフォーマンスの分析を簡易的にしたい場合に、
topなどで監視するのもいいのですが、Apacheが現在何プロセス、何本のコネクションか定期的に監視できると便利です。

今回は毎秒Apacheのプロセス数とHTTP/HTTPS接続本数を調べて結果を出力し続けるというコードを書いてみました。

続きを読む Apache httpdの現在のプロセス数、TCP 接続本数を調べる

pkgdb.rb での Segmentation Fault

[2006-02-01] の portsdb.rb での Segmentation Fault とほぼ同じ現象に再び遭遇。

$ portversion -vL=
—> Checking the package registry database
[Updating the pkgdb <format:bdb1_btree> in /var/db/pkg … – 249 packages found (-2 +0) (…)/usr/local/lib/ruby/site_ruby/1.8/pkgdb.rb:466: [BUG] Segmentation fault
ruby 1.8.4 (2005-12-24) [i386-freebsd4]
 
Abort trap (core dumped)

なんで bdb1_btree 見てるのか、と疑問に思いながらソースコードを追っていくとどうやら、PKG_DBDRIVER という変数を見ているもよう。portsdb では PORTS_DBDRIVER ですが、pkgdb ではこちらを使う、と。PORTS_DBDRIVER と同様、PKG_DBDRIVER も bdb_btree (bdb1_btree)がデフォルトで、これは freebsd5 でも変わっていないようです。

export PKG_DBDRIVER=bdb1_hash
pkgdb -aF

これで対処完了!
 
追記: pkgtools.conf に

ENV[‘PORTS_DBDRIVER’] = ‘bdb1_hash’
ENV[‘PKG_DBDRIVER’] = ‘bdb1_hash’

とするほうが設定がまとまっていいかもです。

今日の Eclipse Plugin

最近ネタがあっても更新してません(。。;)
翻訳プラグイン
リリース当初から知ってたものの、見なかった事にしていたプラグイン^^;
命名の時の手間が減るかなと思い今更に導入。
Update Site: http://www.eisbahn.jp/update-site/
EclipseUML
Free Edition を導入。GEF, EMF がバンドルされ, インストーラ(実行可能なjar形式)での配布で昔に比べてインストールが容易になってました。
普段 Jude Community Edition を使っているのですが、
いまいちコードとの同期が取りづらいのと、UML2.0 に対応していないのが不満だったので..
 
HeapStatus
Eclipse3.2 で標準搭載になった(Eclipse自体の)メモリ使用状況表示, メモリ解放プラグイン。
Update Site: http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/updates
追記(2006-07-21): Eclipse3.2 ではデフォルトでヒープステータス表示がオフになっている。「設定→ 一般」の「ヒープステータスを表示」のチェックを入れることで利用可能になります。
 
Commons4E (@IT の記事)
Update Site: http://commons4e.berlios.de/updatesite/
ソロプログラミングプラグイン
これにはまったらきっと病んでる。

モニタリング用プロトコル SNMP を体験するには

– Linux の場合、yum, apt-get などで net-snmp-*.rpm をインストールします。

yum install net-snmp-*.rpm

 
– /etc/snmp.conf でアクセス権を設定する。
次のような設定で全ての情報が参照可能になります。この状態で外部に UDP 160, UDP 161 番ポートを公開すると、誰でもどこからでも同じ情報が参照可能になることに注意してください!!

# 詳細は man 5 snmpd.conf を参照。
# sec.name source community
com2sec notConfigUser default public
# groupName securityModel securityName
group notConfigGroup v1 notConfigUser
group notConfigGroup v2c notConfigUser
group notConfigGroup v3 notConfigUser
# name incl/excl subtree mask(optional)
view all included .1
# group context sec.model sec.level prefix read write notif
access notConfigGroup “” any noauth exact all all all
 
 
syslocation Unknown (edit /etc/snmp/snmpd.conf)
syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
 
# Added for support of bcm5820 cards
pass .1.3.6.1.4.1.4413.4.1 /usr/bin/ucd5820stat

> /etc/init.d/snmpd start

/etc/init.d/snmptrapd start

でサーバ側は完了です。
監視側は TWSNMP というフリーソフトを使うとお手軽なのでおすすめです。

eAccelerator トラブルシューティング – Can not create shared memory area in Unknown on line 0

Q. Linux + Apache + PHP + eAccelerator の環境で apache が次のエラーを出して動かなくなりました。

$tail -f error_log
PHP Warning: [eAccelerator] Can not create shared memory area in Unknown on line 0
PHP Fatal error: Unable to start eAccelerator module in Unknown on line 0
[Thu Feb 23 09:26:31 2006] [warn] pid file /usr/local/apache_1.3.34/logs/httpd.pid overwritten — Unclean shutdown of previous Apache run?
PHP Warning: [eAccelerator] Can not create shared memory area in Unknown on line 0
PHP Fatal error: Unable to start eAccelerator module in Unknown on line 0

A. このエラーが出た場合、原因はここの次の FAQ に書いてあるケースの可能性があります。

Q: I’m using linux 2.6 kernel and eAccelerator doesn’t get loaded when the shm_size is set to value bigger than 32mb. Php gives this warning:
PHP Warning: [eAccelerator] Can not create shared memory area in Unknown on line 0

A: The default shared memory size for the 2.6 kernel is 32mb. You can change this size by setting /proc/sys/kernel/shmmax to the disired maximum value. You can do this by echo VAL > /proc/sys/kernel/shmmax or add the line kernel.shmmax=VAL to /etc/sysctl.conf so you don’t have to set it manualy every time you reboot.

カーネルの共有メモリ制限(デフォルト32MB)を超えて、eaccelerator.shm_size を設定したのが原因でした。php.ini で

eaccelerator.shm_size=32

のように範囲内に押えるか、あるいは FAQ にあるように

# cat /proc/sys/kernel/shmmax
33554432

を、
# expr 64 “*” 1024 “*” 1024 > /proc/sys/kernel/shmmax
のように、バイト単位で適切に上限を設定してカーネルごとリブートすれば解決します。

OpenLaszlo メモ

■OpenLaszlo デモ:
http://www.laszlosystems.com/partners/support/demos/
■OpenLaszlo 利用についての @IT の記事:
http://www.atmarkit.co.jp/fwcr/rensai/laszlo01/01.html
■採用している例:
http://www.behr.com/behrx/colorsmart/main.jsp
http://www.svcfinancial.com/sol_demo_library2.html
 から辿れるリンク先(view demo とあるもの)。
 
■その他採用サイト一覧:
http://www.laszlosystems.com/customers/case/
■OpenLaszlo でビジネス展開している日本の会社:
http://www.net8.co.jp/