<   2012年 11月 ( 35 )   > この月の画像一覧
(PHP,IE)インラインフレームで別ドメインのPHP読み込むとセッションが効かない
インラインフレームを使ったWEBサイトを作っています。
このサイトは www.hoge.jp とします。
フレーム内のコンテンツは、www.piyo.com の PHP ファイルです。

この時、フレーム内のPHPでセッション管理しようとしてもできません。
www.piyo.com/login_input.php から www.piyo.com/login_chk.php に遷移してもセッション情報が引き継がれないのです。

これは、IE6以降で現象が発生しました。FirefoxやChromeでは問題なく動きます。


この時、セッション管理はCookieを使ってました。
IE6以降ではこのようなクロスドメイン環境の場合、プライバシー保護のために別ドメイン(サードパーティ)のクッキーは受け入れないようです。

クライアント側のIEのプライバシー設定で、サードパーティ製のクッキーを受け入れるようにすればいいのですが、サイト管理者からはそんなことは言えません。

対策として、PHPでセッション開始したりクッキーを使う前に以下のコードを書けばいいようです。
header("P3P: CP='UNI CUR OUR'");


IEはP3Pに準拠してるようで、P3Pというのはプライバシーポリシーを記述する標準フォーマットらしく、上記のコードを書くことでそれに準拠してるよ みたいなことを宣言するようです。


ちなみに、セッションをCookieに持たすのではなくURLに持たすことでも動きますが、やはりセキュリティ上好ましくないでしょう。

参考:
IEでクロスドメインのiframe内のcookieが取れない/WEBサイト作成の注意点 サイト構築日記
PHP:IE6でサードパーティのクッキーを受け入れるようにする:P3P
サードパーディーのCookie | shinodogg.com
IE 6のプライバシ管理機能 - @IT
[PR]
by Jehoshaphat | 2012-11-30 23:23 | PHP開発 | Trackback | Comments(0)
(SQL)テーブル名にハイフン入ってる時はクォートする必要あり
SQLiteでついハイフン(-)入のテーブルを作ってしまい、以下の用なクエリを実行したらエラーになりました。
SELECT * FROM hoge-test WHERE name='moe';

テーブル名にハイフンが入っていると、ダメなようです。
これは、SQLiteに限らず他のDBMS(MySQLやSQL Server)も同様みたいです。

解決策としては、ハイフンを付けないか、以下のようにクォートしてやるかです。
SELECT * FROM 'hoge-test' WHERE name='moe';


しばらくSQLやDB触ってないとこうなっちゃいますね。

参考:
PHP+SQLの覚え書き: テーブル名にハイフンはご法度
龍の記憶:SQLServer SQL のテーブル名に - (半角ハイフン) - livedoor Blog(ブログ)
[PR]
by Jehoshaphat | 2012-11-30 23:22 | SQL | Trackback | Comments(0)
(PHP)mb_send_mailでCCを指定したい
mb_send_mail関数でメールを送る方法を(PHP)日本語メール送信で書きましたが、CCやBCCを指定したい時は、第四引数のヘッダ指定部分に以下のように指定してやればいいようです。
//mb系関数を使うための前処理
mb_language("Japanese");
/* 内部文字エンコーディングをUTF-8に設定 (UTF-8でスクリプト書いているため)*/
mb_internal_encoding("UTF-8");
 
//メール送信
$mailTo = "info@example.com";
$mailFromAddr = "<info@example.com>";
$mailSubject = "メール題名";
$mailCc = "hogecc@example.com";
$mailBcc1 = "hogebcc1@example.com";
$mailBcc2 = "hogebcc2@example.com";
 
//送信元に日本語付加
$mailFrom = mb_encode_mimeheader(mb_convert_encoding("【自動送信フォーム】","JIS","UTF-8")). $mailFromAddr;
 
 
//メール本文。
$mailBody = "メール本文。";
 
$mailhead = "From:" . $mailFrom ;
$mailhead .= "\n";
$mailhead .= "Cc:" . $mailCc;
$mailhead .= "\n";
$mailhead .= "Bcc:" . $mailBcc1;
$mailhead .= "," . $mailBcc2;
 
 
//メール送信(送信先、 件名、 本文、 メールヘッダ)
if( mb_send_mail( $mailTo , $mailSubject , $mailBody ,mailhead ) ){
//メールが正常に送れたら
$res = "送信成功";
}else{
//メールが送れなかったら
$res = "送信失敗";
}
echo $res;

参考:
PHPのmb_send_mailでCCやBCCを指定する方法 | 自由が丘で働くWeb屋のブログ
[PR]
by Jehoshaphat | 2012-11-29 23:20 | PHP開発 | Trackback | Comments(1)
(PHP)Smartyを使っているがShift-JISで出力したい
Shift-JISで作られているCGIのサイトをPHP(テンプレートエンジンとしてSmarty使用)に移行してるんですが、やはり移行後もわけあってShift-JISでないとダメなようです。
で、SmartyのテンプレートファイルをShift-JISで作るとエラーが。。。
どうやら「必須」という文字がSmartyのメタ文字「{」となっちゃってるようです。
やはり、Shift-JISのファイルは作っちゃダメだなということで、テンプレートファイル、PHPファイル共にUTF-8で書き、Smartyのアウトプットフィルタを使って出力時にShift-JISに変換することとしました。

以下のような感じです。
//Smarty読み込み(ドキュメントルート外のSmartyクラスにアクセス)
require_once('Smarty.class.php');
//Smartyオブジェクト作成
$smarty = new Smarty();
$smarty->template_dir = "/smarty/templates";
$smarty->compile_dir = "/smarty/templates_c";
$smarty->cache_dir ="/smarty/cache";
 
//アウトプットフィルタを使用し文字コード変換
$smarty->registerFilter("output","filterSjis");
ini_set("default_charset", "Shift_JIS");
 
//テンプレート表示
$smarty->display("hoge.tpl");
 
//smartyアウトプットフィルタ
function filterSjis($buff, &$smarty){
return mb_convert_encoding($buff,"SJIS","UTF-8");
}


参考サイトでは $smarty->register_outputfilter を使っているですが、Smarty3でこのメソッド使うと、"Notice: function call 'register_outputfilter' is unknown or deprecated." みたいなエラーになります。
Smarty3系からは $smarty->registerFilter(タイプ,コールバック関数); としないといけないようです。


参考:
Smartyのアウトプットフィルタを使ってみる kawama.jp
エピゴーネンで | register_prefilterの挙動を変えるとかなしにしようぜSmartyさん
SJISページでのSmartyの使い方 | ガイドミー管理者日記
[PR]
by Jehoshaphat | 2012-11-29 23:18 | PHP開発 | Trackback | Comments(0)
(Linux)CentOSでchkconfigできないプログラムの自動起動方法
デーモンプログラムをパッケージではなくソースからインストールすると、ini.d配下にある起動スクリプトはできませんし、 chkconfig のリストにでてきません。
起動スクリプトはソフトによって異なるのでネットで情報得て作成するとして、マシンの電源投入時にデーモンを実行するには、/etc/rc.d/rc.local ファイルの末尾行に実行ファイルのパスを設定すればいいようです。


# vi /etc/rc.d/rc.local

/usr/local/apache/bin/apachectl start ←追記
/etc/init.d/smokeping start ←追記



参考:
rc.local Linux(Cent OS)で起動時に自動実行するスクリプトの登録
LINUXの電源のON,OFFのやりかた、ONの時に自動的にプログラムが起動するようにする
[PR]
by Jehoshaphat | 2012-11-28 23:16 | Linux | Trackback | Comments(0)
(Linux)CentOSでパッケージグループ単位でインストールする
RedHatEnterpriseLinux6.0のクローンであるCentOS6をインストールしたわけですが、PCのスペックが低すぎてテキストインストールとなってしまいました。
テキストインストールだと最低限のパッケージしか入りません。

インストール後にちまちま個別にパッケージ入れるのも面倒です。

それで、Anacondaのインストーラみたいにパッケージグループ単位でインストール出来ないものか調査したところ、yum コマンドで出来るようです。

まず、以下コマンドでインストール済み、及び、インストール可能なグループを表示できます。


# yum grouplist
Loaded plugins: fastestmirror
Setting up Group Process
Loading mirror speeds from cached hostfile
* base: ftp.jaist.ac.jp
* extras: ftp.jaist.ac.jp
* updates: ftp.jaist.ac.jp
base | 3.7 kB 00:00
extras | 951 B 00:00
updates | 3.5 kB 00:04
base/group_gz | 206 kB 00:00
Installed Groups:    ←インストール済み
Optional packages
電子メールサーバー
Available Groups:    ←未インストール
CIFS ファイルサーバー
Eclipse
Emacs
FCoE ストレージクライアント
FTP サーバー
Infiniband のサポート
Java プラットフォーム
KDE デスクトップ
MySQL データベースクライアント
MySQL データベースサーバー
NFS ファイルサーバー
PHP サポート
Perl のサポート
PostgreSQL データベースクライアント
PostgreSQL データベースサーバー
SNMP サポート
TeX のサポート
TurboGears アプリケーションフレームワーク
WBEM サポート
Web サーバー
Web サーブレットエンジン
X Window System
iSCSI ストレージクライアント
...省略
Done



任意のパッケージグループをインストールするには以下のようにすればいいようです。

yum groupinstall "FTP サーバー"


なお、CetOS6.0の場合、"開発ツール " だけ、なぜか全角スペースが後に入っていたので注意が必要です。
なんか日本語で指定するのはちょっと気持ち悪いですね。

例えばテキストインストールして、X Window System とGNOMEデスクトップを使いたい場合は以下のようにします。


yum groupinstall "X Window System" "デスクトップ"




groupremove で削除、groupinfo でパッケージ中身を表示 するようです。

参考:
@IT:yumで関連パッケージをまとめて追加/削除するには
[PR]
by Jehoshaphat | 2012-11-27 23:14 | Linux | Trackback | Comments(0)
(Linux)CentOS6では参照するDNSサーバの書き方が変わった?
RedHatEnterprise6.0のクローンであるCentOS6ですが、名前解決のために指定するDNSサーバのアドレスの指定方法が変わったようです。

今までは、/etc/resolv.conf に nameserver xxx.xxx.xxx.xxx としていました。
しかし、resolv.conf にはこう書いています。

# No nameservers found; try putting DNS servers into your
# ifcfg files in /etc/sysconfig/network-scripts like so:
#
# DNS1=xxx.xxx.xxx.xxx
# DNS2=xxx.xxx.xxx.xxx
# DOMAIN=lab.foo.com bar.foo.com


どうやら、/etc/sysconfig/network-scripts/ のインターフェイスの設定に DNS1=xxx.xxx.xxx.xxx という感じで書かないと行けないようです。

こんな感じです。

vi /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE="eth0"
BOOTPROTO="static"
HWADDR="00:0B:xx:xx:xx:xx"
IPV6INIT="yes"
IPV6_AUTOCONF="no"
NM_CONTROLLED="yes"
ONBOOT="yes"
IPADDR="192.168.0.100"
NETMASK=255.255.255.0
DNS1=192.168.0.1
DNS2=192.168.0.2
GATEWAY=192.168.0.254


こうして、再起動すると、/etc/resolv.conf に自動的に設定が書かれていました。
[PR]
by Jehoshaphat | 2012-11-27 23:13 | Linux | Trackback(1) | Comments(0)
PukiWikiのページをGUIで編集できるようにするguieditプラグイン
PukiWikiで情報共有サイトを作っても、エンドユーザには独特のWiki記法がネックになってしまうケースが多々あります。

ということで、WYSIWYG でページを編集できるものがないか探したところ、guieditというプラグインがありました。
(こちらのデモサイトで動作を確認できます。)
このプラグインは、オープンソースHTMLエディタである、FCKeditor をPukiwikiでも使えるようにしたもののようです。

ダウンロードは公式サイトから可能です。

インストール方法も上記サイトに書いてますが、一応メモしておきます。

まず、guiedit をダウンロードし、解凍します。
解凍後に、plugin\guiedit.inc.php を PukiWiki の plugin ディレクトリに配置します。
また、skin\guiedit ディレクトリを PukiWiki の skin ディレクトリに配置します。


FCKeditor を公式サイトからダウロードします。
解凍後に、fckeditor を Pukiwiki の skin ディレクトリに配置します。

skin/pukiwiki.skin.php の

<?php _navigator('edit') ?> |

の次行に以下を追加します。

<?php echo '<a href="' . $script . '?cmd=guiedit&page=' . $r_page . '">' .
$lang['guiedit'] . '</a>' ?> |



ja.lng.php の
$_LANG['skin']['edit']      = '編集';

の次行に以下を追加します。
$_LANG['skin']['guiedit']   = '編集(GUI)';



pukiwiki.ini.php でPKWK_ALLOW_JAVASCRIPT を 1 にし、JavaScriptを有効にします。
define('PKWK_ALLOW_JAVASCRIPT', 1);



$pkwk_dtd を PKWK_DTD_XHTML_1_0_TRANSITIONAL か PKWK_DTD_HTML_4_01_TRANSITIONAL にします。
(PKWK_DTD_XHTML_1_0_TRANSITIONALにした場合)

//$pkwk_dtd = PKWK_DTD_XHTML_1_1; // Default
//$pkwk_dtd = PKWK_DTD_XHTML_1_0_STRICT;
$pkwk_dtd = PKWK_DTD_XHTML_1_0_TRANSITIONAL;
//$pkwk_dtd = PKWK_DTD_HTML_4_01_STRICT;
//$pkwk_dtd = PKWK_DTD_HTML_4_01_TRANSITIONAL;



lib/convert_html.php の
$anchor = ' &aname(' . $id . ',super,full){' . $_symbol_anchor . '};';

の次行に以下を追加します。

$fixed_heading_anchor = 1;
$fixed_heading_anchor_edit = 1;




ツールバーにリンクを追加するために、以下の設定を行います。

ja.lng.php の
$_LANG['skin']['edit']      = '編集';

の次行に以下を追加します。
$_LANG['skin']['guiedit']   = '編集(GUI)';



lib/html.php の
$_LINK['edit']     = "$script?cmd=edit&page=$r_page";

の次行に以下を追加します。
$_LINK['guiedit']  = "$script?cmd=guiedit&page=$r_page";



skin/pukiwiki.skin.php の
$_IMAGE['skin']['edit']     = 'edit.png';

の次行に以下を追加します。
$_IMAGE['skin']['guiedit']  = 'edit.png';



skin/pukiwiki.skin.php の
<?php _toolbar('edit') ?>

の次行に以下を追加します。
<?php _toolbar('guiedit') ?>





guieditを導入して気になったのが、編集画面の縦が小さいことです。
どうやら既定値は300pxのようです。これではちょっと不便なので、もっと縦を長くとってみました。


skin/guiedit/guiedit.js ファイルの
var oFCKeditor = new FCKeditor('msg', '100%', 300, 'Normal');

の 300 の所を任意の値にすると高さが変わるようです。


文章入力時に普通に改行すると、違う段落になってしまうようです。
同じ段落内での改行は Shift+Enter で改行しないといけないようですね。


リンクを張る場合、リンクを張る文字列を選択し、「リンク挿入/編集」ボタンを押します。URL へのリンクを張る場合はリンクタイプ:URL,プロトコル:httpを選びURLを、Wiki ページ名へのリンクを張る場合は、リンクタイプ:URL,プロトコルから<その他>を選択しURL欄にページ名を入力するようです。
[PR]
by Jehoshaphat | 2012-11-26 23:00 | PHP開発 | Trackback | Comments(0)
(Linux)PXEサーバ(Ubuntu系)を立ててネットワークブートでCentOS6をインストールしてみた
今回、光学ドライブがなくUSBブートもできない端末に、RedHatEnterpriseLinux6.0のクローンである CentOS6.0 をインストーすることになりました。
この端末は幸いにも、ネットワークブート(PXE)に対応してしたので、そこからのインストールを試みてみました。


PXEサーバは Ubuntu10.04 をベースにしている EcoLinux10.04 を使うこととしました。
PXEサーバに必要なのは、DHCPサーバ、TFTPサーバ、HTTPサーバとなるので、これらをまずインストールします。

●TFTPサーバ
当初、xinetdスーパーサーバを介して、tftpd を使おうかと思ってました。
しかし、いざtftpdで環境構築するとネットワークブートしたクライアント側で「TFTP server does not support the tsize option 」というエラーが出てブートに失敗します。
これは Debian 系のTFTPDは tsize オプションをサポートしてないためのようです。
(Ubuntu系で tftp をインストーするには、 apt-get install tftpd でできます)

それで、TFTPサーバとしては tftpd-hpa を使うことにしました。
まず、インストールです。

apt-get install tftpd-hpa


公開するディレクトリを作成後、設定ファイルを修正します。

mkdir /tftpd

vi /etc/default/tftpd-hpa

TFTPD_DIRECTORY="/tftpd" ←公開するディレクトリ
RUN_DEAMON="yes" ←追記

service tftpd-hpa start ←サービス開始

ちゃんと動いているかどうかは、netstatでポートを確認するといいかもしれません。

netstat -an | grep 69

また、ダミーファイルを公開ディレクトリに配置し、WindowsPCのコマンドプロンプトでダウンロードできるか確認もできます。

tftp サーバIP get a.txt



●DHCPサーバ
PXEクライアントは起動時にDHCPサーバからIPを取得する必要がありますが、ルータ等のDHCP機能では細かいオプションが指定できないため、自前で立てる必要があります。
既にDHCPサーバがLAN内にある場合は運用に気を付けないとおかしなことになります。
なので、PXEブートするときだけ別LANにして、DHCPサーバを起動するような方法をとったほうが良いかもしれません。

インストールは以下のようにします。

apt-get install dhcp3-server

DHCPサーバの設定ファイルを変更します。

vi /etc/dhcpd.conf


subnet 192.168.0.0 netmask 255.255.255.0 {
option subnet-mask 255.255.255.0;
option time-offset -18000;
filename "/linux-install/pxelinu.0" ←ロードするファイル名
next-server 192.168.0.2 ←TFTPサーバのIP(TFTP,DHCPサーバが同一マシンなら、自身のIPでもOK)
range dynamic-bootp 192.168.0.100 192.168.0.100; ←割り当てるIP範囲
default-lease-time 21600;
max-lease-time 43200;

}


設定が終われば、DHCPサーバを起動します。

service dhcp3-server start


なお、このままだとPC起動時にもDHCPサーバが立ち上がってしまうので、自動起動しないようにしておきます。

update-rc.d dhcp3-server disable


●Apache
CentOS自体のインストールはHTTPを使って行います。(FTPでもいいのですが)
EcoLinuxにはWEBサーバが入ってないので、インストールします。

apt-get install apache2

service apache2 start


●PXEブートローダ配置
PXEブートローダは syslinux パッケージに入っているようです。
EcoLinuxではデフォルトで入っていました。

PXEブートローダファイルを、TFTPの公開ディレクトリに配置します。
また、CentOSのISOファイルを、Apache公開ディレクトリにマウントし、ブートイメージをTFTP公開に配置します。

cp /usr/lib/syslinux/pxelinux.0 /tftpboot/linux_install/

mkdir /var/www/centos6
mount -t iso9660 -o loop /home/hoge/CentOS-6.0-i386-bin-DVD.iso /var/www/centos6

cp /var/www/centos6/images/pxeboot/vmlinuz /tftpboot/linux-install
cp /var/www/centos6/images/pxeboot/initrd.img /tftpboot/linux-install


PXEブートの設定ファイルを作成します。

mkdir /tftpboot/linux-install/pxelinux.cfg
vi /tftpboot/linux-install/pxelinux.cfg/default

↓ファイルの中身
default centos6
label dentos6
kernel vmlinuz
append load initrd=initrd.img devfs=nomount


●クライアントにて実行
後は、クライアントでネットワークブートを実施します。
(場合によってはBIOSでネットワークブートの優先度を上げる必要があるかもしれません。PCによってはBIOS起動の画面でファンクションキー押せばネットワークブートするのもあるようです)

DHCPよりIPが割り振られて、TFTP経由でPXEブートローダが読み込まれ、インストーラが起動します。

言語設定と、キーボード設定を行い、インストール元で URL を選択します。
URL欄で、ウェブサーバのCentOSをマウントしているディレクトリ( http://svip/centos6 )を入力します。
すると、Anacondaが立ちがありいつものインストール画面となります。(PCのグラフィックスペックが低い場合はテキストインストールになってしまいますが。。。)


ちょっとサーバを立てるのが手間ですが、非常に便利ですね。


参考:
Ubuntu Weekly Recipe:第47回 Ubuntuのネットワークインストールとapt-mirrorの活用|gihyo.jp … 技術評論社
きままなひとりごと Ubuntu 11.04 PXEブート環境の構築
第1回 ネットワーク経由でCentOSを導入する - 旧型ノートPCで本格サーバーを作ろう:ITpro
@IT:PXEネットワークブート用サーバを構築するには RedHat系でPXEサーバとする例です。
PXEネットワークブートでCentOSをインストール/kickstartによるインストール自動化 - Layer8 Reference RedHat系でPXEサーバとする例です。

Windows XP のネットワークインストール (Windows PE 3.0 使用) - regerege メモ帳 PXEでWindowsをインストールする例ですが、Windowsはちょっと面倒くさそうです。
[PR]
by Jehoshaphat | 2012-11-26 01:11 | Linux | Trackback | Comments(0)
(PHP)MVCモデルを使ったPHPアプリケーション
PHPのフレームワーク(CakePHP等)は、元からMVCモデルとなっているわけですが、機能も多く重量級です。
軽量のMVCフレームワークもあるのかもしれませんが、ほんとに小規模なPHPアプリケーションとかだと、案外自作にした方が効率がよいのかもしれません。

5年度前に、以前の勤務先で自作MVCモデルを使ってたんですが、しばらくPHP触らない間にすっかり忘れていました。
ということで、PHPのオブジェクト指向入門 | オブジェクト指向PHP.NETを参考に、軽量なMVCフレームワークを作ってみました。


MVCの概念は多くのサイトで解説されているので省略します。

今回作成するのは、大まかに下記のような構造になります。
e0091163_145447.jpg



リクエス振り分け
まずは、リクエスト振り分けの部分です。
たいていは、全アクセスを index.php に集中させ、そこからURLの内容に基づきどのコントローラのどのアクションに処理を割り振るかを制御します。

利用するコントローラを指定する方法として、URLの index.php に対してGETパラメータを付ける方法と、/区切りでパラメータを付ける方法があります。

今回は / 区切りでパラータを指定する方法を取りました。
(http://hoge.jp/index.php?c=login → http://hoge.jp/login/ みたいな感じ)

参考先の設定ではサイト直下にMVCコンテンツを置くような設定になっています。
しかしイントラネットのサーバ等で1台のWEBサーバにWEBアプリが乱立していると、サイト直下に配置できないケースが出てくるんですよね。
(例えば、http://hoge.jp/eigyou/ とか http://hoge.jp/jousys/ とか部署のディレクトリの配下にコンテンツ置く必要がある場合など)

ということで、特定の階層以下からコントローラのパラータとみなすように手を加えてみました。
例として、http://hoge.jp/eigyou/ 配下にMVCモデルで作ったコンテンツを置くこととします。

まず、apacheのリライト機能の設定です。
コンテツを置く場所の .htaccess に以下のように設定しました。
RewriteRuleに QSA を指定するとこで、GETパラメータも引き継げます。

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /eigyou/ [QSA,L]

※当然MVCアプリコンテンツのパスが変わると、mod_rewriteの設定は変わります。
例:http://hoge.jp/ → RewriteRule ^(.*)$ / [QSA,L]
例:http://hoge.jp/eigyou/app1/ → RewriteRule ^(.*)$ /eigyou/app1/ [QSA,L]



全てのアクセスが集中する index.php とそこから呼ばれる Dispatcher.php は下記のようになります。
(文字数制限のためハイライトはなしです)

index.php

<?php

require_once 'Dispatcher.php';
require_once 'util.php'
$dispatcher = new Dispatcher();

IncludePathSetting($dispatcher);

//apacheのドキュメントルートから何階層目のディレクトリにMVCアプリを配備するか。
//ルートを0とすると、eigyou/ 配下は1階層目に当たるので、1とする。
$dispatcher->setPramLevel(1);
$dispatcher->dispatch();

?>



util.php

<?php
/**
* PHPのinclude_pathを設定。
* 本番環境、テスト環境を切り分ける。
*/
function IncludePathSetting($dispatcher){
if ($_SERVER['SERVER_NAME']=='hoge.jp' ){
//本番環境
$path = '/home/hoge/smarty/libs/';
$path .= PATH_SEPARATOR . '/home/hoge/別にインクルードするディレクトリあれば指定/';
$dispatcher->setSystemRoot('/home/hoge/html/eigyou);
} else {
//開発環境
$path = 'D:/devlop/php/smarty/libs/';
$path .= PATH_SEPARATOR . 'D:/devlop/php/別にインクルードするディレクトリあれば指定/';
$dispatcher->setSystemRoot('D:/devlop/php/eigyou');
}
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
}
?>



Dispatcher.php
このPHPファイルで、リクエストを振り分けます。
1つめのパラメータで、どのコントローラを使うか決めます。
具体的に、パラメータ名+Controller というクラスのインスタンスを作成します。
そして、2つめのパラメータでどのアクションメソッドを実行するか決めます。
こちらも、パラメータ名+Action というメソッドを実行します。

<?php
class Dispatcher
{
private $sysRoot;
//URLの階層設定。どの階層からをパラメータとして解釈するか。
// /直下に置くなら0, /hoge/以下に置くなら1, /hoge/piyo/以下に置くなら2
private $paramLevel=1;

public function setSystemRoot($path)
{
$this->sysRoot = rtrim($path, '/');
}

/**
* URLの階層設定。どの階層からをパラメータとして解釈するか。
* @param int $iLevel
*/
public function setPramLevel($iLevel) {
$this->paramLevel=$iLevel;
}

public function dispatch()
{
$params_tmp = array();
//?で分割。GETパラータを無視するため
$params_tmp = explode('?', $_SERVER['REQUEST_URI']);
// パラメーター取得(末尾,先頭の / は削除)
$params_tmp[0] = ereg_replace('/?$', '', $params_tmp[0]);
$params_tmp[0] = ereg_replace('^/*', '', $params_tmp[0]);
$params = array();
if ('' != $params_tmp[0]) {
// パラメーターを / で分割
$params = explode('/', $params_tmp[0]);
}

// 1番目のパラメーターをコントローラーとして取得
$controller = "index";
if ($this->paramLevel < count($params)) {
$controller = $params[$this->paramLevel];
}

// パラメータより取得したコントローラー名によりクラス振分け
$className = ucfirst(strtolower($controller)) . 'Controller';

// クラスファイル読込
require_once $this->sysRoot . '/controllers/' . $className . '.php';

$url ="/";
for ($i = 0; $i < $this->paramLevel; $i++) {
$url = $url . $params[$i] . "/";
}
// クラスインスタンス生成
$controllerInstance = new $className($url);

// 2番目のパラメーターをコントローラーとして取得
$action= 'index';

if ( ($this->paramLevel + 1) < count($params)) {
$action= $params[($this->paramLevel + 1)];
}
// アクションメソッドを実行
$actionMethod = $action . 'Action';
$controllerInstance->$actionMethod();

}
}

?>



xxxController.php
各コントローラのクラスファイルです。
ここで、モデル、ビューへの制御を行います。

<?php
require_once( "Request.php" );
require_once( 'model/HogeModel.php' );
require_once('Smarty.class.php');

class HogeController
{

//リクエスト
private $request;
//モデル
private $model;
//ビュー(Smartyのインスタンス)
private $view;
//ビューで表示するURL
private $url;

// コンストラクタ
public function __construct($url)
{
// リクエスト
$this->request = new Request();
//モデルをインスタンス化(コントローラと1:1のパターン)
$this->model = new HogeModel();
//ビューインスタンス化
$this->view = new Smarty();
//Smartyのディレクトリ設定(キャッシュやテンプレート置き場など)
$this->view->template_dir = "smarty/templates";
$this->view->compile_dir = "smarty/templates_c";
$this->view->cache_dir ="smarty/cache";
//Smartyテンプレートにセットするパス
$this->url = $url;
//HTMLから参照すべき外部ファイルのパス設定(URLを/区切りにするとパスが変わるため)
$this->view->assign("url",$this->url);
}

public function indexAction()
{

//http://hoge.jp/eigyou/hoge/ アクセス時の処理
//モデル($this->model )の任意のメソッドを実行。
//画面表示
$this->view->display("hoge_index.tpl");
}
public function dispguestAction(){
//http://hoge.jp/eigyou/hoge/dispguest/ アクセス時の処理
//モデル($this->model )の任意のメソッドを実行。
//画面表示
$this->view->display("hoge_disp.tpl");
}

}
?>



xxxModelクラス.php
各モデルのクラスファイルです。
このクラス内でDBにアクセスしたりと、メインロジックを書いて行きます。

<?php

class HogeModel
{
//各処理毎にメソッドを作成。
}
?>



リクエスト
ブラウザから送信されるリクエストですが、これもクラス化してやります。
詳しいコードは、(PHP)MVCモデルを使ったPHPアプリケーション(リクエスト部分)を参照にしてください。


コントローラからリクエストを取得するには下記のようにします。

$this->request->getPost("パラメータ名");
$this->request->getPost(); //とすると、全POST情報を取得できます。



ビュー
ビューは前述のとおり、テンプレートエンジンであるSmartyを使います。
コントローラにSmartyのインスタンスを作成し、テンプレートを指定して表示するという方法です。
Smartyについては大量に情報が出まわってますし、3流PGのメモ書きにもちょこっと書いてるのでそのあたりが参考になるかもです。


さて、こう考えると結構簡単にMVCモデルって作れるんですね。
オブジェクト指向的には、コントローラやモデルクラスでベースクラスに汎用処理埋め込み、それを継承して各クラス別の処理を書くのが理想なんでしょうが、今回はMVCの基本的な部分だけということなので、以上です。

参考先には、継承をつかった話も書いているので、見てみるといいかもしれません。
[PR]
by Jehoshaphat | 2012-11-25 23:03 | PHP開発 | Trackback | Comments(0)