忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2024/05/19 23:36 |
ZF1.11 ZendX_JQuery
PHPをJQueryと連携できるようになります。
例によって日本語情報が全然ありませんので手探りで使ってみます。

jQuery自体についてはVer1.4.0以降更新が滞っていますがこちらのサイトが非常にわかりやすいです。
しかしZendX_JQueryが対応しているのは1.5.2以降のようです。残念。

さて、とりあえずインストール…ってところでいきなり躓いた。

なにしろリポジトリに置いてなければPearチャンネルにもない。

どういうことだと探し回ってみればこんなエントリを発見。

パッケージをダウンロードするとextras/libraryディレクトリ内にあるそうな。なんでだよ。

さて、extras/library/ZendX/JQueryは無事に見つかりました。
ついでにZendX/ConsoleとかZendX_Db_Adapter_Firebirdとか見つかりました。
そもそもZendXってなんだ?

http://framework.zend.com/manual/ja/coding-standard.naming-conventions.html
> Zend Framework 追加ライブラリの最上位レベルのディレクトリは "ZendX/" ディレクトリです。

うむ、意味がわからん。

ちなみにリポジトリでは違うディレクトリに置いてありました。

とりあえずPear/Zendディレクトリと並列にZendXディレクトリを配置。
これだけで最低限動作するはずです。
<?php
	
	//インクルード
		require_once('Zend/Form.php');
		require_once('ZendX/JQuery/Form.php');
		require_once('ZendX/JQuery/Form/Element/Slider.php');
		require_once('ZendX/JQuery/Form/Element/DatePicker.php');
	
	//Zend_Form
		$form = new ZendX_JQuery_Form();
		
		//スライダー
			$slider = new ZendX_JQuery_Form_Element_Slider('slider1', array('label' => 'Slider:'));
			$slider->setJQueryParams(array('defaultValue' => '75'));
			$form->addElement($slider);
		
		//日付選択
			$datepicker = new ZendX_JQuery_Form_Element_DatePicker('dp1', array('jQueryParams' => array('defaultDate' => '2007/10/10')));
			$form->addElement($datepicker);

	//出力
		print($form->__toString());

> Warning: Exception caught by form: UiWidgetElement decorator cannot render without a registered view object

お?

実はZendX_JQueryはZend_Viewが必須となっており、ZendX_JQuery単体あるいはZend_Formとだけ組み合わせるということができません。
というかZend_FormがZend_Viewを必要としています。
なんて迷惑な。

後半の出力部分を変更。
	//出力
		require_once('Zend/View.php');
		$view = new Zend_View();
		$view->addHelperPath("ZendX/JQuery/View/Helper", "ZendX_JQuery_View_Helper");
		print($form->render($view));
<form enctype="application/x-www-form-urlencoded" action="" method="post"><dl class="zend_form">
<dt id="slider1-label"><label for="slider1" class="optional">Slider:</label></dt>
<dd>
<div options="" id="slider1-slider"></div></dd>
<dt id="dp1-label"> </dt>
<dd>
<input type="text" name="dp1" id="dp1" value=""></dd></dl></form>
あれ?
jQueryParamsどこいった?

必要な要素が出力されないため、これでは使う意味がありません。
どうも使い方がわかりません。
誰か教えてください。
PR


2011/09/26 22:56 | Comments(0) | TrackBack() | PHP
ZF1.11 Zend_Db_SelectのorWhere()の例がどうかしてる件
http://framework.zend.com/manual/ja/zend.db.select.html

>  例19 orWhere() メソッドの例
> $select = $db->select()
>  ->where('price < ?', $minimumPrice)
>  ->orWhere('price > ?', $maximumPrice);


これはよくある作りで問題無い。

> 例20 論理式を括弧で囲む例
> $select = $db->select()->where("price < $minimumPrice OR price > $maximumPrice")


なんでいきなりベタ書きになってんだよ。
$db->select()->where("price < ? OR price > ?", array($minimumPrice, $maximumPrice))
って書くべきだろそこ。

ちなみにZend_Db_Selectでは"SELECT * FROM hoge WHERE A AND (B OR C)"というSQLが普通には作れません。
$db->select()->where('A')->where('(B')->orWhere('C)');
とアクロバティックな書き方をする必要があります。

なんで?


2011/09/16 22:45 | Comments(0) | TrackBack() | PHP
ZF1.11 Zend_Loaderでオートローダー
機能が似ていることもあり、Zend_Loaderからspl_autoload_register()を操作することができます。

http://framework.zend.com/manual/1.11/ja/zend.loader.load.html
> Autoloader の使用法
> そのコールバックメソッドが Zend_Loader::autoload() です。
> 利便性を考慮して、 Zend_Loader では registerAutoload() 関数を提供しています。


って書いてあるんだけど実際registerAutoload()には
public static function registerAutoload($class = 'Zend_Loader', $enabled = true)
   trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0;
    use Zend_Loader_Autoloader instead', E_USER_NOTICE);
}
って書いてあります。
よってZend_Loader_Autoloaderを使ってみたいと思いますが、マニュアルが和訳されていないので手探りでやってみます。
<?php
	//オートロード用関数
	function autoload1($className){
		class AutoLoad1{}
	}
	
	//Zend_Loader_Autoloader
		require_once('Zend/Loader/Autoloader.php');
		$autoLoader = Zend_Loader_Autoloader::getInstance();
	
	//ZFのパスをセット
		$autoLoader->setZfPath('C:\xampp\php\PEAR','1.2.2');
	
	//NotFoundエラーの発生抑止
		$autoLoader->suppressNotFoundWarnings(true);
	
	//pushAutoloader
		$autoLoader->pushAutoloader('autoload1');
	
	//オートロード
		new Zend_Filter_Word_DashToSeparator('/');
		new AutoLoad1();
実はZend_Loader_Autoloader::getInstance()した時点でZendフレームワークについては自動的にオートロードが適用されます。
今後、前回までのようにZend_Loader::loadClass($className)を書く必要はありません。
ただ何故かPearのクラスは適用範囲外になります。

setZfPath()はZendFrameworkのパスを指定します。
特徴的なのは第二引数を指定することで任意のバージョンをセットできるというところです。
過去バージョンでの動作確認などを簡単に行えます。
ただ何故かディレクトリ名の許容範囲がやたらと狭く、例のような引数を与えた場合、ディレクトリ名が
"C:\PEAR/ZendFramework-1.2.2/library"あるいは"C:\PEAR/1.2.2-minimal"のような形に勝手に決まってしまいます。
http://framework.zend.com/manual/1.11/ja/zend.loader.autoloader.html#zend.loader.autoloader.zf-version
任意のパスを登録することができません。
何故だ。

pushAutoloader()でオートロード用関数を登録します。
http://framework.zend.com/manual/1.11/ja/zend.loader.load.html#zend.loader.load.autoload
使い方は基本的にspl_autoload_register()と同じです。

どうもいまいち便利なのかよくわからないクラスだ。
普通に使う分にはspl_autoload_register()のほうが手っ取り早いので、あくまでsetZfPath()を使用しての開発用・動作検証用というスタンスのクラスではないかと思われます。


2011/09/12 23:41 | Comments(0) | TrackBack() | PHP
ZF1.11 Zend_Loader
Zend_ValidateZend_Filterで静的呼び出しを行った際、該当のファイルを自力でインクルードしなくても勝手に対応するクラスがインクルードされていました。

そのインクルードを行っている実体がZend_Loaderです。
まあやってることは_を/にしてインクルードしてるだけです。
<?php
	//Zend_Loader
	require_once('Zend/Loader.php');
	
	//任意のクラスをロード
	Zend_Loader::loadClass('Zend_Cloud_QueueService_Adapter_ZendQueue');
	Zend_Loader::loadClass('Spreadsheet_Excel_Writer_Worksheet');
	
	//インクルードパスを指定してロード
	Zend_Loader::loadClass('Hoge_Fuga_FooBar', '../');
	$hogeFugaFooBar = new Hoge_Fuga_FooBar();
