Archive for the ‘CODING’ Category

ブラウザの壁

木曜日, 10 月 15th, 2009

さてさて今回は久しぶりのcodingネタですよ。
最近何やっているかというと、なんか再びPHPに戻ってます。
というのものページ作成を例によって某氏と一緒にやっていたから。 いや正確にはやっているから。でも一通り完成といったところですね。見た目は。

今回主に私が書いたのは、WordPressのインストールディレクトリ配下にない場所に置いたPHPファイルから、WordPressの情報を取り出す、という作業。 最初はworpressの関数群を呼び出す必要があるかと思ってたんだけど、よく考えたら(いや考えるまでもなく)自分でQuery発行する気があるなら、データベースに直接クエリ発行してしまった方がいろんな意味で早いんでね?と気づいた訳です。
どの道、書き込みをする気はなかったのでWordPressのデータベースの情報を整合性を破壊する心配はないし。
DBへの負荷はむしろ減るかも知れないし(笑)。

さて私がやったこと、そして躓いたことを。
まず第一に、自分の使っているサーバのDBへアクセスするために必要な以下の情報を確認。
ホスト名、ユーザ名、パスワード
次に、WordPressが利用しているデータベースのDB名。
最後に、WordPress(MU)が利用しているテーブルに着く、データベース接頭辞。
WordPressの関数群を利用するなら、WPDBオブジェクトのインスタンスglobal $wpdbのメンバbase_prefixを参照すれば分かります。
そうでなくとも、phpMyadminするなり、MySQLに接続するなりすれば、分かると思いますが…。
あとはそもそもconfig.phpをみれば丸わかりですな。上記全て。

とりあえず、単純にDBに接続するテスト。mysql_connectを呼んで、適当なテーブルから情報を読み出してみる。
成功。次に、後々使うに決まってるからmysql_な関数たちのごく一部、使いそうなやつだけラッパーを書いた。
ここで、クエリを発行するためにmysql_real_escape_stringをしようとしてハマった。
ただの勘違いでしかないんだけど、echo mysql_real_escape_string($string);すると、文字化けするんだよね。
ちなみに$stringはUTF-8で書いてる。そもそも文字化けして当然だということをよく理解せずに、「何で文字化けしてるんだー!」とあっちゃこっちゃのQ&AやらTipsやらリファレンスやらを読み漁るも、解決できず(出来る訳がない)。

