Wikipedia日本語版には項目が存在しないマイナーなプロトコル、DICT。
http://en.wikipedia.org/wiki/Dict
DICTプロトコルとは、まあ簡単に言うとネットワーク辞書です。
対応サーバにDICTリクエストを投げると、その結果を返してきてくれます。
いくら探してもびっくりするほど日本語ドキュメントがありません。
Pearパッケージも存在しますが、これまた日本語ドキュメントは存在しません。
Net_Dict 1.0.5 (stable)
http://pear.php.net/package/Net_Dict
仕方ないのでソースとRFC2229を眺めながら試してみます。
http://www.dict.org/rfc2229.txt
まあ最初からメソッドが揃っているのでRFCあんまり意味ないですが。
とりあえず適当にメソッド呼ぶだけで簡単に使えました。
dict.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
require_once "Net/Dict.php";
$dict=new Net_Dict();
$dict->connect();
//$ret=$dict->status();
//$ret=$dict->showServer();
//$ret=$dict->help();
//$ret=$dict->showDatabases();
//$ret=$dict->showStrategies();
//$ret=$dict->match('ai','substring','jpn-deu');
//$ret=$dict->define('baisyun yado','jpn-deu');
$dict->disconnect();
|
デフォルトでDICTサーバのひとつであるdict.orgが登録されているので、特に何もしなくてもいきなり使用できます。
http://www.dict.org/
showDatabasesで使用可能な辞書の一覧とその用途を取得できます。
辞書によって登録されている内容が全く違います。
eastonにイーストン聖書辞典があったり、devilsで悪魔の辞典が引けたりするので楽しいかもしれません。
日本語は何故か日独辞書しかありません。
しかも'ai'が無いのに'baisyun yado'があるとかどんな辞書だよ。
showStrategiesで、検索オプションの一覧が返ってきます。
デフォルトだとsubstring、すなわち全文検索です。
exactで完全一致、reでPOSIX正規表現等が使用できます。
検索したい辞書がわかっている場合は、第三引数に指定します。
matchで語句の検索を行います。
こちらはどのような文字が登録されているかという検索が目的で、具体的な内容までは取得しません。
最終的にdefineで完全一致検索を行い、内容を取得します。
第二引数のサーバを指定しない場合返事が返ってこないことがあるので、特殊な辞書を使用する場合は指定したほうがいいです。
また、statusやshowServer、help等辞書の情報やヘルプを取得するメソッドがあります。
日独辞書の容量が13キロバイトしかないというのはどういうことだ。
日本語ドキュメントが無いのを見てもわかるように、日本語はほぼ対象とされていません。
日本でやるならgoo辞書あたりにHTTPリクエスト投げた方が手っ取り早いです。
まあその場合はパースが面倒ですが。
PHP5にはIteratorインターフェイスというものが存在しますが、このインターフェイスを実装すると、それがそのオブジェクトのforeachの挙動になります。
http://php.benscom.com/manual/ja/class.iterator.php
適当なクラスを作成し、それに対して
foreach($MyClass as $key=>$val)
とやったときの$keyと$val、そしてその出現内容や順番なんかを自由に変更できるのです。
特に意味はありませんが、適当に文字列を突っ込んだら50音順に取り出せるクラスを作ってみます。
example_foreach.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
class Example_Foreach implements Iterator{
//変数
protected $words=array(); //配列入れ
protected $current=0; //現在値
//コンストラクタ
public function __construct(){}
//追加
public function set($word){
$this->words[]=$word;
sort($this->words,SORT_STRING);
}
//検索対象の全件数を返す
public function count(){
return count($this->words);
}
//イテレータ(foreachの実装)
public function current(){
return $this->words[$this->current];
}
public function key(){
return $this->current;
}
public function next(){
$this->current=$this->current+1;
}
public function valid(){
if(isset($this->words[$this->current])){
return true;
}
return false;
}
public function rewind(){
$this->current=0;
}
#↓クラスのおわり
}
|
使用時は普通にset()してforeachで取り出すだけです。
example.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
require_once('example_foreach.php');
$obj=new Example_Foreach();
$obj->set('a');
$obj->set('d');
$obj->set('e');
$obj->set('c');
$obj->set('b');
foreach($obj as $key=>$val){
$ret[$key]=$val;
}
|
$retはarray('a','b','c','d','e')という配列になります。
Example_Foreachには他にも$currentという変数や幾つかのメソッドがあるのに、それは無視されて、$wordsの中身だけが返ってきます。
Iteratorインターフェイスに存在するcurrent()、key()、next()、valid()、rewind()の各メソッドを実装することで、foreachの挙動を変更することができました。
ここでは単純に小さい順に取り出しましたが、メソッドを変更することで順番を変更したり、返り値を文字列以外のものにしたりといったことが自由に行えます。
ただ注意事項として、うっかり変な実装をすると、特にnextあたりを間違えると容易に無限ループになってしまうので気をつけましょう。
next(){}とかやってしまうとブラウザが死にます。
まあ、この程度ならいちいちオブジェクトにせず、配列に入れてsortした方が早い(というかIteratorが遅い)というのは秘密だ。
Mantis 1.1.6
http://www.alles.or.jp/~sogabe/mantis/
バグ管理といえばチラ裏です。
まあ自分用とか小物ならメモ帳でもいいんですが、大規模になってきたり複数人でひとつのシステムを作っていたりするとそうも言っていられません。
PHPのバグトラッキングシステムで日本語対応といえばまあMantisあたりが有名だろうのでとりあえず使ってみましょう。
まずはDBにMantis用の領域を用意します。
1
2
3
|
CREATE USER 'mantis'@'localhost' IDENTIFIED BY '******';
CREATE DATABASE IF NOT EXISTS `mantis` ;
GRANT ALL PRIVILEGES ON `mantis` . * TO 'mantis'@'localhost';
|
次はMantisを用意します。
といってもダウンロードして解凍してできたファイルを丸ごとそのままアップロードするだけですが。
次にMantisに対してDBやらなにやらの設定を行わないといけないのですが、Webから行うことができます。
普通にインストールフォルダをブラウザで開くだけです。
先ほど作成したユーザ名とパスワードを入力すると、自動的にDBにテーブルを作成し、またconfig_inc.phpというファイルを勝手に作成しDB接続に必要な情報を保存してくれます。
そしたらそのconfig_inc.phpに、以下の2行を付け加えます。
$g_default_language = 'japanese_utf8';
$g_fallback_language = 'japanese';
最初から用意されているアカウント、administrator/rootでログインします。
いきなり日本語になっているはずですが、なっていなければMy Account→Preferences→Languageをjapaneseにすれば日本語化されます。
ログイン後最初に行うことは、システム管理から新しい管理者を作成することです。
適当な管理者を作成したら、先程のadministrator/rootを削除します。
皆に知られているアカウントなので、残していて誰かに進入されたりしたら危険だからです。
最後に、adminフォルダを適当にリネームしてインストール完了。
これでMantisを使用する準備が整いました。
あとは適当にユーザを追加したりプロジェクトを追加したりバグを追加したりバグを追加するためにプログラムを作成したりしてみましょう。
バグを追加するためにプログラムを作成するというのも変な話ですが。
Text/Highlighterで色づけを行うと、生成されるcssのclass名が".hl-main"とかに固定されて出力されます。
ここを変更するにはText_Highlighter_Renderer_Html::$_class_mapを直接変更します。
実際私はソースの出力に使用しているclass名を"highlight-hl-main "というふうにしています。
ただこうすると、例えば複数のソースを違うスタイルで表示したいというようなことができません。
それに配布されているPearのソースに手を加えるのはできれば避けたいところです。
何かメソッドで変更できたりできないものでしょうか。
Webを探してみてもその手の情報は全くないので自力でソースを追っていったところ、どうやらそれっぽいオプションを発見。
どうでもいいんだがググるとマニュアルのコピペばっかり大量に見つかるのだが、あれってどういう意味があるんだろう。
colorsのヒントとか全く意味がわからんだろ。
はっきりいって邪魔でしょうがない。
とりあえずText/highliter/Renderer/Html.php::reset()内に
if (isset($this->_options['class_map'])) {
$this->_class_map = array_merge($this->_class_map, $this->_options['class_map']);
}
とかいう記述があったのでおそらくここらへんだろうと推測し、適当に突っ込んでみる。
highlighe_test.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//インスタンス
require_once('Text/Highlighter.php');
require_once('Text/Highlighter/Renderer/Html.php');
$highlight = Text_Highlighter::factory('PHP');
$renderclass='Text_Highlighter_Renderer_Html';
//レンダラセット
$highlight->setRenderer(
new $renderclass(
array(
'numbers'=>FALSE
,'class_map'=>array('main'=>'hogehoge')
)
)
);
//表示
$str=file_get_contents(__FILE__);
$a=$highlight->highlight($str);
print($a);
|
あっさり成功。
というわけでクラス化してみます。
highlight.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
//初期設定
require_once('Text/Highlighter.php');
class pearHighLightModel {
//メンバ変数
private $highlight = '';
private $language = 'PHP';
private $renderer = 'Html';
private $numbers = FALSE ;
private $class_map_head='';
private $class_map_ori=array(
'main' => 'hl-main'
,'table' => 'hl-table'
,'gutter' => 'hl-gutter'
,'brackets' => 'hl-brackets'
,'builtin' => 'hl-builtin'
,'code' => 'hl-code'
,'comment' => 'hl-comment'
,'default' => 'hl-default'
,'identifier' => 'hl-identifier'
,'inlinedoc' => 'hl-inlinedoc'
,'inlinetags' => 'hl-inlinetags'
,'mlcomment' => 'hl-mlcomment'
,'number' => 'hl-number'
,'quotes' => 'hl-quotes'
,'reserved' => 'hl-reserved'
,'special' => 'hl-special'
,'string' => 'hl-string'
,'url' => 'hl-url'
,'var' => 'hl-var'
);
//コンストラクタ
public function __construct(){
}
//ハイライトして返す
public function highlight($str){
$this->_makeHighlighter();
return $this->highlight->highlight($str);
}
//cssの接頭辞を入れる
public function setClassMap($head=''){
$this->class_map_head=$head;
}
private function _setClassMap(){
foreach($this->class_map_ori as $key=>$val){
$this->class_map[$key]=$this->class_map_head.$val;
}
}
//言語を変更
public function setLang($language){
$this->language=$language;
}
//レンダリング変更
public function setRenderer($renderer){
$this->renderer=$renderer;
}
//表示形式を変更
public function setNumbers($numbers){
$this->numbers=$numbers;
}
//オブジェクト作る
private function _makeHighlighter(){
if($this->class_map_head){$this->_setClassMap();}
require_once('Text/Highlighter/Renderer/'.$this->renderer.'.php');
$renderclass='Text_Highlighter_Renderer_'.$this->renderer;
$this->highlight = Text_Highlighter::factory($this->language);
$this->highlight->setRenderer(
new $renderclass(
array(
'numbers'=>$this->numbers
,'class_map'=>$this->class_map
)
)
);
}
#↓クラスのおわり
}
|
利用するときに
$highlight->setClassMap('highlight-');
というかんじで接頭辞を突っ込んだら、出力が
class="highlight-hl-main"
となります。
問題点としては、class_mapの一覧をこちらで持ってしまっていること。
Text_Highlighter_Renderer_Html::_class_mapを直接引っ張ってくればよかったのでしょうが、めんどいからもういいや。
見返していたらなんかメソッド呼ぶたびにオブジェクトを作成とか壮大に無駄なことをやっていたのでスリム化してみる。
highlighter.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
//初期設定
require_once('Text/Highlighter.php');
class pearHighLightModel {
//メンバ変数
private $highlight = '';
private $language = 'PHP';
private $renderer = 'Html';
private $numbers = FALSE ;
//コンストラクタ
public function __construct(){
}
//ハイライトして返す
public function highlight($str){
$this->_makeHighlighter();
return $this->highlight->highlight($str);
}
//言語を変更
public function setLang($language){
$this->language=$language;
}
//レンダリング変更
public function setRenderer($renderer){
$this->renderer=$renderer;
}
//表示形式を変更
public function setNumbers($numbers){
$this->numbers=$numbers;
}
//オブジェクト作る
private function _makeHighlighter(){
require_once('Text/Highlighter/Renderer/'.$this->renderer.'.php');
$renderclass='Text_Highlighter_Renderer_'.$this->renderer;
$this->highlight = Text_Highlighter::factory($this->language);
$this->highlight->setRenderer(
new $renderclass(array('numbers'=>$this->numbers))
);
}
#↓クラスのおわり
}
|
これなら実際にText_Highlighterインスタンスを作成するのはpearHighLightModel::highlight()を呼んだときだけなので、requireしたけど結局使わなかったというような時にも負担軽減になります。
さらにrequire_once('Text/Highlighter.php');の行もpearHighLightModel::_makeHighlighter()に含めることもできますが、そこまでやるとText_Highlighter::setRenderer()で使用するHL_NUMBERS_TABLEのような定数まで使えなくなるので不便です。
http://pear.php.net/manual/ja/package.text.text-highlighter.oc.php
そもそもText/Highlighterなんぞ、そんなに負荷がかかるほど使わないという噂もありますが気にしない。
<input type="file">でどの画像を指定したのかわからなくなった、うっかり違うファイルをアップロードしてしまった、なんてことはよくあると思いますが、それを防ぐために確認画面を用意しているサイトもあります。
ただ個人的に確認画面要らないと思うのですがどうでしょう。
というわけで画面遷移せずに指定した画像をプレビューできるjQueryプラグインを見つけたので使ってみます。
jQuery.autouploader 1.0.1
http://tech.kayac.com/archive/jquery-autouploader-plugin.html
使い方は簡単。
適当な引数付けて<script src>で呼ぶだけというお手軽さです。
とりあえず作ってみましょう。
jquery_index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<!--
jquery.autouploader.jsを呼び出すときに、srcに引数を入れる
api=/api/image/set
サーバ上の処理プログラムのURL
send_name=img
送信する画像ファイル名
loading=''
ロード中別の画像を表示する場合
no_exec=''
trueにすると自動プレビュー無効
その場合は↓のように手動で呼び出す
$(function(){$('form[enctype="multipart/form-data"]').autouploader();});
-->
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript" src=
"./jquery.autouploader.js#api=./jquery_api.php&send_name=img">
</script>
<form method="POST" action="./jquery_submit.php" enctype="multipart/form-data">
<input type="file" name="data"><br /><br />
<input type="submit" name="submit"></form>
|
#api=./jquery_api.php&send_name=img
という形で呼び出しています。
これは、サーバ側で画像ファイルの処理を行うのが./jquery_api.phpで、$_FILESの名前となるのがimgということです。
デフォルトがimgで、<input type="file">のname属性は無視されます。
本来、フォームは
<input type="submit">
ボタンを押した時点で送信されますが、今回は画像ファイルを指定して「開く」を押した時点でjQueryがそれを察知し、jquery.autouploader.jsがそのファイルを取得して送信します。
送信先のURLで行うなことは、送信されてきた画像を適切に保存することと、その画像のURLを返すことです。
jquery_api.php
1
2
3
4
5
6
|
move_uploaded_file(
$_FILES["img"]["tmp_name"]
,'/image/'.$_FILES['img']['name']);
print('/image/'.$_FILES['img']['name']);
|
アップロードされたファイルを/imageフォルダにコピーし、そのファイル名をprintしてるだけです。
アップロードファイルのエラーチェックやファイル形式チェックも本来は必要ですが、どうせローカルなので一切やってません。
公開するときにはこんなことやっちゃいけません。
たったこれだけで画像プレビュー機能が追加できてしまいました。
ちなみに、プレビュー時に「削除」ボタンが出ますが、このボタンは単にプレビューを非表示にするだけで、サーバ上のファイルを消すわけではありません。
そんな機能作ってないですし。
というわけで延々プレビューを繰り返すと、そのぶんだけサーバにファイルが増えていきます。
うっかり機密ファイルを指定しちゃったからやり直した、という場合でもファイルはしっかり盗られています。
なんかに使えそう。
問題点としては、日本語ファイルが使用できません。
保存はできるのですが、表示するアドレスとして日本語が使用できません。
何の文字コードで送っても駄目なので、日本語自体アウトと思われます。
サーバ側で適当に名前を割り振る必要があります。
だいぶ前の記事の続き。
今度はcURLでアクセスにチャレンジ。
単にCurlと言うとFlashの超すごい版みたいなWeb用言語のことですが、
http://ja.wikipedia.org/wiki/Curl_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E)
PHPで言うところのcURLはlibcurlです。
元はCでしたが、PHPをはじめ多くの言語に移植されています。
httpをはじめftp、telnetといった有名な通信プロトコルに対応しており、認証や暗号化、ファイルアップロード等多くの機能を備えているという通信ライブラリです。
とりあえずcURLでfile_get_contents相当相当のことを行ってみます。
curl_file_get_contents.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//cURL
$ch = curl_init();
//cURLオプション
curl_setopt($ch, CURLOPT_URL, "http://example.com/index.php");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
//URL取得
$a=curl_exec($ch);
curl_close($ch);
print("<pre>");var_dump($a);die();
|
まあ、これだけならcURLを使う意味がありません。
cURLの特徴は多様なオプション設定が可能なところです。
ただ、PHPではあらゆるオプションをcurl_setoptに押し込むという荒技で処理しているため、素のままだと少々扱いづらいです。
http://jp2.php.net/manual/ja/function.curl-setopt.php
特にデフォルトだと問答無用でブラウザに出力してしまったりするのでどうにかします。
例によってクラス化してみましょう。
curl.class.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
class curlModel {
//メンバ変数
private $curl = array();
private $url = '';
//コンストラクタ
public function __construct($url,$port=null){
if(!$url){return false;}
$this->url=$url;
//Curlオブジェクトを用意
$this->curl=curl_init($url);
//Locationが指定されていればその先を呼び出す
curl_setopt($this->curl,CURLOPT_FOLLOWLOCATION,true);
//Locationを辿る最大回数
curl_setopt($this->curl,CURLOPT_MAXREDIRS,3);
//ヘッダを画面出力しない
curl_setopt($this->curl,CURLOPT_HEADER, false);
//返り値を画面出力しない
curl_setopt($this->curl,CURLOPT_RETURNTRANSFER,true);
//400以上のステータスコードが返ってきた場合取得しない
curl_setopt($this->curl,CURLOPT_FAILONERROR,true);
//更新日時を取得する
curl_setopt($this->curl,CURLOPT_FILETIME,true);
//接続先ポート
if($port){
curl_setopt($this->curl,CURLOPT_PORT,$port);
}
return true;
}
//あればBasic認証
public function setBasicAuth($user,$pass){
$basic=$user.':'.$pass;
curl_setopt($this->curl,CURLOPT_HTTPAUTH,CURLAUTH_ANY);
curl_setopt($this->curl,CURLOPT_USERPWD,$basic);
return true;
}
//GETパラメータをセット
public function setGetParam($get_array){
if(strpos($this->url,'?')===false){
$this->url.='?';
}
foreach($get_array as $key=>$val){
$this->url.=urlencode($key).'='.urlencode($val).'&';
}
curl_setopt($this->curl,CURLOPT_HTTPGET,true);
curl_setopt($this->curl,CURLOPT_URL,$this->url);
return true;
}
//POSTパラメータをセット
public function setPostParam($post_array){
curl_setopt($this->curl,CURLOPT_POST,true);
curl_setopt($this->curl,CURLOPT_POSTFIELDS,$post_array);
return true;
}
//実行
public function exec(){
return curl_exec($this->curl);
}
#↓クラスのおわり
}
|
まあ面倒なcurl_setoptをクラスに纏めただけです。
コンストラクタにURLと必要ならばポートを渡します。
setBasicAuthでベーシック認証、setGetParamでGETパラメータ、setPostParamでPOSTパラメータを与えてexecで実行します。
curl.php
1
2
3
4
5
6
7
8
9
10
11
|
require_once('./curl.class.php');
$url='http://yuubiseiharukana.blog.shinobi.jp/';
$get['a']='aa';
$get['b']='bb';
$curl=new curlModel($url);
$curl->setGetParam($get);
$ret=$curl->exec();
|
簡単に取得できました。
上の例ではこのブログに引数渡してますが、実際は引数とか見てないので全く意味ないですが。
あと実装が適当なので引数チェックしていないとか、setPostParamの後にsetGetParamしたら不穏な動きをしそうだとか、curl_setopt_arrayの存在に今気付いたとか色々あるけど気にしない。
ぶっちゃけここの忍者ブログのように何処かをレンタルするのが一番手っ取り早いですが、自前でサーバを持っているのならフリーのブログソフトを使用してみましょう。
有名どころとしてはMovableType、XOOPS等がありますが、MTは再構築が重すぎてやってられん。ていうかPerlです。
XOOPSはブログというよりCMSなので、何でもできる反面設定運用等が大変です。
ということでとりあえず、彼の大垣氏も使用しているWordPressで。
有志により日本語化されています。
WordPressの特徴は、簡単インストール簡単設定、ブログの運営には必要十分な機能、といったところです。
まずインストール手順。
ダウンロードして解凍してできたファイルを丸ごとアップロード。
wp-config-sample.phpにデータベース接続情報、及び暗号を記入してwp-config.phpに改名。
アップロードしたディレクトリにアクセス。
あとは画面に現れたボタンを押しましょう。
ただし、ローカルで行う場合は「このブログを Google や Technorati などの検索エンジンに表示されるようにする。」をチェックしてはいけません。
次のページは詳細設定画面ではなく、なんと自動生成されたパスワードが表示されてすべての設定終了です。
死ぬほど簡単。
むしろ簡単すぎて書くことがありません。
一旦稼働してしまえば設定変更など殆どあらゆる操作を管理画面から行うことができるので、直接ファイルを触る必要もありません。
他のブログソフトウェアと比べた場合、弱点としては複数のブログを使用できないという点が挙げられます。
複数ブログを使用する場合はそれぞれのディレクトリを作成し、別々のスクリプトとして使用する必要があります。
しかし個人用と割り切れば複雑な設定も必要ないこの形式で十分でしょう。
ブログ自体は一つですが、書き込むユーザは複数作成できるので権限の心配は必要ありません。
うん、本当に書くこと無いな。
File_Archive 1.5.4 (stable)
http://pear.php.net/package/File_Archive
Linuxだったらexecやsystemで直接tar呼ぶのが手っ取り早いですが、Windowsだと当然使えません。
またBzip2やZlib等のライブラリで圧縮解凍を行うことが出来ますが、アーカイバ毎に個別のコマンドを使用する必要があり面倒です。
http://jp.php.net/manual/ja/refs.compression.php
そんな場合は例によって抽象化です。
File_Archiveは、読み込みや書き込みの際に、ファイル名の拡張子から勝手にアーカイバを識別して、それぞれに対応した方法で圧縮解凍を行ってくれます。
対応拡張子はtar、zip、jar、gz、tgz、tbz、bz2、bzi、ar、debと、Linuxで使用されるひととおりの拡張子に対応しています。
ただ例えばbz2はbzopenを呼んでいるだけだったりするので、一部の拡張子については各モジュールをインストールする必要があります。
またこのFile_Archive、使用法が少々特殊なので慣れないと面倒です。
file_archive.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
require_once "File/Archive.php";
//解凍
//test.zip内にあるsample.txtを/tmpに解凍します
File_Archive::extract(
File_Archive::read('test.zip/sample.txt')
, $dest='/tmp/'
);
//圧縮
///tmp/testフォルダの中身を全部/tmp/sample.zipに圧縮します
File_Archive::extract(
$src= '/tmp/test/'
, File_Archive::toArchive(
'/tmp/sample.zip'
, File_Archive::toFiles()
)
);
//アーカイブ形式変換
//test.zipを読み出して、test.tgzとして保存しただけ
File_Archive::extract(
File_Archive::read('test.zip')
, File_Archive::toArchive(
'test.tgz'
, File_Archive::toFiles()
)
);
|
基本的に何もかもをFile_Archive::extractの中で処理します。
引数はふたつで、基本は前者を後者に変換となります。
引数はFile_Archiveオブジェクト、もしくは変数で与えることができます。
extractの引数がextract(&$sourceToConvert, &$destToConvert, $autoClose = true, $bufferSize = 0)となっているため、上記のように$src=と変数で与えると大丈夫ですが、直接'test.zip'とか書くとエラーになります。
第二引数の指定方法ですが、toFilesを呼べば現在のファイル構造をそのままファイルとして保存します。
toArchiveを呼べばアーカイブを作成します。
toArchiveの場合はそのままではアーカイブ化するだけで出力を行わないので、さらに第二引数を指定します。
第二引数にtoFilesを呼べば作成したアーカイブを保存し、toOutputを呼ぶとブラウザからダウンロードさせることができます。
さてFile_Archiveにもイテレータのようなものが実装されています。
圧縮ファイル内のファイルをnextで取得してgetFilenameやgetStatで状態を取得できます。
まあcountは無いですしrewindはなんかうまく動いてないっぽいしで微妙ですが。
file_archive2.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
require_once "File/Archive.php";
//圧縮ファイルのイテレータ
$source = File_Archive::read('sample.zip/');
while($source->next()) {
var_dump($source->getFilename(),$source->getStat());
}
//sample.zipから、1キロバイト以下のファイルを抜き出す
File_Archive::extract(
File_Archive::filter(
File_Archive::predNot(
File_Archive::predMinSize(1024)
),
File_Archive::read('sample.zip/')
),
File_Archive::toArchive(
'directory.zip',
File_Archive::toFiles()
)
);
|
圧縮ファイルを作成する際、File_Archive::filterで任意のファイルを抜き出すことができます。
抜き出し方はわかりやすいので簡単にできるのですが、これもまた普通に&&とか書くことができず、
File_Archive::predAnd(File_Archive::predMinSize($size),File_Archive::predMinTime($time))
みたいな書き方をしないといけないため、入れ子だらけになります。
上のサンプルですら既に嫌になる状態ですが、マニュアルのサンプルはさらに凄いことになっています。
もうちょっとどうにかならなかったものでしょうか。
前回の続き?
前回とりあえずPDFの作成はできるようになりましたが、AdobeAcrobatのように自由にレイアウトを作成するにはほど遠いものがあります。
フォーム上などでレイアウトしたとおりのPDFを作成するにはHTMLを解析して座標を計算してどうのこうのと面倒なことを行わねばならないので、正直手に余ります。
しかし世の中は広いもので、そのようなサービスをフリーで提供してくれているところがあります。
HTML2PDF.BIZ
http://www.html2pdf.biz/
ありがたく利用させていただきましょう。
使用方法は見ての通りGET投げるだけなので難しくも何ともありません。
http://www.html2pdf.biz/api.php
html2pdf.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//初期設定
//サーバ
$html2pdf_server='http://html2pdf.biz/api';
//生成時間用
ini_set('max_execution_time',120);
set_time_limit(120);
//設定
$html2pdf_url='http://example.com/';
$html2pdf_ret='pdf';
$html2pdf_name='hoge.pdf';
$html2pdf_ts=true;
//URL作成
$html2pdf=
$html2pdf_server
.'?url='.urlencode($html2pdf_url)
.'&ret='.(isset($html2pdf_ret)?$html2pdf_ret:'pdf')
.'&ts='.(isset($html2pdf_ts)?'true':'false');
//取得
$pdf=file_get_contents($html2pdf);
if(!$pdf){die();}
//表示
header('Content-Type: application/pdf');
header('Content-Length: '.strlen($pdf));
header('Content-Disposition: inline; filename="'.$html2pdf_name.'"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression','0');
print($pdf);
|
$html2pdf_urlに入れたURLを、$html2pdf_ret形式で取得します。
$html2pdf_ts=trueだとタイムスタンプが入ります。
$html2pdf_nameは出力されたPDFを保存する場合のデフォルト名です。
PDF生成に2,30秒かかるので、念のためタイムアウト時間を2分に設定しています。
以上でHTMLから簡単にPDFの作成ができました。
PDFにHTML2PDF.BIZのロゴが入りますが、これはフリー版なので仕方ありません。
これで自力でではありませんがHTMLをそのままPDF化することに成功しました。
しかし重いせいなのかなんなのか、しょっちゅうfile_get_contentsに失敗してしまうのが難点。