はてなキーワード: バグフィックスとは
みんな大好きPostgreSQL。
複数DBマルチテナントシステムを構築するなら忘れてはいけないコネクションプーリング。
大量コネクションを扱うなら都度forkやpre-fork式ではちょっと辛い、イベントベースが好ましい。
もうお分かりですね。pgbouncer1.6の話題です。
PostgreSQL界隈では有名なコネクションプーリングの実装が2つあります。 pgpool-II と pgbouncer。
ざっくり言うと高機能の pgpool-II に対して、軽量・大規模向けの pgbouncer という棲み分けがあると言えるでしょう。
pgpool-II は最近は日本の トレジャーデータ社の Prestogres ( https://github.com/treasure-data/prestogres ) という痺れるようなプロジェクトのベースとして採用されていることで名前を聞いたことのある方もいるのではないでしょうか。
pgbouncer は少し古いですが LastFM( http://www.lastfm.jp/user/Russ/journal/2008/02/21/zd_postgres_connection_pools:_pgpool_vs._pgbouncer )の事例が有名でしょう。Instagram も使ってますネ。
pgbouncerは現行のバージョンは1.5系で、最新は1.5.5です。1.6系は8月1日にリリースされ、複数DBマルチテナントシステムに向けた大規模な機能強化が行われています。
この1.6系では複数DBマルチテナントシステム開発者にとって嬉しい機能がたくさん搭載される予定です。本番運用に投入する前に一足お先にリリースノートを読んで夢を感じましょう。
本バージョン、2013年ぐらいからリリースノートは準備されているのにさっぱりリリースされなくて関係者をやきもきさせていました。(想像)
本記事では以下のリリースノートをもとにザックリ読み解いたものです。
http://pgbouncer.github.io/2015/08/pgbouncer-1-6/
・接続ユーザーやパスワードハッシュをDBからロードできるようになった
・プーリングモードの設定をデータベース毎、ユーザー毎に設定できるようになった
・データベース毎、ユーザー毎にコネクションの最大接続数を制御できるようになった
・新しいコネクション確立を避けるための DISABLE/ENABLE コマンドが追加された
・新しい推奨のDNSバックエンド c-ares が追加された
・設定ファイルに include ディレクティブを追加した
新しく以下のパラメータが追加された
1.5までのpgbouncerは userlist.txt というテキストに静的に接続ユーザを書かなければいけませんでした。
これは動的に接続先ユーザーが増えるようなマルチテナントシステムを構築するのに不向きという事です。
タイトルがすべてを物語ってます。柔軟にできますねぇ('∀`)
ただ、私にはちょっと有用な利用シーンが思いつかなかったです。
たとえば分析用ユーザーではトランザクションなんて使わないので statement モードにしてコネクションの消費を抑えたりできるという事でしょうか。
max_db_connections と max_user_connections という設定が追加されます。
テナント毎にユーザーを分けているような複数DBマルチテナントシステムにとって必須といえる機能です。
特定のユーザーのリクエストにコネクションをすべて占有されてしまい、他のユーザーにサービスできないという事態を避けることができるようになるでしょう。
特定のデータベースの新しいコネクション確立を抑止・再開することができます。
c-ares は名前解決の非同期化を行うためのライブラリです。c-aresは名前解決をブロックしないし、いろいろな方式の名前解決に対応している唯一のプロダクトとのこと。
名前解決をブロッキングしてしまうようではpgbouncerのような大規模向けシステムでは役に立たないのだというpgbouncerの強い意志を感じる。
というか、ドキュメントを見る限り pgbouncer は名前解決にかなりこだわりを持っているらしい。それだけそこが重要ということでしょう
(個人的には困ったことがないのでそこまでだわる理由はよくわからない。)。
UNIXドメインソケットで接続しているクライアントと、TCPまたはUNIXドメインソケットで接続しているサーバーでremote_pidを取得できるようになりました。
tcp serverの場合、pid はキャンセルキーから取得できる。(?ドキュメントから意味が読み取れず)
キャンセルキーとは何でしょうね。ちょっとリリースノートからは判断できませんでした。
pg_cancel_backend とかに使えるPIDだよという事なのでしょうか。
DBの数なんてもはや何台あるかわからない。ホスト名の解決はもはやDNSで行っておるよという皆様にとって必須の機能。
…なのでしょうが、ちょっとこの機能が必要となるようなシステムとはどんなものなのか、私も未経験なのでよくわからないです。
この設定は application_name_add_host=on にすることで有効となる。
今や接続元アプリケーション名がWebだとかBatchだとか区別できるだけで問題が解決するような時代ではない。
どのホスト(ポート)レベルで区別しないと。という事なんだろう。
「おお、Webサーバーから死ぬほど重いクエリが飛んでる、今すぐ調べないと!で、どのWebサーバーよ?100台あるんだぜ」みたいなときに助かりますね。
設定ファイルが大規模化してくると、切り出して整理したいという要望はどうしてもでてくるもの。
データベース毎、ユーザー毎に設定できる項目が増えてきたので必要になったという事でしょう。
以降はバグフィックスとかクリーンアップだとかで自分はあまり興味がないので各自読むように。
本番運用に突撃するPostgreSQL界の猛者の報告待ってます。
アプリケーションを完成させるにはテストを終わらせなきゃダメなんだよプロジェクトマネージャー。
キミは本当に頑張ってるが、
テストをちゃんとやらなくても納品すりゃ終わるというキミの思い込みが、プロジェクトをダメにしたんだ。
何度もリリース日を延期して仕切り直すチャンスが与えられたのに、
顕在化しているバグの修正日数だけを計上して、何とか納品に漕ぎ着けようとしてるのが致命的だ。
終わってないテストを終わった事にしたって、バグは消えてくれないんだよ。
せめて「まだできてません」と言えば良かったのに、「できました」でまともに動かない代物を客に渡して、
それでどうなるかも判らないくせにプロマネか。
客の信頼は既に地に落ち、リリースしたところでバグだらけの代物では毎月平謝りとデータ修正・バグフィックスに忙殺されて、他の業務に支障を来すのはもう確定的だ。
付き合いきれない主力メンバー2人も去った。
うちの部署は消えるだろう。
その原因にキミ自身が気づくかどうかは知らんけどね。
コミュニケーションスキルを駆使して情報を自分のところだけにかき集めてメンバーに「由らしむべし知らしむべからず」の方針を取ったのはキミだ。
僕の知ったこっちゃない。
せめて仕切りなおすタイミングで一度でも打ち合わせをして、僕達に「アプリを完成させるのに後何が必要か」を共有する機会を作っておけば、
仕切り直しは一回で済んでたんだ。
こうなっちゃ僕達じゃプロジェクトを救えないし、勝ち目のない戦いを勝てる気でいるキミのために健康や生活を犠牲にしてやるつもりもない。
こんなインパール作戦みたいなプロジェクトに関わり続けるのは御免だ。
どうすればいいの?
最初の2,3ヶ月は少しは期待して懇切丁寧に教えてみたけど、
「それは私にはわからない」とか「好みの問題だ」(実際には副作用ある危険な実装だった)とか言って受け入れてもらえなかった。
「早急なバグフィックス」を免罪符に、コードはどんどん荒んでいった。
他にも数名チームメンバはいてそこまでひどくはないものの、動けばいいというメンタルモデルは同じらしく、レビューもまともに機能していない。
ツールやら手法やらも試してみても、使うメンバの意識がなければ全く役に立たない。
そんなこんなを画策しているうちに、精神が参りそうだったので、自分で適当にコメントをつけて修正するのが最善であるという結論に至ったんだけど、
先に言っておきたい。LINEは確かに便利だけれども、運営があまりにもサボりすぎである。
LINEゲームに労力を割きすぎているのではと、勝手に思ってる
あ、僕はそこらの大学生ですよ、誤解なきよう
(個人的には高校・浪人時代のメールの返信を待ってる時間が好きだったけどなぁ、時代は変わっちゃいました笑)
で、表題の件だけれども、以下に書いてみた。時間ない人はまとめだけ読んで下さい。
※まとめ
iPhoneのLINEが強制アンインストール(またはアイコンが消えそうになってる)されてる時は
その場で機内モードにすると(なぜか)防げた
数時間前のことの流れはこんな感じ。
ーーーーーーーーーーーーーーーーーーーーーーーーーー
↓
LINEのアイコンが暗くなって揺れていて、「削除中」の途中だった。
(焦ってて細かく覚えてない、Appの自動更新はオフにしてるから、アップデート時の不具合ではない。原因不明)
↓
↓
↓
機内モードにする
↓
↓
iPhoneは機内モードのまま、怖いからiTunesでバックアップ
http://appllio.com/line-transfer-and-restore-talk-history-completely#h2_1
http://did2memo.net/2012/09/21/naver-line-how-to-move-talk-history/
※この時PC版LINEでは購入したスタンプが消えていた。トークは閲覧可
↓
(キャッシュがかなり消えていたみたいで、友達のトップ画をロードしたりと。)
ほんとにトーク内容消えなくてよかった・・・
一安心。
ーーーーーーーーーーーーーーーーーーーーーーーーーー
運営いいかげんにしろや、LINEゲームのCM流してる暇あるなら、LINEアプリのバグフィックスしろ!!!!!
国内トップのシェアあるからって、天狗になってんじゃねーよ!!!!
※無料ってのには感謝しますけど、不具合多すぎ、利用人数考えて下さい。もはやインフラです。昔のキャリアメールの代わりですから、その辺、もう少し責任をもって下さい。
こういうふうに、minifyしないのは見やすさを残して後で簡単に変更出来るようにするためだ!
とか言う馬鹿が沢山いるんだけど(それもはてなでの大御所?的なひとから明らかにプログラマー()的なひとまで)
そもそも、元のコードははてなの中にはあるわけで、この外に出てくるコードを直接見ていじるわけではないわけで、
これをminifyしても大したこと無いから別にしない、ってのは実際問題そうだと思うし別にどうでもいいんだけど、
それに対する反論が余りに馬鹿すぎるでしょう、と。
後、反応が大きかったのは「コメントを残してる」というところではなくて、
おばかゆとりぷろぐらま()のテンプレにも出てきそうな余りにびっくりするようなコメントを実際に見てしまって
笑ってしまった、というだけの事なのに。
というか
「よく分からないけど〜」とか
「ここは難しいのでとりあえず放置」
とかむしろ分かってて敢えて面白がって書いて、ユーザーが見つけてくれたら面白いなって敢えて仕込んでるだけじゃないのか?とすら思うんだけど。
はてなは最近迷走している。ある調査だとアクセス数が落ちているという。アクセス数が増えないことを別の方法でカバーしようとまた余計なことをして顧客ばなれを招くという悪循環に陥っていると。新しいサービスは軒並み失敗中だ。
なぜか。それは顧客が求めているものを分析せず、表面的に考えているからだ。社員が顧客ではなくとなりの同僚の方をみて仕事をしているからだ。
それを表す顕著な事例があったので書かせてもらう。
http://emija.hatenablog.com/entry/2014/03/11/231940
はてなブログが遅いのはだいたいJavaScriptのせい
こんな記事があがった。
要点を絞るとこうだ
また、この情報に対する他の顧客から、minifyを実施するのは常識であって、なぜそれを行わないのかという指摘があった。
http://developer.hatenastaff.com/entry/2014/03/14/125131
また、この情報に対する他の顧客から、HACCPを取得しそれによって管理するのは常識であって、なぜ行わないのかと言う指摘があった。
それに対して
今回のはてなの対応で何か改善した事は何もない。元の顧客が感じた「遅い」という問題は解決していない。
はてなの中では「お前のせいで遅いのだろう」と言う汚名を返上できたと言う内々の評価はあろうかとおもうが、そんなものが顧客に何の関係があるのか。最大限評価してもこう言う的外れなクレームに晒された経験のある一部のニッチな同類技術者が多少の賛意を得られ、彼や彼女らの評価が若干上がる程度だ。
多くの人は重たいページに出会ったとき、その場で評価を決めて次に去ってしまう。そこで技術論をいくら述べてもほとんどの人間はそれに興味が無い。
クレームを上げてくれる人間などほんの僅かだ。さらに分析までしてくれるというのは顧客としてはその分析が多少間違いでも最優秀だろう。そこで自社のプライドを守るためだけの話に終始し、顧客の問題を放置するなど、一体何を考えているのか。
書くべきエントリーは
「はてなブログにおけるページ表示速度改善の取り組みについて」ではなく
「はてなブログの表示をより高速にするためのTips」であるべきだった。
内容はいきなり技術論から始め、顧客の推論を否定する等ではなく
「はてなブログは速度も最大限になるように努力しておりますが、ユーザの皆様の環境によっては読み込みが遅く感じる事もあると思います。読み込み速度を重視する皆様に、よくある速度を遅くする原因と、できるだけ快適にするためいくつかチェックするポイントをまとめました」
として
といった事をきちんと書き、顧客の「遅い」という問題の解決を図る。
そして最後に
「ご参考に、弊社ではできる限り高速なサービスを提供出来るよう、様々な工夫をおこなっています」
として、今回のこの「はてなブログにおけるページ表示速度改善の取り組みについて」エントリーの一部を掲示し、やんわりと顧客が推測したことは間違いだと否定する形にするべきだった。(当然ながら社内コストがかかるからやらないとか余計なことは書かない)
そして、今回のような説が広がったことが営業的にマイナスであると考えるのであれば、今後は誤解を与えないように誤解を与えた原因を修正する。(誤解する相手を変えることは不可能)
食品工場の例なら、客が不衛生な環境に置いたのが悪いのだというのではなくて、清潔で乾燥した場所に置けと言う事をやんわりと伝え、最後に自社の衛生環境に対する取り組みを伝えるべきだ。その後でまた誤解を受けないようにペンキ屋でもなんでも手配し、対外的に説明のしやすくなるHACCP認定取得を目指すという事になるだろう。
はてなはブクマガールズなど試験的なものをリリースしている。今度はニュースアプリにも参画しようという。これは従来のはてなユーザ以外にも顧客を広げたい意向があるのだろう。そうでなければ企業としての成長が難しいからだ。
確かにはてなはエンジニアの利用者が多い。だからはてなの内情を察知してくれ、技術の話をしたらそれにもきちんとついてきてくれる。しかし、今後もそんな優しいユーザだけ相手にするつもりなのか?彼らは技術の事を話をすれば、なるほどそれは仕方が無いと納得してくれるだろう。だが果たしてそんな姿勢で、顧客を増やせるのか?
はてなブックマークのデザイン改悪が実施された頃からいろいろとおかしくなった。それ以前はなによりベータ版を提供していたし、それによって得たフィードバックを反映していた。しかしそのあたりから指摘を受けると間違っていないと言う言い訳はするものの、顧客が困っていることについての解決策を示さなくなった。顧客が出すクレームよりも、となりにすわる同僚が同意してくれることを重視していないか?
もう一度考え直せ。このままでいいのか?
ユーザとしては全くよくない。いい加減しっかりしてくれ。
どうもわかってないな。
minifyは開発手法だとする意見。常識を理由にするのでは技術者失格だし、技術者じゃないのなら「もうちょっと周囲のコメント読んで」といった所。作り話(≠例え話)でないと対抗できない時点で勝負ありと思うがどうか
解決ではなくて「問題なし問題なし」と言い続ける奴らが回り回ってはてなを駄目にしてる。はてなを甘やかすなと言いたい。
そんなのは枝葉。
そういう技術論ばかりやって本当に客が必要だったものを用意できないのがはてなの最近の駄目さなんだよ
例えば、LINEが自社で使ってる技術をアピールする事で客を集めてるか?
もしLINEが技術をアピールする戦略をとったら、今のような形になれていたと思うか?
その上で"尖った"技術力がどんどん無くなっているのがはてなの現状。ベンチャー企業ってのはそういうもん。これは別に悪い事じゃない。ただそれ以外にウリを作り出せないとじり貧だろう。
http://anond.hatelabo.jp/20140315033741
実際に見て欲しいんだけど、そんなに広告多い?
具体的には分からない。
ただはてなは顧客から寄せられたクレームにおける推測部分を否定だけしたが、顧客が抱えている問題に対して答えを出していないのは確か。
そこに書いてあるようにはてなが言うべき回答例として挙げた部分は、例えばそういうことが言われているので書いた例程度に思ってくれ。
当然ながら、はてなはきちんと分析して回答するべき。顧客が投げてきた疑問を否定するためだけに無駄に時間を使う暇があるならできるはずだ。
http://anond.hatelabo.jp/20140315042727
http://emija.hatenablog.com/about
その人も技術者らしいんだけど
バグフィックスやiOS6最適化をさせた最新のAdMobを載せたい!→AdMob SDK 6.2.0を使ってね。あ、でもこのバージョンのAdMobはiOS5以下ではUDID取得するから(あと、iOS6ではadvertising identifier使うから)アプリ側の責任でそのことはちゃんとユーザに告知してね☆
あれ、今まではUDID使わないバージョンがダウンロードできていたと思うけど、それどこ行ったの? 6.2.1とかないんですか。
え、iPhoneでAdMob使うなら、ユーザに「IDFA/UDIDを使ってもいい?」って同意をとったことを確認した上じゃないと使えない? めんどくさくね? 端末がユニークになるようにトラッキングしないと広告出せないの?
はまちちゃんの手法の問題点は、脆弱性を直せる立場の人よりも先にクラッカーに脆弱性を教え、しかもその利用方法まで実証し解説してみせていることにある。
なお、「先に」と書いたのは、はまちちゃんがクラッキング手法を披露した時に、理論上はサービスプロバイダもクラッカーも同時に知りうるはずだが、実際のところ、はまちちゃんが突く程度の穴を作る開発者ははまちちゃんのblogをチェックしておらず、他方クラッカーは手軽な情報源としてチェックしている可能性があるからだ。また、バグフィックスよりもクラッキングの方が早いため、どうしてもはまちちゃんに教示されたクラッカーのアタックの危険に曝される時間ができてしまうからだ。
サービスプロバイダがいつまでも直さないなら、あの「カンチョー程度の」教示も親切と呼べるかもしれない。
しかし、まずサービスプロバイダに直す機会を与えなければならない。
はまちちゃんはblogでクラッキング手法を披露する前に、まずはサービスプロバイダに「貴社サイトには◯◯という脆弱性が有ります。直す予定があるのか、直す場合はいつまでに直すのかを、◯月◯日までに返答してください。」と脆弱性を報告し、返答期限を無視し、あるいはまともなバグフィックス予定を示さなかった場合に、初めてカンチョーするべきなのだ。
(カンチョーするに至った場合であれ、殊勝にもカンチョー前に直された場合であれ、blogでネタにするのはかまわないだろう。)
ところで余談だけれども、「内臓露出」した患者に対し「カンチョー」しているというのは比喩として不正確ではないか。
はまちちゃんは脆弱性自体を突いているのだから、比喩においても失態と攻撃が部位的に一致していなければならない。
「(アナルの)隙」に対しては「カンチョー」で対応が取れているが、「内臓露出」に対しては対応が取れていない。内臓に粉末ハバネロを吹きかけるとか、そういう喩えにならなければ対応しない。
おそらく脆弱性を「内臓露出」と派手にしてみたものの、内臓を攻撃してしまうとはまちちゃんの攻撃が正当だと言いづらくなる為、あえてカンチョーを維持して読者の印象を操作しようとしたのではないか。
PhotoshopCS4とIllustaratorCS4アプリの体験版をちょっと弄ってみた。以下はその感想メモ
アプリ全体のウィンドウはVistaっぽくなった。表示操作に関する機能が取り出されてメニューより上の段に並べられ扱いやすくされている。
書類のウィンドウは2種類の状態があり複雑になった。一つはFlashのように書類エリアにハメ殺しになっている状態と書類ごとにウィンドウに分かれた状態。そしてそれぞれで単独の書類を表示している状態と複数の書類をタブでまとめている状態を持っている。少し分かりにくい。実際は自分が作業しやすい一定の状態に落ち着くので問題はないと思われるが「並べて表示」での挙動が違ったりして消化し切れていない印象が残る。
パネル(旧パレットウィンドウ)とドックはCS3から少し洗練され、操作時に思わずクリックしてしまうクローズボタンはドック内では表示されなくなった。
また、スクリーンを共有するというどこかで見たような機能が追加された(β版らしい)。こういうのは諸々のコンセンサスの得やすい社内チーム間とかで使うのだろうか。VersionCueもそうだけど不可視の概念とか設定とかで面倒そうだと使う気にならないなあ。
今回の変更点は分かりやすい。CS3でもGPUに演算させていたそうだが、さらにGPU利用のスムーズなズームとカンバスの見た目だけの回転(回転ビュー)が追加された。特に回転はPhotoshopで絵を描く人にはありがたいだろう。一部でペンツールに補正機能が付いたといってるようだがこれは元からあったブラシオプションの「滑らかさ」がデフォルトで付くようになっただけのようだ。
もう一つ大きな変更は3Dペイントらしいのだがちょっと分からない。何しろすごく重くて弄る気がなくなってしまった。グラボを奢ってる人はいいかもしれない。
写真の自動編集機能も機能強化されている。複数の画像を用いたピント操作(レイヤーを自動合成)はCS3より精度が良くなっている。被写体を除いた背景の自動拡大縮小(コンテンツにあわせて拡大縮小)も追加された。しかし触った所では「自動」ゆえにコントロールできず画像を上手く加工できなかった。既存の機能で手作業したほうが思い通りに扱えるのではないか。
ほかにもスタンプツールの複数コピー元対応とかマスクの編集パレットなど地味ながら使い勝手を向上する変更もある。
残念なことにメニューリストや書類ウィンドウにリフレッシュされない目障りなバグがあるがこれはグラフィックボードに依存して再現されるのかもしれない
総合するとPhotoshopで絵を描く人には要アップデートだがそれ以外の人には別にどっちでもよさそう。
のっけから言わせてもらうとIllustrator CS3は欠陥商品であった。オブジェクト操作に数字にでない誤差(?)が出るバグがあり、カラーパレットには指した値が指定できないというとても不細工なバグがあった。その不具合が直っただけでもアップデートする価値がある。というかさっさとパッチで対応して欲しかった。
大きな変更点は複数アートボードの取扱いが可能になったこととブラシの復活だろう。従来から数ページものの印刷物ならIllustratorで作られたりしていたわけで、そのへんの機能強化ともいえる。でもマスターページも自動ノンブルも無くてどうするのかなと思う。PDF変換が楽とかそういうものかもしれない。
ブラシは既存ブラシのようなパスにシンボルを貼り付けて変形させている機能と違って、10年前、Illustrator 5.5まではあった描画した線の輪郭にパスが付くブラシ機能である。前回との違いはFlashとの統合を意識してか重ねて描いた部分が1つのオブジェクトに結合される所だ。使い勝手が直感的でいいと思う。
あとパネルの改良がされている。カーソルをあっちこっち動かさずにすむよう、その場で設定値パネルを開けるようになっている。いいねえ。
ほかにもDreamWeaverやFireWorksも弄ってみて、CS3の時も思ったが正直メジャーアップデートするほどの更新があっただろうか疑問だ。旧Macromedia製品だからだろうか。
AdobeはCS Suiteというパッケージを売り出してからSuiteのためだけにバージョンの数字を上げているだけに見える。新製品で特定のもの以外、あまり魅力的でなくとも現状のままではSuiteで丸ごとアップグレードせざるをえない。抱き合わせ商法である。個別製品以外に更新意欲がわかないようなバージョンアップをするならSuiteから個別製品へのアップグレードを認めてほしい所だ。
前の60行テンプレートエンジンを改良して、レイアウトテンプレート機能を追加してみた(それでも全部で90行)。
レイアウトテンプレート機能とは、例えば個別のテンプレートが<table>...</table>を出力して、それをレイアウトテンプレートが<html><body>...</body></html>で囲って出力するとかそんなの。
詳しくは終わりの方のサンプルをみてくれ。
これは Ruby on Rails(とその仲間たち)にある便利機能のひとつ。
ついでにいうとSmartyにはない機能のひとつ。
今まで知らなかった人はぜひ試してくれ。チョー便利だから。
前回はたくさんのブックマークありがと。
コメントで「男前テンプレート」と名前がついてたので、勝手に採用。
あと、これ以上の機能追加はしないので、各自勝手に改造して使ってくれ(そのためにコメントをつけてるから)。何でも人任せにするな。
コード:
<?php /* * OtokomaeTemplate.php -- レイアウトテンプレートに対応した90行のテンプレートエンジン * * - レイアウトテンプレート中で echo $_content; とすると中身が表示される。 * - テンプレート中で設定した変数をレイアウトテンプレートで使うことが可能。 * - レイアウトテンプレート名をテンプレート側で指定することも可能。 * - 使い方: * require_once('OtokomaeTemplate.php'); * $TEMPLATE_DIR = 'templates'; // 省略可、パーミッションに注意 * $LAYOUT_TEMPLATE = 'layout.php'; // 省略可 * $context = array('title'=>'Example', * 'list'=>array(10,'<A&B>',NULL)); * include_template('template.php', $context); * - 要 PHP 5.1 or later * - ライセンス: public domain (自由に改造してね) */ /* * 設定用のグローバル変数 */ $TEMPLATE_DIR = NULL; /* テンプレートを探すディレクトリ */ $LAYOUT_TEMPLATE = NULL; /* レイアウトテンプレートのファイル名 */ /* * テンプレートを読み込んで実行する。 * $_context は変数名をキー、値を要素とする連想配列。 * $_layout はレイアウトテンプレートのファイル名。 * - NULL または省略した場合は $LAYOUT_TEMPLATE を使う。 * - FALSE ならレイアウトテンプレートを使わない。 * - $_context['_layout'] = '...'; とすればテンプレート側でも指定可能。 */ function include_template($_filename, $_context, $_layout=NULL) { global $LAYOUT_TEMPLATE; $_content = render_template($_filename, $_context); if (@$_context['_layout'] !== NULL) // テンプレート側で指定された場合は $_layout = $_context['_layout']; // それを使う。 elseif ($_layout === NULL) // 引数で指定されなかった場合は $_layout = $LAYOUT_TEMPLATE; // デフォルトのファイル名を使う。 if ($_layout) { $_context['_content'] = $_content; // レイアウトテンプレート中で使う変数 $_content = render_template($_layout, $_context); } echo $_content; // or return $_content; } /* * テンプレートを読み込んで実行し、その結果を文字列で返す。 * include_template() の実体。 */ function render_template($_filename, &$_context) { $_cachename = convert_template($_filename); extract($_context); // 連想配列をローカル変数に展開 ob_start(); include($_cachename); // テンプレートを読み込んで実行 return ob_get_clean(); } /* * テンプレートファイルを読み込み、convert_string() で置換してから * キャッシュファイルに書き込む。読み込み時のロックは省略。 * (file_get_contents() もファイルロックできるようにしてほしいなあ。) */ function convert_template($filename) { global $TEMPLATE_DIR; if (! file_exists($filename) && $TEMPLATE_DIR) $filename = "$TEMPLATE_DIR/$filename"; $cachename = $filename . '.cache'; if (! file_exists($cachename) || filemtime($cachename) < filemtime($filename)) { $s = file_get_contents($filename); $s = convert_string($s); file_put_contents($cachename, $s, LOCK_EX); // LOCK_EX サポートは 5.1.0 から } return $cachename; } /* * テンプレートの中身を置換する。 * - '#{...}' を 'echo ...;' に置換 * - '%{...}' を 'echo htmlspecialchars(...);' に置換 * - ついでにXML宣言も置換 */ function convert_string($s) { $s = preg_replace('/^<\?xml/', '<<?php ?>?xml', $s); $s = preg_replace('/#\{(.*?)\}/', '<?php echo $1; ?>', $s); $s = preg_replace('/%\{(.*?)\}/', '<?php echo htmlspecialchars($1); ?>', $s); return $s; } ?>
<?php require_once('OtokomaeTemplate.php'); $TEMPLATE_DIR = 'templates'; $LAYOUT_TEMPLATE = 'layout.php'; $context = array('list'=>array(10,'<A&B>',NULL)); include_template('template.php', $context); ?>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <body> <h1>%{$title}</h1> <div id="maincontent"> <!-- テンプレートの内容 --> <?php echo $_content; ?> <!-- /テンプレートの内容 --> </div> </body> </html>
<?php // レイアウトテンプレート名をテンプレート中で指定する場合 ?> <?php //$_context['_layout'] = 'mylayout.php'; ?> <?php // レイアウトで使用する変数をテンプレート中で指定する場合 ?> <?php $_context['title'] = 'レイアウトのサンプル'; ?> <table> <?php foreach ($list as $i=>$item): ?> <tr bgcolor="#{$i % 2 ? '#FFCCCC' : '#CCCCFF'}"> <td>#{$i}</td> <td>%{$item}</td> </tr> <?php endforeach ?> </table>
出力例:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <body> <h1>レイアウトのサンプル</h1> <div id="maincontent"> <!-- テンプレートの内容 --> <table> <tr bgcolor="#CCCCFF"> <td>0</td> <td>10</td> </tr> <tr bgcolor="#FFCCCC"> <td>1</td> <td><A&B></td> </tr> <tr bgcolor="#CCCCFF"> <td>2</td> <td></td> </tr> </table> <!-- /テンプレートの内容 --> </div> </body> </html>
いくつか補足: