YUI2.7.0+PHP5でメニューを自作する(その1)
YUI2.7.0とPHPを使って、以下のようなシンプルなメニューを作ってみたい。YUIに付属するメニューは、ちょっと好きになれない。
- ログインしたユーザーに応じて、メニューの内容を変える。
- 単純なツリー形式にする。
- 画面にオーバーレイして出現する。
第1回目は、まず、最初の項についてプログラムを作ってみた。
「ユーザーに応じて」と書いたが、「ユーザーのロールに応じて」というのがありがちと思うので、まず、先のログインのサンプルで用いたusers.txtに「ロール」を追加した。
dummy@dummy.com,password,admin
これに応じて、先日のログで作成した、users.txtのためのPHPクラスを修正した。
<?php /** * LoginTextDao.class.php * * (C) 2009, tetsuya.odaka(EzoGP). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * users.txtのためのDao * * author ; t.odaka * date ; 2009/5/7 * * update ; t.odaka users.txtへのRoleの追加による * */ require_once('BaseTextDao.class.php'); class LoginTextDao extends BaseTextDao { /* * プロパティー */ var $Email, $Password, $Role; /* * デフォルトのコンストラクタ */ function __construct() { parent::__construct(); } /* * Getter */ function getEmail(){return $this->Email;} function getPassword(){return $this->Password;} function getRole(){return $this->Role;} /* * Setter */ function setEmail($_str){$this->Email = $_str;} function setPassword($_str){$this->Password = $_str;} function setRole($_str){$this->Role = $_str;} /* * findByUniqueKey * 主キーをもとに、データを取得する。 * パラメータ * $_fp : this->FileNameのファイルポインタ * 戻り値 : 見つかったらLoginTextDaoオブジェクト、なかったらnull. */ function findByUniqueKey($_fp, $_key){ while($_rarray = fgetcsv($_fp,1024)){ if($_rarray[0] == $_key){ $_retObj = new LoginTextDao(); $_retObj->setEmail($_rarray[0]); $_retObj->setPassword($_rarray[1]); $_retObj->setRole($_rarray[2]); return $_retObj; } } return null; } } ?>
前準備が終わったところで、スナップショット。以下は初期画面。
ログインした後は、そのログインユーザーのロールに応じたメニューを取得するようにする。メニューの内容はMarkup(リストとアンカー)で記述して、「ロール.txt」の名前でmenuディレクトリ下におく。ログイン前にメニューを表示する、ロールに応じたメニューの取得に失敗した場合にそなえて、default.txtというメニューファイルをおくことにした。以下は、default.txt。
<ul> <li>DefaultList 0 <ul> <li>List 0-0 <ul> <li>item 0-0-0</li> <li>item 0-0-1</li> </ul> </li> <li>item 0-1 <ul> <li><a target="_new" href="http://www.yahoo.co.jp" title="yahoo">Yahoo!</a> <ul> <li>item 0-1-0</li> <li>item 0-1-1</li> </ul> </li> </ul> </li> </ul> </li> </ul>
上にあるように、dummy@dummy.comには「admin」ロールを割り当てた。menu/admin.txtの内容は以下の通り。
<ul> <li>AdminList 0 <ul> <li>List 0-0 <ul> <li>item 0-0-0</li> <li>item 0-0-1</li> </ul> </li> </ul> </li> <li>item 0-1 <ul> <li><a target="_new" href="http://www.google.co.jp" title="google">Google</a> <ul> <li>item 0-1-0</li> <li>item 0-1-1</li> </ul> </li> </ul> </li> </ul>
以下は、dummy@dummy.comでログインする前に、Menuをクリックした際のスナップショット。このサンプルでは、「ロールごとのメニューを取得して、クライアントにフィードする」ことに主眼をおくので、画面下方に取得したメニューを表示する。
以下は、ログイン画面でdummy@dummy.comでログイン後、メニューを表示したもの。
以下にプログラムを掲載する。ここで作ったプログラムは3つ。
指定されたファイルを取得し、文字列として返却する | TextPickup.class.php |
Menuの表示要求をうけて、クライアントのログイン情報をもとに、Menu情報をクライアントにフィードする | getMenu1.php |
Menu取得のトリガーを引き、XHRで取得したメニューを表示する | test_menu1.html |
TextPickup.class.phpは、以前に作成した、BaseTextDao.class.phpをextendsして作成した。
<?php /** * TextPickup.class.php * * (C) 2009, tetsuya.odaka(EzoGP). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Textファイルをピックアップするのためのクラス * (注)ファイルのロック処理のため、呼び出し側から * ファイルポインタをもらうことを前提にする。 * * author ; t.odaka * date ; 2009/5/8 * */ require_once('BaseTextDao.class.php'); class TextPickup extends BaseTextDao { /* * デフォルトのコンストラクタ */ function __construct() { parent::__construct(); } /* * pickupText * 指定されたテキストファイルを取得して、文字列にして戻す。 * パラメータ * $_fp : this->FileNameのファイルポインタ * 戻り値 : 文字列に変換して返却. */ function pickupText($_fp){ require("../Myznala/debugLog.php"); $_ret; while($_data = fgets($_fp,1024)){ $m_log->debug('$_data: '.$_data); // Debugログ $_ret .= $_data; } $m_log->debug('$_ret: '.$_ret); // Debugログ return $_ret; } } ?>
以下は、getMenu1.php。
<?php /* * メニューの取得を行う * メニューは、menu/下にユーザーロール別に存在する前提です。 * * author ; t.odaka * date ; 2009/5/7 */ require_once("TextPickup.class.php"); require_once("LoginTextDao.class.php"); // セッションの開始 session_start(); // SESSIONにEMailアドレスがあったらロールを取得する。 if (isset($_SESSION['Email'])) { $pObj = new LoginTextDao(); $pObj->setFileName('data/users.txt'); // users.txtをopen. $fp = $pObj->fileOpen('r'); $retObj = $pObj->findByUniqueKey($fp, $_SESSION['Email']); $pObj->fileClose($fp,'r'); if($retObj == null) $role = 'default'; $role = $retObj->getRole(); }else{ $role = 'default'; } // 取り出すメニューの名称 $_menu = 'menu/'.$role.'.txt'; if(!file_exists($_menu)) $_menu = 'menu/default.txt'; // テキストの取り出し $ret = null; $tObj = new TextPickup(); $tObj->setFileName($_menu); $fp = $tObj->fileOpen('r'); $ret = $tObj->pickupText($fp); $tObj->fileClose($fp,'r'); // 出力 header("Content-Type:text/html"); echo($ret); return; ?>
最後にJavascriptを含むHTMLの全文を示す。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no-cache"> <meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT"> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>Login</title> <style type="text/css"> </style> <link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/fonts/fonts-min.css" /> <script type="text/javascript" src="../scripts/lib/yui/build/yahoo-dom-event/yahoo-dom-event.js"></script> <script type="text/javascript" src="../scripts/lib/yui/build/connection/connection-min.js" ></script> <style type="text/css" id="defaultstyle"> #main { margin: 2px; padding: 3px; } .ez_error { /* red(エラー用) */ color:#ff0000; } </style> <script type="text/javascript"> DisplayMenu = function() { var Event = YAHOO.util.Event; var Dom = YAHOO.util.Dom; /* * メニューリンクをクリックしたときのハンドラ */ var menuClickHdlr = function(){ // メッセージのクリア Dom.get('msg').innerHTML = ''; Dom.get('res').innerHTML = ''; var _url = 'getMenu1.php'; var _arg ={ 'errId' : 'msg', 'resId' : 'res' }; menuCallback.argument = _arg; // ajaxで検証 YAHOO.util.Connect.asyncRequest('POST',_url, menuCallback); } /* * メニュー取得時のコールバック */ var menuCallback = { success : function(_obj) { var _resId = _obj.argument.resId; var _errId = _obj.argument.errId; // XHRの戻り値の取得(メニュー文字列) var _ret = _obj.responseText; // メニューの表示 if(_ret.length > 0){ Dom.get(_resId).innerHTML = _ret; }else{ // エラーのハンドル(皆さん適当に) Dom.get(_errId).innerHTML = 'メニューの取得に失敗しました.'; } }, failure : function(_obj) { var _errId = _obj.argument.errId; var _ret = 'ステータス: ' + _obj.status + 'ステータステキスト: ' + _obj.statusText + ' メニューの取得に失敗しました。'; // エラーのハンドル(皆さん適当に) Dom.get(_errId).innerHTML = _ret; } }; return{ init: function() { // ダイアログを表示するハンドラー Event.on("menu", "click", menuClickHdlr); } }; }(); //DOMが完全にloadされたら、サンプルを初期化する。 YAHOO.util.Event.onDOMReady( //DomReadyイベントで発火するハンドラ DisplayMenu.init, //ハンドラに渡すオブジェクト DisplayMenu, //ハンドラは、上記のオブジェクトのスコープをもつ。 true ); </script> </HEAD> <BODY class="yui-skin-sam"> test_menu1.html <br> <div id="container"> <p> ユーザーのロールに基づいてMenuを取得するサンプルです。<br/> </p> <a id="menu" href="#" class="my_menu">Menu</a> <div id="msg" class=".ez_error"></div> <div id="res"></div> </div> </BODY> </HTML>