Posts Tagged ‘覚書’

ブラウザの壁

木曜日, 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%あると言うことですから、決して疎かには出来ない…。


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

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と言うか、かなり「そのまま」です。フィールド名やキー名は見れば大体意味が分かりますし、保持されているデータも、人間の可読性を意識したものがほとんどです。
ちょこちょことデータベースから直接データをいじることを想定してあるんでしょうか。
まぁコーディングし易いってのが一番の理由ですよね…。

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

愚痴めいた技術的文書

月曜日, 5 月 4th, 2009

半ば以上覚書である。これをこのBlogに書く意味があるのか気になるが、 もしかしたらWPMUで困っている他のヒトが見つけて喜ぶかもしれないので、敢えて書く。

さて私のWPMU暦は1月程度である。いや、以下か。 とりあえず、みんなのバイブルへリンクを張っておく。

さらに、私が参考にしまくったページを挙げておこう。

  1. CODEXの中のデータベース概要
  2. 関数リファレンス
  3. 英語版の、WPMU_Functions
  4. 同じく、Global_Variables

そもそも私が本格的にWPMU向けコーディングを始めたのは、某サイト管理者から、 「こんな感じの出力をしたい」と相談を受けたためである。 RSSワカンネと思いつつ、参考資料として渡された、コレのソースを解読するのが、私の作業の始まりであった。

SQLシラネと思いつつも、適当に見当をつけて、 自分のブログにテスト記事を投稿して反応を見、 大体把握する。重要だったのは、

$blog_list = $wpdb->get_results( "SELECT blog_id, last_updated FROM " . $wpdb->blogs. " WHERE public = '1' AND archived = '0' AND mature = '0' AND spam = '0' AND deleted ='0' " . $order . " " . $limit . "", ARRAY_A );
このへんと、
get_blog_option( $bid, "blogname");
このへんであった。

この時点では理解していなかったが、最初のget_resultsの方では、 先ほどリストで挙げた、グローバル変数のテーブルからデータをひっぱて来ている。

そしてなんだかんだやっていて、投稿のデータをどうやって取得するかが問題になった。 最初はこの関数が使えないかと思ったのだが、どうやらコレは特定のブログにおいてだけ使える(ブログをまたいで記事を取得できない)らしいことが分かった。

んー。どうしたものか…。なにやら検索を繰り返しているうちに、この関数に辿りつく。しかし、最新の投稿のpost_idなんてどうやって取得するんだ?分からん。。。

しばらく眺めていると、get_blog_postの$wpdb->get_row();を、$wpdb->get_results();に変えたらどうなるかなーと思いつく。この頃になると、大分SQL文の構造が分かってきたのである。 そこでとりあえずWHERE句を消して、get_resultsに置き換えたものを走らせて見る。 怖いので、自分のblog_idだけにしておく。

おお!なんか上手くいったみたいだぞ?

こうなりゃこっちのものである。帰ってくる構造体がデータベース概要にあった、wp_postsであることも分かったので、WHERE句で欲しいデータを検索できるようになる。さらに、ORDERで当初はdateの降順にしていたのだが、last_modified降順の方が適切な気がしたので、そうする。

こうして骨組みが出来上がった。 この辺でやっと最終的にどうやって実行するか考える。 うーんやはりプラグインにすべきか…?この段階でようやっと、プラグインの作り方を読み始める。 テンプレートタグとして作るなら、特に何も考えずに関数を書けばいいだけらしい。 そうすることにした。しかし上記ページを読んでいて、コーディング基準に従ってください、とあったのでリンクを飛ぶと、

オレの書き方と全然違う…。しかもデータベースにはなるべく触るなと書いてある…。 「止むを得ない場合を除き」だからまぁ良いか…。と言いつつも、当初は全部データベースから直接データを取得する方法で書いていたのを、できる所は用意された関数を使うように改める。

この辺で、要素技術は大体そろった。しかし、定番であるが、くっつけると何かしらエラーが出るモノである。大体、変数名が食い違ってるとか、書き足した行末にセミコロンがないとか、そんなくだらないことなのだが、WordPress上にPHPを書き込んでも、エラーメッセージは出ない。当然だけど…。しかも、データベースなどWP上じゃないと意味を成さない変数関数が山ほどあるので、ローカルで実行してエラーを洗い出すわけにも行かない。

しょーがないから、上のほうから意味を成すブロックごとに区切り、書いてはプレヴュー、の繰り返しでエラーチェックをしていく。さっきまでエラーが出ておらず、今回の更新でエラーが出たなら、足した部分がおかしいはず、ということで。

意外だったのが、コメントを途中で書き込んでもちゃんと処理される、ということ。 最初はテキストエディタに書き込んだコードをWPに貼り付ける際いちいちコメントを消していたのだが、結論から言うと必要ない作業だった。

それから、これはPHPの仕様かもしれないが、空文字列かどうかの評価が上手く働かなかった。 つまり、ある文字列$strがあったら、if($str=”)とやっても予期した結果が出ない。 PHPManualを見て、空文字列はFALSEに評価されるとあったので、if($str)にして、ifのブロックとelseのブロックを入れ替えたら、大丈夫だった。

あと、どうもヒアドキュメントはWPMUでは上手く動かないらしい。

これもPHPの仕様かもしれないが、文字列の中で(もちろんダブルクォートでクォートした場合の話であるが)変数はきちんと展開されるのだが、関数は中括弧{}で囲んでも、全くパースされない。記憶が正しければ、普通のPHPだったらコレでも大丈夫だった気がするのだが…。