タグ:PHP ( 68 ) タグの人気記事
(PHP)require,includeで相対パスのファイルを指定する場合

今更な話ですが、require , require_once , include , include_once で別ファイルを読み込む時に相対パスを使う時の注意点です。

PHPには、実行したファイルのあるディレクトリがカレントディレクトリになるというルールがあるようです。また、ファイルインクルードの順番ですが、まず指定されたパス→include_path→現在の作業ディレクトリとなるようです。

なので、一旦絶対パスを取得してからファイル名を指定するといいようです。

require_once dirname(__FILE__) .'/util.php' ; //php5.3.0より前のバージョン
require_once __DIR__ .'/util.php' ; //php5.3.0以降のバージョン



参考:
PHPでincludeの時、ファイルパスの指示の仕方。 | WEBデザイン&WEBプログラミング -sei2の日記-
PHP の include, require で相対パスを指定して読み込む場合のメモ - hoge256ブログ
PHP include時のパス解決方法
PHP で 外部ファイルを include したり require する場合は 絶対パスで指定するべきなんだって
[PR]
by Jehoshaphat | 2013-03-19 21:34 | PHP開発 | Trackback | Comments(0)
(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)
(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)
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)
(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)
(PHP)MVCモデルを使ったPHPアプリケーション(リクエスト部分)
(PHP)MVCモデルを使ったPHPアプリケーションのリクエスト部分のソースです。

GET,POSTで送られてくるリクエストをオブジェクトとして扱えるようクラス化します。
参考先まるままですが、こんな感じ。

Request.php
コントローラからはこのクラスを呼び出し、リクエストにアクセスします。

<?php
 
require_once( "QueryString.php" );
require_once( "Post.php" );
class Request
{
// POSTパラメータ
private $_post;
// GETパラメータ
private $_query;

// コンストラクタ@
public function __construct()
{
$this->_post = new Post();
$this->_query = new QueryString();
}
 
// POST変数取得
public function getPost($key = null)
{
if (null == $key) {
return $this->_post->get();
}
if (false == $this->_post->has($key)) {
return null;
}
return $this->_post->get($key);
}
 
// GET変数取得
public function getQuery($key = null)
{
if (null == $key) {
return $this->_query->get();
}
if (false == $this->_query->has($key)) {
return null;
}
return $this->_query->get($key);
}
}
?>



RequestVariables.php
リクエストの変数を抽象化するためのクラスです。
<?php
 
// リクエスト変数抽象クラス
abstract class RequestVariables
{
protected $_values;
 
// コンストラクタ
public function __construct()
{
$this->setValues();
}
 
// パラメータ値設定
abstract protected function setValues();
 
// 指定キーのパラメータを取得
public function get($key = null)
{
$ret = null;
if (null == $key) {
$ret = $this->_values;
} else {
if (true == $this->has($key)) {
$ret = $this->_values[$key];
}
}
return $ret;
}
 
// 指定のキーが存在するか確認
public function has($key)
{
if (false == array_key_exists($key, $this->_values)) {
return false;
}
return true;
}
}
?>



Post.php
POST変数を抽象化します。
<?php
require_once( "RequestVariables.php" );
// POST変数クラス
class Post extends RequestVariables
{
protected function setValues()
{
foreach ($_POST as $key => $value) {
$this->_values[$key] = $value;
}
}
}
?>



QueryString.php
GET変数を抽象化します。
<?php
require_once( "RequestVariables.php" );
 
// GET変数クラス
class QueryString extends RequestVariables
{
protected function setValues()
{
foreach ($_GET as $key => $value) {
$this->_values[$key] = $value;
}
}
}
 
?>

[PR]
by Jehoshaphat | 2012-11-25 23:03 | PHP開発 | Trackback | Comments(0)
(Ajax,PHP)Ajaxを使って入力フォームに戻ったときに値を再セットする
(PHP)セッションを使ってて入力フォームページに戻ると入力内容がクリアされる(PHP)Smarty利用時に入力チェックエラー時に入力画面に戻し入力データを再表示する方法と関係のある話になります。

