かつてPear::Mailを使用してGmailからメール送信というのを行いましたが、日本産ではないのでヘッダの日本語対応等少々面倒なところがあります。
世の中は広いもので、Pear要らずの日本語メール送信スクリプトを公開してくれている人がいます。
Qdsmtp 0.2.0a
http://hal456.net/qdsmtp/
準備は、qdsmtp.phpを適当なフォルダに置くだけです。
とりあえず普通にメール送信してみます。
decomail.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
|
//require
require_once('qdsmtp.php');
class Decomail{
//送信メールの初期値
protected $param = array(
'host'=>'tls://smtp.gmail.com'
,'port'=> 465
,'protocol'=>'SMTP_AUTH'
,'user'=>''
,'pass' => ''
,'from'=>''
);
//Qdsmtp
protected $smtp='';
//コンストラクタ
public function __construct($user,$pass,$from){
//引数セット
$this->param['user']=$user;
$this->param['pass']=$pass;
$this->param['from']=$from;
//Qdsmtp
$this->smtp = & new QdSmtp($this->param);
$this->smtp->continueConnect(true);
}
//送信
public function send($mailto,$subject,$body){
//送信
return $this->smtp -> mail(
$mailto
,$subject
,$body
);
}
#クラスのおわり
}
|
使用は普通にnewしてsendするだけ。
decomail.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//初期設定
$user='ユーザ名';
$pass='パスワード';
$from='送信元メアド';
//インクルード
require_once('decomail.class.php');
$smtp=new Decomail($user,$pass,$from);
//送信
$mailto='送信先メアド';
$subject='件名';
$body='本文';
$ret=$smtp->send($mailto,$subject,$body);
|
Googleからあっさり送信できました。
あとは引数のチェックルーチンなんかを入れると完成です。
一見Pear::Mail版とほとんど変わりませんが、こちらはqdsmtp.phpを一本置いただけです。
Pearをインストールできない環境などでは重宝するでしょう。
また、ヘルプでは日本語が使用できないと書いてありますが、環境によっては通るみたいです。
http://hal456.net/qdsmtp/mail
とりあえず私の手元では何の問題もなく日本語メールが送信できました。何でしょう?
前回のさらに続き?
SOAPとは、ネット越しに情報をやりとりする手段の一つです。
http://ja.wikipedia.org/wiki/SOAP_(%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB)
Webサービスのメイン手段として登場し、特徴としてはすべてをXMLでやりとりするため汎用化がしやすい(ということになっている)ことや、WSDLという設計図を利用して簡単にサービスが構築できる(ということになっている)ことがあります。
http://ja.wikipedia.org/wiki/WSDL
が、より簡単なXML-RPCや、もっと簡単にfile_get_contentsするだけで全てが終わるRESTなどが普及したため、あまり使われていません。
確かに出来ることはSOAPのほうが多いのですが、なにしろ面倒ですからな。
また、Yahooは最初からRESTしか無かったり、SOAPの主導権争いに嫌気がさしたGoogleの中の人がSOAP対応を打ち切るなど将来も微妙な感じです。
企業間通信やなどでは今でも使われているところはあるようですが、実際WebサービスとしてSOAPを提供しているところはググってもあまり出てきません。
イースト辞書WebサービスはSOAPにも対応しているのでそちらを使用してみましょう。
http://www.btonic.com/ws/index.html
WSDLに関しては、サーバ上のWSDLを直接参照することも出来ますが、まああまり迷惑をかけないよう拾ってきてローカルに保存しておきましょう。
WSDLファイルにはGetDiclistとかSearchDicItemといった要素が書かれていますが、これをSoapClient関数に読み込ませることによってSoapClient::GetDiclistやSoapClient::SearchDicItemといった関数を使えるようになります。
http://jp.php.net/manual/ja/book.soap.php
WSDLがWebサービスの設計図となっているのでこういう芸当が可能なのです。
というわけでとりあえずGetDiclistとSearchDicItemを作ってみます。
dict_soap.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
|
//検索を行うクラス
class Dict_Soap{
//URL
protected $url_service=
'http://btonic.est.co.jp/Netdic/Netdicv10.asmx';
//WSDLファイル
//protected $file_wsdl=
'http://btonic.est.co.jp/Netdic/Netdicv10.asmx?WSDL';
protected $file_wsdl='Netdicv10.wsdl';
//SOAPオブジェクト
protected $soap='';
//辞書リスト
protected $diclist=array();
//メソッド用パラメータ初期値
//辞書リスト取得
protected $param_GetDicList=array(
'AuthTicket'=>''
);
//検索
protected $param_SearchDicItem=array(
'AuthTicket'=>''
,'DicIDList'=>array(
'19553dab-aa51-43bb-9fb7-764153b647ac' //EJDict英和辞典
//'8a68bb8a-16ee-4b51-afaa-74c277bb600a'//Edict和英辞典
//'39124c12-6244-4c65-94eb-8b18c20c2898'//Wikipedia
)
,'QueryList'=>array(
'ScopeID'=>'ANYWHERE'
,'MatchOption'=>'EXACT'
,'MergeOption'=>'AND'
)
,'ContentProfile'=>array(
'FormatType'=>'XHTML'
,'ResourceOption'=>'URI'
,'CharsetOption'=>'WINJPENV'
)
,'SortOrderID'=>''
,'ItemStartIndex'=>'1'
,'ItemCount'=>'4'
,'CompleteItemCount'=>'2'
);
//コンストラクタ
function __construct($AuthTicket=false){
$this->soap = new SoapClient($this->file_wsdl);
//チケットがあれば
if($AuthTicket){
$this->$this->param_GetDicList['AuthTicket']=$AuthTicket;
$this->$this->param_SearchDicItem['AuthTicket']=$AuthTicket;
}
}
//使用可能な辞書のリストを取得
public function getDicList(){
//取得
$tmp=$this->soap->GetDiclist($this->param_GetDicList);
//返り値のうち必要な部分のみ取得
foreach($tmp->GetDicListResult->DicInfo as $key=>$val){
$this->diclist[$key]['DicID']=$val->DicID;
$this->diclist[$key]['FullName']=$val->FullName;
$this->diclist[$key]['Abbrev']=$val->Abbrev;
}
return $this->diclist;
}
//辞書を検索する
public function searchDicItem($string){
//検索語句セット
$this->param_SearchDicItem['QueryList']['Words']=$string;
//何故か返り値が常に見つからない
$ret=$this->soap->SearchDicItem($this->param_SearchDicItem);
return $ret;
}
#↓クラスのおわり
}
|
できました。
一部分テキトーなので辞書IDなんかがべた書きになってますがまあ気にしない。
さて実行。
soap.php
1
2
3
4
5
6
7
8
9
10
11
|
//インスタンス
require_once('./dict_soap.class.php');
$dictsoap=new Dict_Soap();
//$ret=$dictsoap->getDicList();
$ret=$dictsoap->searchDicItem('love');
print("<html><pre>");var_dump($ret);die();
|
実行結果。
object(stdClass)#3 (2) { ["SearchDicItemResult"]=> int(0) ["ItemList"]=> object(stdClass)#4 (0) { } } |
…あれー?
SearchDicItemがうまく動いてくれません。
送信メッセージ形式は合っている筈なんだが…
getDicListは結果がきちんと返ってきます。
二重配列内の、WSDLでminOccurs="1"と定義されている部分、たとえば$param_SearchDicItem['QueryList']['MatchOption']あたりを削除してみると正しく不正になる(どころか、正しくないことにApache毎落ちる)のでパラメータの指定が間違っているということもないと思います。
うむ、よくわからん。
今回は原因特定しきれなかったので相手が悪いのだと勝手に納得しつつ終了。
前回の続き。
というわけでDICTプロトコルは全く役に立たないことがわかったので、日本語対応のオンライン辞書を探してみます。
ググると一杯出てきますな。
とりあえず「辞書 API」で真っ先に出てきたイースト辞書Webサービスを試してみることにします。
http://www.btonic.com/ws/index.html
イースト辞書Webサービスはイースト株式会社が作成している辞書Webサービスのテストサイトという位置づけのようです。
http://www.est.co.jp/
とりあえず簡単なほうのRESTで。
http://www.btonic.com/ws/NetDicv09RestSpec.htm
見ての通りHTTPリクエストを投げるだけという簡単設定。
これに限らず専用のプロトコルを使用するよりHTTPのほうが遙かにメジャーで簡単なので、専用プロトコルは今後どんどん滅びていくものと思われます。
もちろんセキュリティが必要だったり高度に専門性が必要だったりといった特別なものは別ですが。
作成方針としては、まず検索メソッドで該当語句の含まれる記事の一覧を取得し、その中から該当の記事のIDを探し出し内容取得メソッドで内容を取得する、という順番になります。
dict_east.class.php
ソースは本文長すぎとか意味不明なことを言われたので ファイルにしてあります。
Dict_East_Search::currentはforeachで配列を返す部分を実装しています。
ItemIDのままだとオブジェクトを返してしまい、asXMLだと現在地点である<ItemID>等のタグまでくっついてきてしまうので(string)で無理矢理文字列にしています。
Dict_East::searchメソッドは単純にsimplexml_load_string()でパースしています。
こちらは返り値の各項は値なので単純にsimplexml_load_stringを適用して問題ありません。
ところがDict_East::requestメソッドは返り値が以下のようにHTMLタグ込みで返ってきます。
<Head> <div class="NetDicHead" xml:space="preserve" xmlns=""> <span class="NetDicHeadTitle">山口人生</span> </div> </Head> |
この場合、XMLパース関数はどれも癖があり、単純に<Head>タグ内の値だけを全取得したいだけという場合のパースが困難です。
simplexml_load_string()やxml_parse_into_struct()を使用するとHTMLタグ単位で全てオブジェクトや配列に分解されてしまい、えらいことになってしまいます。
DOMDocumentクラスのgetElementsByTagNameあたりを使用するとHTMLタグが全て削除されてしまいます。
XMLReaderは一行毎に読み込んでは処理するという形式のため実装が面倒になってやめました。
結局自力でのパースは諦め、simplexml_load_string()後にxpathでノードを指定してasXMLでXMLだということにして返すようにしました。
このときにまたネームスペースが存在する場合は単純指定では取得できないとか一悶着あったが、最終的にはどうにか成功しました。
使用する場合は簡単にこんなふうに使います。
dict_east.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
|
//インスタンス
require_once('./dict_east.class.php');
$dicteast=new Dict_East();
$ret=array();
$dicteast_search_array=array();
//オプション設定
//$dicteast->setDictionary('EJdict');
//$dicteast->setSearchScope('ANYWHERE','EXACT');
//検索メソッド
$dicteast_search=$dicteast->search('愛');
$count=$dicteast_search->getCount();
foreach($dicteast_search as $val){
$dicteast_search_array[]=$val;
}
//取得メソッド
$ret=$dicteast->get($dicteast_search_array[0]['itemID']);
print("<pre>");var_dump($dicteast_search_array,$ret);die();
|
まあこんなかんじでネット辞書検索APIのクライアントを作成することが出来ました。
後は適当にフロントを実装すれば簡単に単語翻訳なんかを作成することができます。
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なんぞ、そんなに負荷がかかるほど使わないという噂もありますが気にしない。
だいぶ前の記事の続き。
今度は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 などの検索エンジンに表示されるようにする。」をチェックしてはいけません。
次のページは詳細設定画面ではなく、なんと自動生成されたパスワードが表示されてすべての設定終了です。
死ぬほど簡単。
むしろ簡単すぎて書くことがありません。
一旦稼働してしまえば設定変更など殆どあらゆる操作を管理画面から行うことができるので、直接ファイルを触る必要もありません。
他のブログソフトウェアと比べた場合、弱点としては複数のブログを使用できないという点が挙げられます。
複数ブログを使用する場合はそれぞれのディレクトリを作成し、別々のスクリプトとして使用する必要があります。
しかし個人用と割り切れば複雑な設定も必要ないこの形式で十分でしょう。
ブログ自体は一つですが、書き込むユーザは複数作成できるので権限の心配は必要ありません。
うん、本当に書くこと無いな。