ファイル名およびクラス名はPearの命名規約に沿っている必要があります。
例えば引数として'Zend_Cloud_QueueService_Adapter_ZendQueue'を与えると、'Zend/Cloud/QueueService/Adapter/ZendQueue.php'をインクルードしてクラス名'Zend_Cloud_QueueService_Adapter_ZendQueue'が存在するかまでをチェックします。
従って、ZendライブラリだけではなくPearライブラリもZend_Loaderでインクルード可能ですが、SymfonyのライブラリはPearの命名規則に沿っていないので読み出し不可能です。
また第二引数にパスを与えると、指定された場所からの相対ディレクトリのみをチェックします。

このファイル名の変換は先日やったZend_Filter_Word_UnderscoreToSeparator('/')そのままなのでこれを使っているのかと思いきや、全く使わずZend_Loader内で普通に自力で実装していました。
なんだそれ。


まあともかく、このようにZend_Loader::loadClass()にはクラス名をファイル名に変換する仕組みが備わっているのですが、実際このZend_Loaderを使用しているクラスを見てみると、

Zend_Validate
	$className  = ucfirst($classBaseName);
	$class = $namespace . '_' . $className;
	$file  = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
	if (Zend_Loader::isReadable($file)) {
		Zend_Loader::loadClass($class);
	}
Zend_Filter
	$className = $namespace . '_' . ucfirst($classBaseName);
	$file = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
	if (Zend_Loader::isReadable($file)) {
		Zend_Loader::loadClass($className);
	}
まずZend_Loader::isReadableでファイルが存在するか確認してからZend_Loader::loadClassでクラスを呼び出しています。
で、このZend_Loader::isReadableが引数として何故かクラス名ではなくファイル名を必要とするので、結局呼び出し側でも自力でクラス名→ファイル名の変換という同じ処理を行わないといけない果てしなく微妙な作り。


2011/09/09 23:09 | Comments(0) | TrackBack() | PHP
ZF1.11 Zend_Filterで命名規則変換
前回前々回Zend_Filterを紹介しましたが、実はリファレンスにはフィルタクラス群のリストに載っていない謎のクラス群が存在します。
Zend_Filter_Word_UnderscoreToDash、Zend_Filter_Word_CamelCaseToSeparatorなどZend_Filter_Word配下に属するクラス群です。

まあ謎と言っても実はインフレクタのほうに載ってるんですが。

しかしこの解説、何言ってるのか全然わからないのですが、簡単に言うと文字列変換を行うフィルタのようです。
で、インフレクタと文字列変換は実際は微妙に違う機能なのですが、リファレンスではまとめて解説されているせいでわかりにくくなっています。
ここではとりあえず文字列変換フィルタだけ使ってみます。

Zend_Filter_Wordクラス群は、キャメルケースやスネークケースといった命名規則を変換する専用のフィルタです。
<?php
	
	//キャメルケース
        $string='fooBarBazHogeFuga';
	
	//Zend_Filter
		require_once('Zend/Filter.php');
	
	//静的にフィルタを実行
		//キャメルケースからアンダースコアに
		Zend_Filter::filterStatic($string, 'Word_CamelCaseToUnderscore'); //「foo_Bar_Baz_Hoge_Fuga」になる
	
	//フィルタチェイン
		require_once('Zend/Filter/Word/CamelCaseToDash.php');
		require_once('Zend/Filter/Word/DashToSeparator.php');
		
		//フィルタチェインを作成
		$filterChain = new Zend_Filter();
		$filterChain
			->addFilter(new Zend_Filter_Word_CamelCaseToDash())	//キャメルケースから-に
			->appendFilter(new Zend_Filter_Word_DashToSeparator('/'));//-から任意のセパレータに
		
		$filterChain->filter($string);	//「foo/Bar/Baz/Hoge/Fuga」になる
やってることははZend_Filter::filterStatic($string, 'PregReplace', array('match'=>'#(?<=(?:[a-z0-9]))([A-Z])#','replace'=>'_\1'));なので不要といえばそのとおりですが、正規表現などをいちいち考えずに使用できるので楽です。