今回、[Rails] Ajaxによる入力と、"戻る"ボタン対策 : 篳篥日記を参考にさせてもらいました。

要は、入力画面で入力した値をセッション変数に保存→入力画面に戻ったらAjaxリクエストによってセッション変数に保存した値をJSONで取ってきてフォームに再セットという流れです。

この手法はページ全体をAjax化してなくても、ページ毎にURLが変わる典型的なWEBページでも使うことができると思います。


以下にサンプルコードを載せますが、AjaxはjQueryライブラリ、サーバサイドはPHP、テンプレートエンジンはSmartyを使っています。(文字数制限のためハイライトはOFFです)

●test_inputdataset.php
最初に表示する入力フォームを表示するPHPスクリプトです。
Smartyを使って基本のページテンプレートを呼び出します。

<?php
//最初に表示される入力フォームのページ
session_start(); //セション開始
require 'smarty/libs/Smarty.class.php';
$smarty = new Smarty;
$smarty->display("test_input_page.tpl");
?>


●test_input_page.tpl
ページのSmartyテンプレートです。
最初に表示されたときは、入力フォームテンプレートである、test_input_form.tplを読み込みます。

<html>
<head>
<title>入力テスト</title>
<script type="text/javascript" src="jquery-1.6.2.js">
</script>
<script type="text/javascript" src="test_input.js">
</script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="body">
{include file="test_input_form.tpl"}
</div>
</body>
</html>


●test_input_form.tpl
入力フォームのテンプレートです。

<form method="post" id="input">
氏名:<input type="text" id="name" name="name" ><br>
電話:<input type="text" id="tel" name="tel" ><br>
年齢:<input type="text" id="age" name="age" ><br>
<select id="hoge" name="hoge">
<option value="1">1 : hoge1</option>
<option value="2">2 : hoge2</option>
<option value="3">3 : hoge3</option>
</select>
<input type="button" value="送信" onclick="return SendData()">
</form>



●test_input_form.tpl
確認画面のテンプレートです。
戻るボタン押下時に、backInputPate() 関数を実行します。

確認画面<br>
氏名:{$name}<br>
電話:{$tel}<br>
年齢:{$age}<br>
選択:{$sel}<br>
<input type="button" value="戻る" onclick="return backInputPate()">