ようやっとescapeしているのがシングルクォートや\r\nだということを理解し、なんか徒労感に襲われる(実際徒労なんだが)。
んでクエリにreal_escapeした文字列をぶち込んで成功。
そしてクエリ丸ごとescapeして失敗(そりゃそうだわな)。
やっぱり駄目か…と思いつつ、クエリを渡すとシングルクォートでexplodeして、シングルクォートに挟まれた文字列だけをescapeして再結合するルーチンを追加。シングルクォートがいくつでも今のところ動いているようだ。
やったことは単純で、explodeした後の配列を$stringsとすると、for($i=1;$i SQL文はシングルクォートから始まったりしないという知識を利用しているのであんまりよろしくない気もするが、正しくないクエリーは何れどこかで弾かれるので、まぁ問題ない気もする。

ここまでできれば後は簡単で(といいつつエラーを出しまくったが)、WordPress CODEXのデータベース概要を見ながら、欲しい情報を取り出すクエリを書き、ラッパー関数からクエリの結果をもらい、整形するのみ。
こっから後で出したエラーは行末の;忘れたとか文字列結合演算子.を飛ばしてたとかそんなんばっか。
SQLのWHERE句の中でのNOTを使おうとして詰まったが、!=に書き直したらあっさり動いたので満足している。

もうひとつ微妙なエラーがあったのを思い出した。
if($array[x]=query($query_strings)){}の形式でif文を構成した時、queryの結果がNULLだと、 if文の中は実行されないが、変数にFALSEが入るなんでorz
結局elseの中でunset($array[x]);しましたよ。妙な仕様だなぁ。
たしか$array[]だとちゃんと代入されないんですよねー。
添え字を指定するとミョーなことが起きるorz
ご注意ください(誰が?)。

さて次に私が請け負った作業がCSSの調整。ページの大枠と素材は某氏が既に完成させていて、私は調整だけ。
とはいえクロスブラウザにまつわる問題…と言うよりIE7とIE6で表示が崩れるのを何とかする、つー話だったので、辛かった。
何しろCSSの何がどう影響を与えているのか見当もつかなんだ。
真IE6の挙動は奇怪です…。(と言いつつ我が家のデスクトップのIEはver6ですが)
今回初めてIE8を見直しましたよ。ええ。標準準拠は素晴らしい。
結局どんなところで躓いていたかと言うと、

  • XHTMLのxml宣言がひっかっかっていた。
  • CSSでfloat指定したセレクタに、widthとpaddingを同時指定するとバグ、に引っかかっていた。
詳しくは、前者はDOCTYPE宣言がブラウザに与える影響と言う話で、 原因が分からないので兎に角ggrks状態だった私が、ヤケクソでIE opera firefox css 崩れるとかそんなワードで 検索してたどり着いたページにあったのをみつけて、藁にすがってみたらこれだった、と言うもの。
これを修正するまでIE6では絶望的にレイアウトが崩壊していた。いわゆる互換モードだったわけ。
互換モードだとそれこそCSS Hackでもしない限り、まともな表示は望めない。
後者は、IE6 float CSS 上下 崩れるとかで検索して出てきたページで見つけたもの。
ほかのサイトでも見てた内容のような気はするけど(IE6はバグのワンダーランドなので解説サイトは山ほどある)、 この時点まで作ってるサイトのCSSが引っかかってるとは気づいてなかった訳です。
どういうことかといえば、aタグにIDを割振ってあって、CSSの中でaタグすべてについてpaddingを設定しており、 あるIDの要素についてwidthを設定してあった為に、ぱっと見分からないけれども特定の要素に対してどちらも設定されていた、と言う話。
widthがないといかんともし難いので、paddingを削除。
書いてしまえばこれだけなんだけど、なにしろどこで何が起きてるのかさっぱり予想がつかないので、先が見えない。
先の見えないデバッグは心に傷を残します(笑)。
自分で書いたコードならどこでエラーが起きてるか見当が付くし、テストコード挟めばハッキリ分かるので良いんですが…。

JavaScriptもそうですが、ブラウザの非互換性は本当にもうどうしようか、と途方にくれてしまいますね。
もうブラウザなんて一種類で良いよ!!!とか思いましたとも(危険発言)。
そういう私がメインで使っているブラウザはOpera(シェア2%以下)だったりするんですが。
IE6のシェアも今年夏時点でまだ24%あると言うことですから、決して疎かには出来ない…。


クロスブラウザ問題は、永遠に、不滅です。

取材記と見せかけて

火曜日, 9 月 1st, 2009

ダウト。見せかけてって自分で最初からバラしてますけど。
-2009/9/2追記-作例のFlashが見られなかったのは、kenbundenをkebundenと間違えていたから+ブログ名指定(Fumiaki_KUBOTA)をしないとアップロードディレクトリにアクセスできないから、でしたorz
objectタグの対応状況も知りたいので、時計が見られなかったとか、時計が動いていないとか気付かれた方は、是非ブラウザなどの環境情報と共にコメント欄に書き込んでください。参考にします。
あ、あとコメントに何箇所かウソ書いてたのに気付いたので直しました。

取材記はこの次に来る予定です。…予定です。
一応、例の記事で宣言したとおり、今まで交互に書くのを何とか維持しているので、折角だから続けよう。
今回はFlashに手を出しました、って話です。タイトルからは欠片も読み取れませんが。
内容と関係ないタイトルをつける癖(?)はどうにかした方がいいと思うよ、自分。
真・タイトルはMTASCで始めるActionScript2.0とでもして置きましょうか。

目次

  1. 言わずと知れたFlash
  2. 微妙にマイナなActionScript
  3. MTASC
  4. 作例
  5. 気付いたこと&参考ページ等

言わずと知れたFlash
えー言わずもがなですが、皆さんAdobe Flash Playerはご存知かと思います。
ご存知、ないのですか?コレですよコレ。
皆さんもゲームとかゲームとかゲームとか、Youtubeとかニコニコ動画とか、時々アップローダとか、お世話になってると思いますが、そんな技術の話です。
ゲームばっかりだな。でもリンクしたサイトはお勧めなので、遊んでみてね(オイ)。
その昔はMacromedia Flash Playerと言いまして、Macromediaという会社が扱っていたのですが、今は昔の話です。
正確にはFlashは動画規格とそれを作るためのソフト、Flash Playerが動画を再生するためのソフト、なんですが、あんまり区別しませんね。

微妙にマイナなActionScript
そのFlashの中で、処理手順なんかを記述するためのスクリプト言語がActionScriptな訳です。
Flashは有名だけれどもActionScriptとなるとグンと知名度が下がりますよね。Google先生に拠れば、Flash->17,200,000件に対してActionScript->1,880,000と検索結果が一桁違いますね。
ベクターデータをアニメーションさせる機能と、それをボタンのように扱って次の処理を行う機能が組み合わさることで、Flashは非常に高い表現力を実現している訳ですねー。
その処理を記述するための言語がActionScriptで、ECMAScriptの拡張なので、JavaScriptの親戚と言って良いでしょう。実際瓜二つです。
とはいえ、大分違う所もあります。当然ながらグラフィック関連とか(JavaScriptの場合は基本的にグラフィカルな機能はありませんので)。
どちらにしろ、このテの言語にあまり馴染みがないので戸惑う所は多々ありますが…。
単純な処理能力は十分すぎるほどあるようです。しばしばASと略されますが、某陸戦用機動兵器とは無関係です。多分。

MTASC
普通、FlashはAdobeのAdobe Flash CS3とかCS4なんてソフトを使って作ります。
とは言えFlashの仕様は公開されているので、そこまでメジャーではないもののFlashを作成するためのツールはAdobe以外からもリリースされています。
Windows限定で良ければParaFla!とかSuzukaが開発者が日本人(つまり主要なドキュメントが日本語!)、完全フリーといった理由で日本では割とメジャーだと思います。
これらはGUIベースの開発環境で、どちらかと言えばAdobe Flashを触ったことがある人が乗り換えるような使い方を意図して開発されていると思われます。
それに対して、CUIのActionScriptコンパイラのMTASC(Motion-Twin ActionScript 2 Compiler)つーものがありまして、私はこちらを使い始めた所です。
なんていうか、やっぱりGUIは使い方を覚えるだけでも一苦労な面があるので、今回は(も?)敢えてCUIでActionScript入門してみました。
因みに、名前の通りMTASCはAS2.0対応ですが3.0対応ではありません。reademeを見ると、MTASCでAS3.0に対応する予定はないが、3.0相当なhaXeという言語を開発中なので、3.0が利用したい人はそちらをどうぞとのこと。
うーんでも折角だからActionScriptをやりたいじゃないですか。更に新しい言語に手を出すのー?みたいな。
haXe自体は謳い文句を聞く限りかなり魅力的なんだけどね…。かなり。
勿論CUI&ActionScript2.0のみの使い方では、限界も多いので、そこは他のソフトと併用することでカバーしましょう。
swf->XML->swfなんてことができる、swfmillとかそんなソフトもあるらしいです。
声を大にして言いたいのは、「Flashと言えどAdobeにお金を払う以外の選択肢もあるのだ!!!!」という事でしょうか。
Adobeに恨みはありませんが、ポイントは”金”です。…ソフトウェアベンダがどうやって開発費を賄うのかとか冷静に考えると怖くなりますが。
MTASCは特にインストールと言った手続きは必要なく、バイナリを解凍してパスを通せばもう使えます。
こういう手間の掛らないソフトってステキ。当然レジストリにも無痕跡(だと思う)。

作例
実際作ってみたよ、ということで、時計です。何の変哲もないアナログクロック。

でもワタクシ、この埋め込みタグのブラウザ互換性って所でまた詰まったり…。ここを参考に(つーかコピペ)いたしました。
ほんとブラウザブラザーズ(血縁ないだろ)には悩まされてばかりです。ふぅ。
欲しい人がいるか分かりませんが、一応ソース掲載。たったの60行余り。
あ、AS2.0はJavaScriptらしくなく(?)、割と型チェックが厳密です。あとvarは常に要ります。

class Clock{
	private var R:Number=80;//Radious-別にprivateにする意味は全くないんですが、気分の問題です。
	private var x_size:Number=240;//書き出し時のサイズ
	private var y_size:Number=160;
	private var dialPlate:MovieClip;
	private var hands:MovieClip;
	private var PI:Number=Math.PI;//単なる別名
	function Clock(){//コンストラクタ。
		var t = this;
		dialPlate=_root.createEmptyMovieClip('dP',100);//文字盤
		hands=_root.createEmptyMovieClip('h',200);//針-実はここで定義する意味はなかった
		dialPlate._x=x_size/2;
		dialPlate._y=y_size/2;
		setDialPlate(dialPlate);
		var intervalID:Number=setInterval(this,'redraw',500);
	}
	public function setDialPlate(mc:MovieClip):Void{//文字盤を作る。
		mc._visible=false;
		var texts:Array=new Array();
		var tf:TextFormat=new TextFormat('_sans',15,0x000000,false,false,false);
		for(var i:Number=1;i<13;i++){
			texts[i]=mc.createTextField(''+i,10+i,0,0,30,30);
			texts[i]._x=R*0.7*Math.sin(i*PI/6)-((i>9)?10:6);
			texts[i]._y=-R*0.7*Math.cos(i*PI/6)-10;
			texts[i].setNewTextFormat(tf);
			texts[i].text=''+i;
		}
		mc.beginFill(0xcc9966,100);//茶色の塗り色
		mc.lineStyle(5,0x333333,100);//灰色の線色
		mc.moveTo(0.9*R*Math.cos(0),0.9*R*Math.sin(0));
		var cos_N:Number=1/Math.cos(PI/8);
		for(var i:Number=0;i<8;i++){//八分割円の描画
			mc.curveTo(0.9*R*Math.cos((2*i+1)*PI/8)*cos_N,0.9*R*Math.sin((2*i+1)*PI/8)*cos_N,0.9*R*Math.cos((i+1)*Math.PI/4),0.9*R*Math.sin((i+1)*Math.PI/4));
		}
		mc.endFill();
		mc._visible=true;
	}
	public function redraw():Void{//実際に針を描画するヤツ。
		if(hands){hands.removeMovieClip()}
		var hands:MovieClip=_root.createEmptyMovieClip('hands',200);
		hands._x=x_size/2;
		hands._y=y_size/2;
		var now:Date=new Date();
		var h:Number=now.getHours();
		var m:Number=now.getMinutes();
		var s:Number=now.getSeconds();
		var theta:Array=new Array();
		h%=12;//12で正規化…というのだろうか
		theta[3]=h+m/60+s/3600;//PI/6-つまり文字の間隔-を単位とする
		theta[4]=m/5+s/300;
		theta[5]=s/5;
		for(var i:Number=3;i<6;i++){
			hands.lineStyle(7-i,0x000000,100);
			hands.moveTo(0,0);
			hands.lineTo(i*R*Math.sin(PI*theta[i]/6)/8,-i*R*Math.cos(PI*theta[i]/6)/8);
		}
	}
	static function main():Void{//エントリポイント。Clockのインスタンスを作るだけ。
		var c=new Clock();
	}
}
色々と実用性皆無な書き方をしていますね。
あんまり褒められたコードじゃありませんな。

気付いたこと&参考サイト
やーこういう短いコードだと、はっきり言って全くオブジェクト指向の意味ありませんね。
私そこまでOOP好きじゃないし。ある程度より複雑だったり大きかったりすれば確かに便利ですけど。
でもそこまで大きなコード滅多に書きませんしね。
今回は参考文献にAdobeのリファレンスは余り使いませんでした。別にAdobeに含みがあるわけではなく、MSDNもそうですがああいうサイト構成はちょっと見難いと思う。
やっぱり最後はコレを見るしかないのではありますが。
そもそもMTASCに出会う切欠になったのは、この記事です。なんか気まぐれで"actionscript コンパイラ"って打ってみたんですよね。
よく考えれば(るまでもなく)、SuzukaやParaFla!はコンパイラではないわけで…。
所詮Webの世界はテキストベースですから、MTASCって名前が分かるか分からないかで手に入る情報が全然違いますね。
MTASCと入力して一番上に出てくるのがこのサイトですね。サンプルも参考になります。
実質一クラスの極めて限られたコードしかコンパイルできませんが、swf server side compilerなんてものも公開されていますので、お試しにはいいかも。
最も、普通はパス通すだけの方が寧ろ簡単だと思いますが。出先からとか職場のPCでパス変えられなくて不便とか、そう言う時にはいいかも。
最初はいつも通りサクラエディタ使ってたんですが、良いキーワードファイルとかを探せなかったので、偶然見つけたひまわりとサクラで有名な、クジラ飛行机さんのas2editを使っています。御免なさいWindows専用です。
結構便利です。でも検索機能は実質機能してないみたい。設定が足りないか?
ASのサンプルスクリプト類は、こんな所とか、こことかを参考にしました。
ここではビルトインクラスのメソッドとプロパティの一覧がありますが、メニューにはないので、前の記事に戻って見て下さいw
ちょっとしたときに便利です。最も、引数とか分からないので、それは別個に確認する必要がありますが。そういう意味でもas2editを入れて、stdフォルダを指定する方が楽ですね。
順番が逆になりましたが、気付いたこととか。
描画用の関数群なんですが、AS2だと二次Bezierとか直線しか描画できないので、正円ですら近似して描かないといけません。
実験した所、6分割だとまだ不自然ですね。8分割だとかなり拡大しても違和感ないです。これもどっかのサイトに書いてありましたが。
直線や曲線、面それ自体をオブジェクトとして扱う機能はAS2にはありません。多分3でもないでしょう。
MovieClipよりも下の階層については、直接触るAPIは用意されていないようです。
拡大縮小してもジャギーが出ませんので、内部的にはベクトルデータが保持されているに違いないのですが、そのレベルには触れません。
識別子が尽きるからでしょうか…。
そのため、一度書いた線を消すには基本的にMovieClipごと削除するしかない、のはちょっと不便。
やはりアニメーションを提示する、といった使い方を想定されたプログラムだということでしょう。
ある程度まとまった単位で描画や変形、修正を行うことまでしか想定していません。
同一MovieClipに描いた図形は、当然同じ深度(Depth.画面垂直方向にレイヤが積み重なるイメージですね)を持つ訳ですが、実際には新しく描画されたものが単純に上書きしていく、という仕様のようです。
おそらく内部的なDepthを持っているのでしょう。また線を増やすと明確に動作が重くなりますので、生成された線一本一本についてデータが保持されているみたい。
ビットマップへの変換などは基本的に行っていない様子。Flash8以降だとそういう機能(BitMap処理)もあるようですが。
ああ、時が足りぬ…。
残念ながら出かける時間が迫っております。これにて一旦お別れでござるー。

木曜日, 8 月 13th, 2009

暫く前から見聞伝本家はAtahualpa342で動いている。のだが…。
Atahualpa342導入時、私は大いに期待していた。
特に「CSSとJavaScriptの外部化」にはちょー心躍ったのだ。
CSSを外部化するコードをatahualpaのheader.phpに書き込む、なんて邪道は要らなくなるぜ!
と無邪気に喜んだのだが…。
糠喜びでしたorz

まぁ導入する時にちゃんと調べて置けよ、って話ですけどねー。
とりあえず動作確認しただけで安心しちゃったんですよ。
気付いたのは、8/6に朝倉氏の指摘があってでした。
「何かAtahualpa新しくなってから動作遅くね?」@駒場図書館
うーんマジで?それは困るな…。と思いつつとりあえずSafariのWebInspectorを起動。
確かにどう考えても遅くなっている。しかもリロードしても殆ど速度が上がらない。
その上遅いのは件のCSSとJSっぽい。ナゼ?
というかリロードして速くならないのだから一々生成しているとしか思えないが…。
先ずはここから、とページソースを見てみれば外部CSSの記述には?bfa_ata_file=cssの文字が。
モロまんまクエリじゃねーか!
これでアクセスの度生成している疑いは濃厚を超えて限りなく黒に近いグレーに。
しかし未だ逮捕状は降りない。物証主義だから。
wpmu/?bfa_ata_file=cssにもアクセスしてみるが、圧縮(空白文字を除去)されたCSSが表示される。
アクセスにかかるラグからするとやはり生成が行われている気配が濃厚だが、詳しく調べる時間が無かった。
続きは家に帰ってから、という事でバイトに出撃する。

さて帰宅して第二ラウンド。手始めにatahualpa342の配下でbfa_ata_fileを含むファイルを洗う。
functions.phpが何かやっているので見てみる。
思えばここで道を踏み外した…。
190行目付近の記述に引っかかり、add_filter()の動作を追うべくWPMU本体のソースコードの山へ…。
この期に及んでもfilter_hookとaction_hookの辺りが良く分かってないんです。
やっぱ使ってないからかなぁ…。
なんて愚痴?はともかく、ソースを掻き分け、query_varsにbfa_ata_fileを登録しているらしい、ということは分かった。
しかしその登録されたクエリがどうやって解釈されるのかが良く分からない…。
そういうコードはどこから見つければいいんだ???などとよく分からない悩み。
この辺で8/8位ですね。この後煮詰まり感からしばし中断。

第三し…おっとっと。こんな所でゼミ長を喜ばせている場合ではないのだ(そこ?
第三ラウンドはなんと今朝から始まった。アレだけ煮詰まってたのに…。
解決する時は案外あっさり解決するものである。
今日はなんだか朝っぱらからこの間近所の図書館で借りたJavaScriptの参考書を眺めていたのだが、そしたらなんだか当たり前のことに気付いたのだ。
余談だが、私がこの手の参考書を読むのは珍しい。
大変いい世の中になったもので、大抵の言語(※もちろんコンピュータ言語デスヨ)のリファレンスやサンプルは、Webだけで手に入ってしまう。
話を戻すと、気付いたのは「結局CSSを出力する部分はAtahualpaと同じタイミングでインストールされたはずである」、つまりatahualpa342の配下に最終的に出力するためのコードが含まれているはず。
当たり前の話なんですがねぇ…。ここのところゲームとかゲームとかゲームとかに現を抜かしていたせいか、頭があんまり動いていなかったらしい。
でatahualpa342でgrepしたら「CSS」という語を含んだファイルが見つかる見つかる。
やっぱり怪しいのでfunctions.phpをあけようとフォルダを開くと…。
css.phpってファイルがあるじゃーありませんか。どう見てもこいつだろw
ナゼ最初に気付かない自分。
開けて見るとやっぱりコイツデスヨ。セットでjs.phpってヤツも居るしね…。
さてどこからこれが呼び出されているのかなーとgrepすると、functionsの私が捕まってた行から30行も下じゃない所にあったし。
細かい経緯は不明だけどbfa_css_js_redirect()って関数がtemplate_redirectってアクションにフックされているので、こいつのせいだろ。
さて結局の所、atahualpa342はCSS/JSの外部化はするが外部ファイル化はしないということが判明したわけです。
なんというか中途半端な機能だな…。これじゃーヘッダを見栄えよくする以上の意味は無いではないか。

つまるところ、旧Atahualpaとほぼ同等の手続きをとってCSSをファイルとして保存せにゃなるまい、というのが結論。
CSS関連だけ一ファイルにまとまっているのは改造しやすいけど…。Atahualpaが更新されるたびにこれをやるのかと思うとちょっと気が重いぜorz
さて改造しますか…。ついでにzip圧縮も試してみようかな…。でも圧縮ファイルが受け取れるブラウザかどうかってどうやって判別するんでしょうか?
投げっ放しでとりあえず完。

WPMU覚書1

木曜日, 7 月 16th, 2009

さて今回から数回のシリーズで、私が知る限りの知識範囲ではあるが、WordPressMUの構造と動作について書いて行きたいと思う。
今回は概要と、データベース構造くらいで。まぁ9割方自分用覚書ですが。

    目次
  1. でWordPressMUって何よ
  2. 概要
  3. データベース構成

でWordPressMUって何よ

まずはここから(しつこいね)。
まぁ公式(系)を見ましょうか。
WordPress MU、WordPressµ とは、ブログアプリケーション WordPress の複数ユーザ版(multi-user version)です。
ほうほう。つまりWordPressを複数ユーザ対応にしたものなのね。でWordPressは?
WordPress (ワードプレス) は、オープンソースのブログ/CMS プラットフォームです。
CMSはContent Management Systemだから、まとめると、複数ユーザで使う、ブログ/Webコンテンツを作成&管理するための土台のアプリケーションと言った所?プラットフォームって日本語にし難いですねぇ。
とにかく、今現在の見聞伝はこのシステムを利用しています。
便宜的に私が”本家”と呼んでいる部分ではCMSとして、他の個人ブログ(このブログとか)ではブログプラットフォームアプリケーションとして、ですね。
うーん英語をカタカナで表現すると、やたら長くなるよなー。Blog Platform Applicationだもんなー。
戯言は置いといて、次行きましょうか。
WordPressの何がいいのかと言えば、Webページの作成や編集がお手軽にできる(一応強調しておきますが、これでもかなりお手軽ですよ!)ので、グループでやる時にページ作成の負担を分担できる、というのが見聞伝で採用している理由、だと思います。
と言う訳で、皆さんがんがん記事を作って下さい(お前もな)。
あとは開発者(特にサードパーティ)が非常に多いので、様々な機能がプラグインの形で公開されており、それを利用できる、と言うのも大きな魅力でした。
とはいえ、大抵のプラグインはMUではなくて、ただのWordPress向けに作られて居るので、そのままでは動かないこともしばしばですが、それでも0から作るのに比べれば、遥かに省力です。
あとは基本的に内容とデザインが分離されているため、デザインの改造がやり易いとか、サイト全体的なデザイン設計/更新が簡単だ、と言ったことが上げられるでしょうか。
このサイト全体のデザイン設計をWordPressテーマと呼んでいる訳ですね。
そうそう、大事なことを忘れていましたが、WordPressはGPLです。改変や再配布も自由なライセンスです。そしてタダ!うーん素晴らしい。
(GPLは必ずしもタダであることは意味しません…ほとんどの場合はそうですが。)

概要

さてそんなWordPressMUですが、

  • Apache:Webサーバ
  • MySQL:RDBMS
  • PHP:CGI
が動作する環境が必要です。
これらのソフトのバージョンですが基本的には新しい方がいいです。しかしWPMUのバージョンによってこまごまと違う様なので、お気をつけ下さい(だれが?)。
ものすごーくおおざっぱに言うと、WordPressMUは、HTTPリクエストを受けると、
  1. Apacheのmod_rewriteの機能を利用して、あるディレクトリ以下へのアクセスを、全てwp-content/index.phpに集める
  2. 当初のリクエストURIから、どのブログにアクセスしているか判定
  3. 当初のURI(パーマリンク)をブログ毎に設定されたrewrite_rulesに基づいてクエリ形式(?year=2009&month=5&day=13&name=…とかそんなの)に変換
  4. クエリに基づいて、SQL文を生成し、データベースから表示する情報を取り出す(複数の投稿やページの時もある)
  5. 取り出して来た情報を、整形をして表示
と言うことをやっているらしい。細かい所把握してないことも多いけど、どうもこんな感じみたいですハイ。
今後も出てくると思うので、ここでWordPressで使う用語についてちょっと書いて置きます。
極めて誤解を招き易いことに、WordPressではややこしい用語を使います。言わばWordPress用語ですね。
投稿(Post)
WordPressで使われる、最も一般的な記事の形式。主に時事性があること-時とともに価値を減ずる様な情報とか-を記述することを意図している。メインページに表示される。
ページ(Page)
WordPressでは、通常の意味とは異なり静的な情報を保持しておくための記事の形式。階層性を持たせることも出来る。
テーマ(Theme)
サイト全体のデザインを決定するもの。各投稿やページのデータはデータベースに保持されているので、それをWebページとして表示するために使われる。
カテゴリ(Category)
記事などが所属するグループ。階層性を持たせられる。二重に所属することも可能。
タグ(Tag)
記事などに付けるキーワード。カテゴリと異なり、階層性を持たせることは出来ない。幾らでも付けられるのはカテゴリと同じ。
なんか記述がちぐはぐですが、まぁこんな所でご勘弁を。

データベース構成

WPMUのデータベース構成ですが、基本的には以下の様になっています。

  • 以下のテーブルはブログ毎に存在
    • comments::コメントを保存
    • links::リンクを保存?よく見てない
    • options::ブログの設定情報を保存している。超重要
    • postmeta::投稿のメタデータ
    • posts::投稿そのもの。実際はページも投稿も添付ファイルの情報も一緒にここに保存されている。
    • terms::タグやカテゴリーに使われた単語を保持してIDを振っている
    • term_relationships::termsに保存された単語が、どの投稿やページと関連を持っているかを保持している
    • term_taxonomy::termsに保存された単語を分類する、分類法を保持している。categoryなのか、tagなのか、とか。
  • 以下のテーブルはサイト全体で一つ
    • users::サイトに登録されたユーザの情報を保持しているテーブル
    • usermeta::ユーザの権限や、ブログではなくユーザに属する設定情報が保持されている
    • site::ドメインが保持されている。用途がいまいち分からない
    • sitemeta::サイト全体の設定。アップロード可能なファイルタイプとか、最大アップロード容量とか、利用可能テーマとか、過去のrss?とかを保持しているようだ
    • blogs::サイトにどんなブログがあるかを保持している
    • signups::良く分からない。使われていない?
    • registration_log::ユーザが承認されたことが記録されている
    • blog_versions::良く分からない。使われていない?
    • sitecategories::サイト全体で使ったtermが保持されている。実際にはcategoryに分類されないものも全部入っているので、この名前はどうかと
あ、あと前にも紹介しましたが、WordPressのデータベース構成はここを参照しましょう。なにしろコードの99%同じと言うだけあって、ほとんど同じです。
WPのデータの保存の仕方は、user friendlyというか、administrator friendlyと言うか、かなり「そのまま」です。フィールド名やキー名は見れば大体意味が分かりますし、保持されているデータも、人間の可読性を意識したものがほとんどです。
ちょこちょことデータベースから直接データをいじることを想定してあるんでしょうか。
まぁコーディングし易いってのが一番の理由ですよね…。

今回はこんな所で。既に十二分に長いし。次回からはリクエスト処理-というか呼び出し関係-を順番に辿って行きましょうか。自分のためにもなりそうだし。

暗黙のエコー

月曜日, 6 月 29th, 2009

このタイトルなんだかかっこいいよね。そんなことを意図して決めた訳ではないのですが。
名前に似合わず?コーディングネタ。

今回はWordPressは置いといて、PHPだけの話。
得てしてマニュアルと言うものは不親切ではありますが…。
いや決してマニュアルを責めている訳でもないのです。
大変お世話になっとります。
しかしぱっとよんで「そう言う理解はせんよ」と思う文章はあります。

PHPでは、他のテキストの間に、コードを埋め込むことが出来ます。こんな感じで。

<html>
	<body>
		<h3>ページタイトル</h3>
		<?php echo 'test'; ?>
		あああああ<br />
	</body>
</html>
恐らくHTMLを書いたことがある人、そしてブラウザからウェブページのソースを覗いたことのある人にとって、 <?php echo 'test'; ?>以外の部分は奇異ではないと思います。
そして(当たり前ですが)この?phpの部分がPHPのコードです。
仮にこのコードがtest.phpというファイルに書き込まれていたとすると、ブラウザで、例えばhttp://kenbunden.net/test.phpにアクセスすると、

ページタイトル

test あああああ

なんて表示になるはず。
つまり、echoの後にアポストロフィとかシングルクォーテーションで括られた文字列があると、それはHTMLに(微妙な言い方)反映されるのです。
多少は実用的な使い方を考えてみると、例えばPHPにはdate()という日付と時刻に関する便利な関数が存在します。
この関数はOSが時刻を管理するのに使っている整数値を、人間が見て分かり易い形式に変換してくれます。
一般的な場合は、1970年1月1日0時0分0秒からその日その瞬間までの秒数です。
大小を比較したりするのには便利ですが、そんな数字を提示されても人間にはいつのことだかサッパリです。
使い方についてはまぁ…マニュアルでも参照してもらうとして…。
先ほどの’test’の部分をdate(’Y-m-d H:i:s’)に書き換えると、2009-06-25 16:38:32等と表示される様に変わります。

<html>
	<body>
		<h3>時間を表示してみる</h3>
		本日は<?php echo date('Y-m-d'); ?>です。
		現在時刻は<?php echo date('H:i:s'); ?>です。<br />
	</body>
</html>
なんて書けば、

時間を表示してみる

本日は2009-06-25です。 現在時刻は16:38:32です。

なんて表示される訳です。

これぐらいのことJavaScriptでも出来る?その通りです。
しかしJavaScriptではなくPHPを使う最大の魅力は、なんと言ってもブラウザから見ている人にはただのHTMLにしか見えない、と言う点です。
JavaScriptであれば、なにやら怪しげなことが背後で行われているのはわかりますし、多少知識があれば何をやっているか丸見えです。
またブラウザを使って実行しているので、閲覧者がJavaScriptの実行を停止すると、表示もおかしくなります。
PHPであれば、閲覧者の元に届くのは処理を全て終えた後のただのHTMLなので、そういった心配は必要ありません。
(勿論PHPとJavaScriptを組み合わせて使うのは全く珍しくない話ですが)

…思えば遠くへ来たもんだ…。元々の話題は何でしたっけ?

    PHPの特徴
  1. PHPはプログラミング言語の一つである
  2. PHPはサーバで実行されるのであって、ブラウザで実行される訳ではない
  3. PHPはHTMLと混ぜて書くことができる
私が今話題にしようとしているのは最後の部分、HTMLと混ぜて書けると言う部分です。
例えばPHPでは以下の様なスクリプトが頻繁に出てきます。
<?php $i = 0; if ($i > 10 ) { ?> $iは10を超えている。<br /> <?php } else { ?> $iは10以下である。<br /> <?php } ?> このコードは、最も基本的な条件分岐を含んでいます。
つまり、変数(数学で使うのとはちょっと違います)$iが、10を超えているか否かによって、その後の動作が変化します。
因に$(ドル記号)はPHPにおいて変数を他のPHPコードの類から区別する為の接頭辞(プレフィクス)です。
プログラムはこれが先頭に来ている文字列を、変数として解釈しようとします。
説明の順序が逆になりましたが、変数と言うのはメモの様なものです。
様々な情報に名前付けをして管理するのに用います。
コンピュータの記憶領域の一部にプログラマが勝手な名前を付けて参照する仕組み、と言った所でしょうか。
さてこのコードは、以下のコード
<?php $i = 0; if ($i > 10 ) { echo '$iは10を超えている。'; } else { echo '$iは10以下である。'; } ?> と等価です。この、echoを明示的に書かなくても実質的にechoを書いたことになる点を指して、「暗黙のエコー」と勝手に呼んでいる訳です。

さて長々とここまでかかってやっと何が「暗黙」なのか書けたのですが、 マニュアルがいけないと思うのは、入門者へのこのHTMLと混ぜて使える点に関する説明がどうも不十分に感じられるんですよねー。
具体的にはこの[HTMLからの脱出]の部分です。
ここを読むと、開始タグと終了タグで囲まれている 箇所以外のすべての部分は、PHP パーサに無視されます。とある訳ですが〜。
現実問題、無視されている訳ではないのはお分かり頂けたかと思います。
なんだよちゃんと制御されているじゃん。
もう少し下を見ると、PHP は ?> 終了タグを見つけると それ以降新たに開始タグを見つけるまでの内容を何でも出力するからですってなってるんだけど、 それは無視じゃねーだろ。

実際、出力バッファリング関数群で、出力をバッファしてみると、<?php>と<?>に挟まれていない部分も、 あくまでもPHPスクリプトの出力として扱われていることがよくわかります。
でも私にはこの仕様(if文の途中で?>を書いても正常に動作する)はどーも気に食わないと言うか、違和感が拭えないと言うか…。
ヒアドキュメントなんてのもあるんだから、それでいーじゃないかと思ったりするんですよね。
うーん。

さらば700行

金曜日, 6 月 19th, 2009

さてAtahualpaの改造だが、一応当初の予定通りの動作をするものが出来た。
ソースを見てもらえば、以前はヘッダにあった長大(700行を越える)なCSSが無くなって、代わりにbfa_ata_style.cssとか、そんな名前のファイルが読み込まれる様になったのが分かると思う。
私が行った改造の具体的な内容及び手順は以下。

  1. Atahualpaの設定が更新されたことを記録するタイムスタンプをadd_optionで用意(実は必要ないが、念のため)
  2. Atahualpaのフォルダ直下にある、functions.phpを開けて、update_option()を呼び出している部分を探す
  3. 上記部分(Save Settingsを押すと呼び出される関数)の末尾に、タイムスタンプをupdate_option('option_name',date('YmdHis'))で記録する部分を追加
  4. header.phpに、カテゴリ判別してスタイルシートの名前を生成するコードを追加(以前からカテゴリ判別してCSSを書き換えていた)
  5. ファイル名を$filenameとすると、filemtime( TEMPLATEPATH . $filename)と、先ほどのタイムスタンプを比較して、タイムスタンプが大きければCSSを再生成する
  6. CSS再生成は具体的には以前のCSSを書き出していた部分の前後から、<style></style>を取り除き、前後にob_start()ob_get_clean()を配置、 バッファリングした内容を変数で受けて、ファイルに保存($filepointer=fopen($filename,'wb+'); fwrite($filepointer,$content);)
  7. 最後に、再生成をしてもしなくても、<link rel='stylesheet' href='春眠に限らず暁を覚えず'>を吐くように記述。

しかし誤算があった…。本家ブログだけでAtahualpaを使っているつもりだったのだが、そうではなかった。
木許さんのブログでもAtahualpaを使っていたのでした…。
複数のブログでAtahualpaを使うと、CSSが一種類しか生成されていないので片方の設定が更新されると、もう片方で読み込まれるCSS(同じファイル)が変わってしまい、結果奇妙なことが起きるのは想像がついていたのだが、「確か他にAtahualpa使ってる人はいないよなー、じゃあブログ判別ルーチンは書かなくていいや〜」と適当に書いた所、案の定衝突が起きました…。
現在はまずglobal $blog_idを呼び出してブログ判別を行い、更にその後カテゴリ判別をしています。
カテゴリとカテゴリIDの対応は、当然ブログ毎に違うので、この判定ルーチンはブログID毎に用意しなくてはいけないのが難点です。
今は本家以外ではカテゴリ判別を行っていないので特に問題はないけど、他でも行おうとすると中々面倒なことに。
引数としてブログIDとカテゴリIDを渡すと、ファイル名を生成するみたいな専用関数を書かないと収拾が着きませんな。
$filename=cr_fname($blog_id,$cats)みたいな。
しかも実際に吐き出すCSSの内容も変更しなくてはいけないので、中々難儀。
そうなったら変更に合わせた内容をoptionに格納してしまうぐらい必要だなー。
要らぬ心配(?)をするのでありました。

あたわるぱ。

水曜日, 6 月 10th, 2009

さてお約束通りCODINGネタ。
前回のキャッシュする作戦は一応成功したらしく、運悪く再生成する場合には、顕著に表示が遅くなる。
まぁ自己満足ですけどね。
でもアルゴリズム的に無駄な所を一カ所発見してショーック。
make_update_list()は、引数を4つ取っているのですが、当然どんな引数が渡されるかは実行時にならないと分かりません。 つまり、前回の引数と違っていたら、動作を変えなくてはいけないので、キャッシュを破棄して再生成しなくてはいけない。
そこで、再生成する度にそのとき使った引数をデータベース上に保存することにしたのですがー。
別に個々の引数が必要な訳じゃないんだから、まとめて判定してまとめて保存しておきゃーいいのに気付かず、 いちいち引数四つを個別に更新しているか判定、さらに個別に保存してまつた…。
後で直します…。

さて次の私の(自己満足の)ターゲットは、本家のあの長〜いヘッダ。アレどうにかしたい。CSSを外部ファイル化したい。とてもしたい。
その為のHeadClearnerってプラグインもあるんだけど、諸般の事情により使えないので、自作(!)しちゃえ。
自作と言う程のことは出来ないけど、Atahualpaのheader.phpを操作(ってかhack)すれば、ページに出力されるCSSが変更できるのは実証済みなので、 その出力を(場合によって)ファイルに保存しておけばいいのです。で、<style rel=”???.css”>とか書き込めば、うまくいく筈ですよね?
同じCSSを使っているページなら、外部CSSファイルを共有して、ブラウザ側でキャッシュしてくれるので、そう言う意味でもサーバ側もクライアント側も嬉しい筈。

で、方針。echoをリダイレクトします。出来るのかチェックした訳じゃないんだけど、これだけCそっくりなんだったら、標準出力への出力をリダイレクトする機能も多分あるでしょ。
CSSをモーレツに出力し始める手前で、条件分岐して、ファイルの更新日時と、タイムスタンプを比較して、もし設定が変わっているようなら、ファイル出力をやり直します。
そうでないなら素通しで。あ、あとカテゴリ毎に違うヘッダを適用するって、Atahualpaじゃ出来ないんでしょうか。Atahualpaの設定項目のほとんどは、CSSの形でheader.phpで呼び出されてしまうので、 header.phpの内容をどうにかしない限りは、どうにもならない。
今はheader.php内にカテゴリ判別を付加して強引に動かしているのですが…。
そんな感じ。いつ取りかかれるやら…。Atahualpa設定項目多過ぎですよ(泣)。

キャッシングは計画的に。

月曜日, 6 月 8th, 2009

いやはや、中々儘ならぬものと言うか、コーディングでよくあるのはうっかりミスである。
今回の、make_update_list高速化計画こと、caching(って言うのかな…)しようぜ!計画は、一応成功裏に終わったのであるが、躓いた所を列挙してみよう。

  1. OSの違いに泣くある程度の部分はローカルでテストをしたのだが、前にも書いたと思うが私の環境はWinXP+Apache2.2+PHP5.2+MySQL5.0である。Unixと違ってパーミッションが無くて云々て言う話は前もしたような気がする。今回はfilemtimeなる関数を使おうとしたのだが、これはWinでは実装されていないそうだ。ダメか。ついでにmb関数群もダメらしい。それは無いだろ。おいおい。という訳で、結局ローカルではプラグイン丸ごとの試験は出来なかったorz
    これはUnixマシンを所有せよとの神のお告げか!?(どーゆー神だ&金はあるのか)
  2. array_splice()は中々曲者であるというのも、添え字が保存されないので、foreach($array as $key => $element)の中で呼ぶと、array_splice()した部分以降の、$keyと$elementの関係がずれてしまうらしいのだ。あるいは、条件式で( $number && $x != 1)みたいなことをやったのだが、つまり$numberが0か空ではなく、しかも別の変数$xが1でないという条件式なのだが、これが意図した通りに解釈されなかった可能性もある。ちゃんと切り分けて実証はしていない。とにかくarray_spliceするループを分離してしまったら収まったので、それでよしとした。
  3. 定義リストを閉じ忘れたトップページのソースを見てもらえば分かるが、”ゼミ生ブログ集”の部分は、DIVタグで囲われた定義リスト(DL)になっている。んで定義リストを閉じる部分を吐き出し忘れた(てへ)。直ぐ気付いたが…。
  4. パスを間違えたのに気付かなかった。キャッシュを保存しているのだが、いくらやっても上手く保存できている様子が無い。この間実験した時には上手く行ったのに、何がいけないんだ…と頭を抱えていたら、スラッシュが一本足りず、存在しないディレクトリにあるファイルを開こうと頑張っていた。そらー開きませんわ。書き込めませんわ。
あとは、データベース上のブログオプションに、一部のデータを保存したくて、この間も紹介した我等がバイブルを参照していたのだが、そこでget_last_updated()なる関数を発見してしまったorz
コレ、私が苦労してデータベースにクエリ発行して取得していた情報を取ってくる関数じゃありませんか。徒労感が…。
とは言え、幾つかのデータは結局データベースにアクセスしないと、用意された関数群からでは取得できそうに無い(?)ので、まぁいいかと自分を慰めています。ハイ。或いは灰。
まぁそもそもこの関数を見つけられたのだって、関数名と引数を見れば大体どんな関数なのか見当がつくという、WPMU(あるいはWP)での命名作法に慣れてきた証ではあります。喜びましょう。悲しみましょう。
これできっと恐らく多分(随分自信ないんだな)、ブログが更新された直後にKENBUNDENトップを訪れた不運な人意外は、キャッシュされたデータでリストが作成されるので、随分表示が速くなる…といいなぁ…。

オマケ:この記事の投稿に使っているstrongタグの閉じタグを、一箇所storngと表記してしまって、変な投稿をしてしまったのは内緒である。

make_update_listを速くする

木曜日, 6 月 4th, 2009

なんとなく、コーディングのネタとそれ以外のネタを交互に書いていくことに今決めた。 次回のコーディングのネタは既に確保済みだが、ごく普通に考えるとやはりコーディングネタの方が先に尽きそうだ。 その時はその時考えよう。コーディングと言う内DNAネタに走ってみたりして…。

夜中にアイスを食べながら、なにを考えるかといえば、見聞伝トップ下部に現在表示されているアレ、何とか高速化できないものだろうか。 どう考えても、アクセスする度にあのリスト全体を生成しているのがいけないのだが、それを避けるにはやはり実行結果をどこかに保存しておくというのが順当な手段だろう。

さてどんな時にリストを生成しなくてはいけないかというと、

  • ブログが更新されたとき
  • 引数が変更されたとき
  • 結果が保存されていないとき
当然ながら、これは頻度の順である。2と3を軽く説明しておくと、このリストを生成する時には、何件表示するかなどのパラメータがいくつか設定できる。当然ながら、この設定が変更された時には、リストを生成し直さなくてはいけない。また、今回更新した直後には当然過去のリストは保存されていないから、生成して保存しなくてはいけない。 他にも、保存した結果を消去すればリストが再生成されるようにしておくと、後々便利そうである。 この条件分岐はそのまま書くと結構スパゲッティーになるので、由緒正しきフラグを使って分岐を書くことにする。

蛇足ながら説明しておくと、スパゲッティーコードとは、スパゲッティーの如くごちゃごちゃと絡まりあっていて、どの部分が何を制御しているのか分かり難く、見通しの悪いコードのことである。間違いの元になるため敬遠される。逆に、そういうコードを意図的に書いて楽しむ(?)、IOCCCなるコンテストも存在している。ニコニコ動画でしばしば見られる、「技術の無駄遣い」を地で行くようなコンテストである。

さらにもう一本足を生やしておくと、フラグというと「死亡フラグ」なんて言葉が有名になってしまっている気がするが、技術屋さんにありがち(?)な伸ばし棒や促音を略して書いているもので、ごく一般的なカタカナ表記をするなら、フラッグである。つまり旗。 条件分岐に使う条件が成立しているかどうかの目印ってだけなんですよー。別にアドベンチャーゲームに出てくるだけじゃないんだぞー。

これ以上足を生やすと蛇が百足になりそうなので、今夜はこの辺で。来週までに改造を完了したいなぁ。

奮闘記02

月曜日, 5 月 18th, 2009

えーと結論を申しますと…インストールできました。 ずばり、phpからmysqlを呼び出せるように設定してませんでしたorz

何をやってるんだか…。ApacheとPHPをインストールした時に、設定を後回しにして失敗したな。まぁローカルへのインストールは成功~。Unixと違ってWinではファイルのパーミッションとかもないし、メンド臭くないですね(セキュリティ意識のない奴め)。これからいじくるぞー。