Zend_Filter_Wordクラス群には全部で12のクラスがあるので、使用目的によって使い分けるとよいでしょう。
変換内容はだいたいクラス名のとおりです。
・CamelCaseToDash
・CamelCaseToSeparator
・CamelCaseToUnderscore
・DashToCamelCase
・DashToSeparator
・DashToUnderscore
・SeparatorToCamelCase
・SeparatorToDash
・SeparatorToSeparator
・UnderscoreToCamelCase
・UnderscoreToDash
・UnderscoreToSeparator

ところでこのZend_Filter_Wordクラス群は抽象クラスZend_Filter_Word_Separator_Abstractを継承しているのですが、この抽象クラスZend_Filter_Word_Separator_Abstractクラスはなんと具象クラスZend_Filter_PregReplaceを継承しています。
こりゃ面白い、と思って試してみたらJavaでも普通に継承できました。


2011/09/05 22:45 | Comments(0) | TrackBack() | PHP
ZF1.11 Zend_Filterで既存の関数を利用
前回Zend_Filterでhtmlspecialchars()できるとか言いましたが、実はZend_Filter_HtmlEntitiesはあってもZend_Filter_HtmlSpecialcharsはありませんでした。
あれれ。

このような場合、Zend_Filterでは簡単にフィルタを追加することができます。

が、htmlspecialchars()のように既存の関数を呼ぶだけであればもっと手っ取り早い方法があります。
<?php
	//フィルタリングする文字列
        $string='<script>alert();</script>';
	
	//Zend_Filter
		require_once('Zend/Filter.php');
		require_once('Zend/Filter/Callback.php');
	
	//関数でフィルタを呼ぶ
		$filter = new Zend_Filter_Callback('htmlspecialchars',array(ENT_QUOTES, 'UTF-8'));
		$filter->filter($string);
	
	//静的にフィルタを実行
		Zend_Filter::filterStatic($string, 'Callback', array('htmlspecialchars',array(ENT_QUOTES, 'UTF-8')));
	
	//フィルタチェイン
		$filterChain = new Zend_Filter();
		$filterChain->addFilter(new Zend_Filter_Callback('htmlspecialchars',array(ENT_QUOTES, 'UTF-8')));
		$filterChain->filter($string);
Zend_Filter_Callbackは、引数に関数名もしくはクラス+メソッド名を与えることで、その関数を実行してくれます。
http://framework.zend.com/manual/1.9/ja/zend.filter.set.html#zend.filter.set.callback
上記例では3種類の呼び出し方を試していますが、いずれも最終的にhtmlspecialchars($string, ENT_QUOTES, 'UTF-8')が実行され、返り値は'&lt;script&gt;alert();&lt;/script&gt;'となります。

まあ関数ひとつで実行可能な変換をわざわざZend_Filterを通して実行する意味があるのかどうかわかりませんが。


2011/09/02 22:39 | Comments(0) | TrackBack() | PHP
ZF1.11 Zend_Filter
Zend_Filterは値のフィルタリングを行います。

Zend_Validateと違うのは、あちらはあくまで値のチェックを行うだけなのに対し、こちらは実際に値を処理するという点です。
まあ、htmlspecialchars()とかtrim()とか数値に変換したりといった操作を一元的に行えるクラスです。

使い方もZend_Validateとほぼ同じです。
filterStatic()メソッドで静的に実行できたり、フィルタチェインにはインクルードが必要なところまで同じです。
http://framework.zend.com/manual/ja/zend.filter.introduction.html
<?php
	
	//フィルタリングする文字列
        $string='ABC012<script>alert();</script>';
	
	//Zend_Filter
		require_once('Zend/Filter.php');
	
	//静的にフィルタを実行
		Zend_Filter::filterStatic($string, 'Alnum'); //「ABC012scriptalertscript」になる
		Zend_Filter::filterStatic($string, 'PregReplace', array('match'=>'/<script>/', 'replace'=>'script'));//「ABC012scriptalert();</script>」になる
	
	//フィルタチェイン
		//フィルタチェインはインクルードが必要
		require_once('Zend/Filter/Alpha.php');
		require_once('Zend/Filter/StringToLower.php');
		
		//フィルタチェインを作成
		$filterChain = new Zend_Filter();
		$filterChain
			->addFilter(new Zend_Filter_Alpha())
			->addFilter(new Zend_Filter_StringToLower());
		//実行
		$filterChain->filter($string);	//「abcscriptalertscript」になる