●test_input_preview.php
確認画面を表示するためのPHPです。
入力フォームから渡された値をセッション変数に保存します。(

<?php
session_start();

$input_data_ary = $_POST;
//入力フォームから渡されたデータをセッション変数に保存
$_SESSION["input"] = $input_data_ary;

require 'smarty/libs/Smarty.class.php';
$smarty = new Smarty;
$smarty->assign("name",$input_data_ary["name"]);
$smarty->assign("tel",$input_data_ary["tel"]);
$smarty->assign("age",$input_data_ary["age"]);
$smarty->assign("sel",$input_data_ary["sel"]);
$smarty->display("test_input_preview.tpl");
?>



●test_input_getjson.php
セッションに保存された値をJSON形式で返すPHPです。
(セッションがない場合はnullが返ります。)
PHPの配列をJSONにするjson_encode関数はPHP5.2以降で使えるようですね。

<?php
//セッションに保存された入力フォームの値をJSON形式で返す
session_start();
if ( isset($_SESSION["input"]) ){
echo json_encode($_SESSION["input"]);
return;
}
?>



●test_input.js
入力フォームで動くJavaScriptです。
入力フォーム表示時に、Ajaxを使って入力済みのデータがあるかどうか問合せます。
データがあればJSONで返ってくるので、フォームに値をセットします。

/**
* ページロード時に動くjQuery処理
*/
$(function(){
//確認画面から戻ったときに値を入力フォームにセットする
SetValue();
});


/**
* 入力データの値をJSONでもらい、フォームにセットする
*/
function SetValue(){
$.getJSON( //jQueryを使ってJSONデータ取得
"test_input_getjson.php", //アクセス先
function(data,status){ //dataにJSONデータが入っている。
if ( data ){
for (var key in data) {
$("*[name=" + key + "]").val(data[key]) ;
}
}
}
);
}

/**
* 戻るページボタンを押下した時に動かすメソッド
* Ajaxを使い、ページそのままでコンテンツのみ変更。
*/
function backInputPate(){
$.ajax({
type: "GET",
url: "test_inputdataset.php",
beforeSend: function(xhr) {
xhr.setRequestHeader("Ajax-Request", "true");
},
success: function(response) {
//$("#body").empty();
$("#body").html(response);

}
});
return false;

}


/**
* 送信ボタンを押下した時に動かすメソッド
* Ajaxを使い、ページそのままでコンテンツのみ変更。
*/
function SendData(){
var form = $("form#input");
$.ajax({
type: "POST",
url: "test_input_preview.php",
data: $(form).serialize(),
dataType: "text",
beforeSend: function(xhr) {
xhr.setRequestHeader("Ajax-Request", "true");
},
success: function(response) {
$("#body").html(response);
/*もし動的にJSを読み込みたい時は以下のようのすればよろし
$.getScript("../findmail_check.js", function(){
alert("読み込み完了");
});*/
}
});
return false;
}



数年ぶりにJSONを使ったのですっかり仕様を忘れていました。
参考サイトのおかげで何となく思い出すことができました。

参考:
逆引きjQuery:非同期でJSON形式のデータを取得するには? - @IT
jQueryクライアントとPHPサーバ間をJSONで結ぶには (3/3) ─ @IT
jQueryでjsonデータを扱ってみる【入門編】 | webOpixel
JSONをjQueryで扱う方法 : ずっと工事中
PHPでJSON形式の出力 - TRAJECTORY.JP -
phpで、json_encodeした配列に、json_decodeするとオブジェクトで返って来てしまう - カサヒラボ
[PR]
by Jehoshaphat | 2012-11-17 19:30 | PHP開発 | Trackback | Comments(0)
(PHP,Ajax)SmartyでAjaxを使用する
Smartyを利用しながらページ遷移をAjaxでシームレスに行ってみることにしました。

参考にしたのはAjax と Smarty: 第 1 回 Smarty を使って Ajax アプリケーションを開発するです。

若干ややこしかったので、自分なりに簡易にしてみました。

具体例として、ログイン画面→ログイン後のマイページ をAjaxで遷移するコードを書いてみました。
(ログイン失敗のメッセージもAjaxでページ遷移せずに表示します)

まず、ページのSmartyテンプレートです。
基本的にこのテンプレートをどのページでも使い続け、テンプレート内の demo_div 内をページによって書き換えていきます。(文字数制限のためハイライトOFFです)

●demo_page.tpl (Smarty ページテンプレート)

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js">
</script>
<script type="text/javascript" src="demo_js.js">
</script>
</head>
<body>
test<br>
<div id="demo_div">
{include file="demo_form.tpl"}
</div>
</body>
</html>

demo_div 内には、最初に表示するテンプレートをインクルードします。


●demo_form.tpl (Smartyテンプレート)

<form method="POST" id="demo_form" >
<input type="hidden" name="mode" value="{$mode}" >
<table border="0" cellpadding="5" cellspacing="0">
<tr>
<td>ユーザ名</td><td><input type="text" id="user" name="user"></td>
</tr>
<tr>
<td>パスワード</td><td><input type="text" id="pass" name="pass"></td>
</tr>
{if $auth_err}
<tr><td colspan="2">ログイン情報に誤りがあります。</tr>
{/if}
</table>
<button type="submit" onclick="return submitDemoForm()">ログイン</button>
</form>

ログイン用の情報を入れるテキストボックスです。最初に、demo_page.tpl に表示されるテンプレートです。
ログインに失敗した場合、$auth_err に true がはいり、エラーメッセージを表示します。


●demo_mypage.tpl (Smartyテンプレート)

<hr>
<span styke="color:brue;">ログイン</span>が完了しました。<br>
ページ遷移なしでコンテンツが切り替わりました。<br>
更新ボタンを押下すると、ログイン画面に戻ってしまうので、セッション変数を上手く使うなど対策が必要。<br>
<hr>

ログインが成功すると demo_page.tpl に表示されるテンプレートです。


つぎに、PHPファイルです。
クライアントはこのPHPにアクセスし、どのページを表示するかのmodeに基づいて処理を割り振ります。(MVCのコントローラみたいな感じですね)
今回はすべてこのPHPファイルにアクセスしていますが、別にページ毎にPHPファイルを作ってもかまいません。(ただしクライアントに表示されるURLは最初にアクセスしたページのままです。)

●demo_html.php (PHP)

<?php
header("Cache-Control: no-cache");
header("Pragma: no-cache");

require 'smarty/libs/Smarty.class.php';

$smarty = new Smarty;
$smarty->compile_check = true;
$smarty->debugging = false;
$smarty->force_compile = 1;
//Smartyのディレクトリ設定(キャッシュやテンプレート置き場など)
$smarty->template_dir = "smarty/templates";
$smarty->compile_dir = "smarty/templates_c";
$smarty->cache_dir ="smarty/cache";

//$mode変数にどの画面を表示するかの値を持たす。
$mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : "default";
//どの画面を表示するか判定。
switch ($mode){
case "login":
//ログイン処理を行う
auth($smarty);
return;
break;
default:
//デフォルトの場合、ページテンプレートを表示
$smarty->assign("mode", "login");
$smarty->assign("auth_err", false);
$smarty->display('demo_page2.tpl');
break;
}

function auth($smarty){
//認証処理
if ( $_POST["user"] != "hoge" || $_POST["pass"] != "hoge" ){
//認証失敗。ログインページテンプレートを表示。
$smarty->assign("mode", "login");
$smarty->assign("auth_err", true);
$smarty->display('demo_form2.tpl' );
return;
}
mypageDisp($smarty);
}

function mypageDisp($smarty){
//認証OK メインコンテツ表示
$smarty->assign("mode", "mypage");
$smarty->display('demo_mypage.tpl');
return;
}
?>



最後に、JavaScriptのファイルです。
jQueryライブラリを使ってAjaxを用います。
●demo_js.js

function submitDemoForm() {
//form要素を選択
var form = $("form#demo_form");
//ajaxで別ページをロード
$.ajax({
type: "POST",
//formにaction属性あればその値にページ遷移、なければ今と同じページ表示
url: form.attr("action") ? form.attr("action") : document .URL,
data: $(form).serialize(),
dataType: "text",
beforeSend: function(xhr) {
//ヘッダに追加
xhr.setRequestHeader("Ajax-Request", "true");
},
success: function(response) {
//ajax通信が完了後、レスポンスしたデータを表示。
$("#demo_div").html(response);
}
});
return false;
}

Ajaxで POST データを submit する時ですが、jQueryの $("form").submit(function(){ }); のイベントは捕まえられないようです。
[PR]
by Jehoshaphat | 2012-11-17 19:16 | PHP開発 | Trackback | Comments(0)
(HTTP,PHP)httpsからhttpへのリファラは送信されない!?
PHPで Referer を取得しようとするんですが、https のサイトからリンクすると、"Notice: Undefined index: HTTP_REFERER "エラーになってしまいます。

で、調べた結果 https から http へアクセスした場合、Referer は送信されないんですね。
知りませんでした。

ちなみに、PHPだとリファラがないと、$_SERVER['HTTP_REFERER'] 自体が存在しないため、上記のエラーとなります。
PHPでサーバ変数とか使うときは、以下のように変数が存在するかどうかをチェックしてから値を使うようにしたほうが良いですね。
$referer = ( isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "");

参考:
[INFO] セキュリティ保護されていない状況で Internet Explorer から Referer ヘッダーを送信しない
nitoka blog: https://ページからhttp://ページへのリンクした場合リファラーは送出されない
[PR]
by Jehoshaphat | 2012-11-12 21:52 | PHP開発 | Trackback | Comments(0)