簡単にフィルタリングできました。

ちなみにfilterStaticの第三引数、'match''replace'には全然意味がなくて、配列の順番だけしか見ていません。
array('replace'=>'/<script>/', 'match'=>'script')って書いても全く同じ動作になります。
Zend_Filter_PregReplace自体にはif (array_key_exists('match', $options))みたいなことが書いてあるので直接呼び出せば連想配列が考慮されるのですが、Zend_Filter::filterStaticの呼び出し側がそこらへんを気にしないのでうっかり逆順に書いてたりすると事故ります。
微妙に残念。


2011/08/29 22:41 | Comments(0) | TrackBack() | PHP
Mantis1.2.5 Mantisのインストールでどん詰まった
とりあえずホストを切る。

hosts
	127.0.0.1 mantis.localhost
httpd.conf
	<VirtualHost *:80>
	    ServerName mantis.localhost
	    DocumentRoot "C:\hoge\fuga\mantis\htdocs"
	    ErrorLog "logs/mantis.localhost-error.log"
	    CustomLog "logs/mantis.localhost-access.log" combined
	</VirtualHost>
DBを作成。
	CREATE USER 'mantis'@'localhost' IDENTIFIED BY '***';
	GRANT USAGE ON * . * TO 'mantis'@'localhost' IDENTIFIED BY '***' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
	CREATE DATABASE IF NOT EXISTS `mantis` ;
	GRANT ALL PRIVILEGES ON `mantis` . * TO 'mantis'@'localhost';

Mantis本体を展開。
http://www.alles.or.jp/~sogabe/mantis/
のダウンロードからStableなreleaseを拾ってきます。
今回は1.2.5でした。
持ってきたらmantis\htdocsに解凍。
ちなみにmantis\htdocsと分けてますが、Mantisのファイルは全部DocumentRoot以下に置くのでmantis\には何もありません。

http://mantis.localhost/admin/check.php
にアクセス。

Checking your installation

Warning: The configuration option $g_ldap_port is now obsolete


please use $g_ldap_server instead.
Checking Config File Exists
Please use install.php to perform initial installation Click here

なんか途中で切れてるんだが。

http://mantis.localhost/admin/install.php
にアクセス。
Hostname (for Database Server) 'localhost'
Username (for Database) 'Mantis'
Password (for Database) 'Mantis'
Database name (for Database) 'Mantis'
Admin Username (to create Database if required) 'root'
Admin Password (to create Database if required) 'root'

Checking Installation...
Checking for register_globals are off for mantis GOOD
Attempting to connect to database as user GOOD
checking ability to SELECT records BAD
Database user doesn't have SELECT access to the database ( Table 'mantis.mantis_config_table' doesn't exist )
checking ability to INSERT records BAD
Database user doesn't have INSERT access to the database ( Table 'mantis.mantis_config_table' doesn't exist )
checking ability to UPDATE records BAD
Database user doesn't have UPDATE access to the database ( Table 'mantis.mantis_config_table' doesn't exist )
checking ability to DELETE records BAD
Database user doesn't have DELETE access to the database ( Table 'mantis.mantis_config_table' doesn't exist )
なんだこれ。
もちろんDBは空のまま。

config_inc.phpにはファイルができている。
<?php
	$g_hostname = 'localhost';
	$g_db_type = 'mysql';
	$g_database_name = 'mantis';
	$g_db_username = 'mantis';
	$g_db_password = 'mantis';
接続確認。
<?php
	$db = mysql_connect('localhost', 'mantis', 'mantis');
	mysql_select_db('mantis', $db);
	$result = mysql_query('SHOW GLOBAL STATUS');
	$ret=mysql_fetch_assoc($result);

	array(2) {
	  ["Variable_name"]=>
	  string(15) "Aborted_clients"
	  ["Value"]=>
	  string(1) "0"
	}
接続成功して権限もちゃんとある。
つまりMantisのどこかでおかしなことがおこっている。

もういちどhttp://mantis.localhost/admin/check.phpにアクセス。

APPLICATION ERROR #401

Database query failed. Error received from database was #1146: Table 'mantis.mantis_plugin_table' doesn't exist for the query: SELECT COUNT(*) FROM mantis_plugin_table WHERE basename=?.

Please use the "Back" button in your web browser to return to the previous page. There you can correct whatever problems were identified in this error or select another action. You can also click an option from the menu bar to go directly to a new section.


なんか悪化した。

調べてみようと思ったがソースが適当過ぎて中がどうなってるかさっぱりわからなかった。

悩んだあげくに
	CREATE USER ''@'localhost';
とかいうフリーダムに危険なユーザがいたのをなんとなく削除してみたら何故か動いた。
意味がわからん。


2011/08/06 01:00 | Comments(0) | TrackBack() | PHP
PHP5.3.5 PharDataクラスを使ってみる
前回の続き?

PharDataクラスは、Pharをextendsしているのでpharの関連機能かと思いきや、実はphar全く関係なしに使うことができる圧縮ファイル操作クラスで、どっちかというとZipArchiveの仲間です。
またPharのようにphp.iniを設定することなく使用することができます。

とりあえず適当なzipファイルに対して使用してみます。
<?php
	//コンストラクタ
		$pharData = new PharData('hoge.zip', 
			FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME
		);
	
	//zip内のファイルを順に辿る
	foreach($pharData as $key=>$val){
		//FilesystemIterator::KEY_AS_FILENAMEを指定しているので$keyはファイル名になる
		print($key);
		//FilesystemIterator::CURRENT_AS_FILEINFOを指定しているので$valはPharFileInfoクラスになる
		print(get_class($val));
	}
	
	//zipにファイル追加
		$pharData->addFile('mushroom.gif');
		$pharData->addFile('mushroom.gif', 'mushroom2.gif');
	
	//zipのファイル削除
		$pharData->delete('mushroom.gif');
		unlink('phar://hoge.zip/mushroom2.gif');
PharDataのコンストラクタの例にはCURRENT_AS_FILEINFOとかKEY_AS_FILENAMEとかいう謎の定数が書かれているのですが、これらは実際には定義されていません。

PharData extends Phar extends RecursiveDirectoryIterator extends FilesystemIteratorとなっており、FilesystemIterator::CURRENT_AS_FILEINFOとかFilesystemIterator::KEY_AS_FILENAMEとかのクラス定数が定義されているのでこれらを設定することができます。
http://www.php.net/manual/ja/class.filesystemiterator.php#filesystemiterator.constants

あとはPharData::addFile()で圧縮ファイルを解凍せずにファイルを追加したり、PharData::delete()で削除したりといった操作を簡単に行うことができます。


ちなみにforeachとかに使うインデックスはオブジェクト作成時に作成したらそのままらしく、addFile()後にループしても出てきません。
それはまだいいのですがdelete()後にforeachするとFatal errorになります。
Fatal error: Uncaught exception 'RuntimeException' with message 'Cannot access phar file entry '/hoge.gif' in archive 'C:/hoge.zip''

まあ正直素直にZipArchive使っておけば、という気がしないでもない。


2011/08/01 23:21 | Comments(0) | TrackBack() | PHP
PHP5.3 pharでWebアプリを作ってみた
前回はpharアーカイブをライブラリとして使用しましたが、実はpharアーカイブだけで完全な動作をするPHPプログラムを作成可能です。
この利用法、Phar::webPhar()あたりをよく読めば書いてあるのですが、物凄く便利っぽい機能にもかかわらず何故か何処にもこれを使ってみたという人が見あたらない不思議。

まあとりあえずでっちあげてみたのがこちら
http://blog.cnobi.jp/v1/blog/user/8f14c19eb01af9c2e80c7f2ad07dc8ca/1311957002

中身は昔作った超適当なフォームなのでソースの参考にしてはいけませんが、以下の3ファイルが入っています。

input.php
<?php
	//初期化
		header("Content-Type: text/html; charset=UTF-8");
		error_reporting(E_ALL ^ E_NOTICE);
		$shimei = '';
		$mail   = '';
		$sex    = '';
	
	//引数を確認
	if($_REQUEST['comp']){
		//引数があれば入力チェック
			$shimei = $_REQUEST['shimei'];
			$mail   = $_REQUEST['mail'];
			$sex    = $_REQUEST['sex'];
			$error_message = '';
			if(empty($shimei)){    $error_message.= "氏名が入力されていません<br />";}
			if(empty($mail)){      $error_message.= "メアドが入力されていません<br />";}
			if($sex!=1 && $sex!=2){$error_message.= "性別が入力されていません<br />";}
			if($error_message){
				//エラーがあれば戻る
				require_once('phar://index.phar/input.tpl');
				exit();
			}else{
				//エラーがなければ保存して終了
				file_put_contents('form.txt', $_REQUEST, FILE_APPEND);
				require_once('phar://index.phar/comp.tpl');
				exit();
			}
	}else{
		//引数が無ければ入力画面
		require_once('phar://index.phar/input.tpl');
		exit();
	}
input.tpl
	<?php if($error_message){print('<div style="color:red;">'.$error_message.'</div>');} ?>
	<form method="POST" action="<?php print(htmlspecialchars($_SERVER['PHP_SELF'])); ?>">
	   氏名:<input type="text" name="shimei" maxlength="64" value="<?php print(htmlspecialchars($shimei)); ?>"><br />
	   メアド:<input type="text" name="mail" maxlength="64" value="<?php print(htmlspecialchars($mail)); ?>"><br />
	   性別:
	   <input type="radio" name="sex" value="1"<?php if($sex==1){print(" checked");} ?>>男 
	   <input type="radio" name="sex" value="2"<?php if($sex==2){print(" checked");} ?>>女<br />
	   <input type="submit" name="comp" value=" 登録 ">
	</form>
comp.tpl
	投稿を受け付けました。<br />
	ご協力ありがとうございました
このファイルをひとつぽんとサーバ上に置くだけでフォームが完成という、配布などに非常に便利な機能となっています。
まあ、この例で作ったフォーム程度なら手動で1ファイルにした方が早いんですがというかわざわざファイル分ける必要ないんですが、たとえばファイルが2200個あるMantisがなんと今ならたった1ファイル、とかになったらずいぶん利用のハードルが下がったりするかもしれません。


ちなみにこのpharファイルの作成方法は以下のようになっています。
<?php
	$phar = new Phar('index.phar', 0);
	
    $phar->addFile('input.php');
    $phar->addFile('input.tpl');
    $phar->addFile('comp.tpl');
    $phar->setStub('<?php
		 Phar::webPhar("index.phar", "input.php" );
		 __HALT_COMPILER(); ?>');
いやあ、__HALT_COMPILER();なんて初めて使ったよ。

Phar::webPhar()が、pharアーカイブを直接呼び出しで利用できるようにするフロントコントローラです。
このメソッドを呼んでおくと$_REQUESTとかの処理を適切に割り振って、pharアーカイブ内でそのまま使用できるようにしてくれます。
第二引数の'input.php'を指定すると、index.pharが呼ばれたときにアーカイブ内の'input.php'が実行されるようになります。

このPhar::webPhar()をセットしているPhar::setStub()はローダスタブをpharアーカイブにセットするメソッドです。
で、そのローダスタブって何なのかというと、今回のようにpharファイルが直接呼び出された、あるいはrequire_once('phar://index.phar')と直接pharアーカイブがインクルードされた際に自動的に実行される部分です。
前回までのようにpharアーカイブ内の一部ファイルだけを呼び出した際には実行されません。

ちなみにデフォルトだと、phar未対応のPHPでpharをエミュレートする機能を追加し、その後自動的にアーカイブ内の'index.php'を実行してくれます。



2011/07/30 01:44 | Comments(0) | TrackBack() | PHP

<<前のページ | HOME | 次のページ>>
忍者ブログ[PR]