自分のための次世代CMS製作メモ
Jeans & Development | 電子ブロック工房 | 三日坊主 | フロントページ |
骨格部分がほぼ完成 [General]
2008年1月13日
Jeans CMSの骨格ともいえるクラス郡のコードがほぼ完成。もっとも大事なクラスは、
coreクラス:Jeans初期化・htmlspecialchars互換のサニタイズルーチン・デストラクタ管理
sqlクラス:SQLite, MySQL, PostgreSQLのラッパークラス
jitクラス:スキン変数・テンプレート変数のコンパイル
の3つのクラスで、これに順ずるものは、
memberクラス:ログインを管理
actionクラス:アクションを管理
refreshクラス:スキン変数・テンプレート変数・アクションを処理するメソッドを、データベースに登録
の3つ。これら6つのクラスを、ハウスキーピング遺伝子(house keeping genes/house keeping jeans)と呼ぶことにする。
coreクラス:Jeans初期化・htmlspecialchars互換のサニタイズルーチン・デストラクタ管理
sqlクラス:SQLite, MySQL, PostgreSQLのラッパークラス
jitクラス:スキン変数・テンプレート変数のコンパイル
の3つのクラスで、これに順ずるものは、
memberクラス:ログインを管理
actionクラス:アクションを管理
refreshクラス:スキン変数・テンプレート変数・アクションを処理するメソッドを、データベースに登録
の3つ。これら6つのクラスを、ハウスキーピング遺伝子(house keeping genes/house keeping jeans)と呼ぶことにする。
デストラクタの利用に関する規約 [Regulations]
2008年1月10日
デストラクタ処理ルーチンがほぼ完成。デストラクタは、次の規約に沿って利用するようにする。それぞれのクラスでオブジェクトのインスタンスが一つだけ必要な場合、$objという名でスタティックに作成する。
1)プラグイン
基本的に、プラグインのデストラクタは、他のプラグインのオブジェクトに依存しないこと。もし依存する場合は、個々のデストラクタ内で適切に処理すること。ただし、ライブラリの各機能は使用可能。
2)ライブラリ(sqlクラス・coreクラスを除く)
基本的に、ライブラリオブジェクトのデストラクタは、他のライブラリオブジェクトに依存しないこと。もし依存する場合は、個々のデストラクタ内で適切に処理すること。ただし、sqlクラス・coreクラスは利用可能。
3)sqlクラス
coreクラス以外のライブラリのオブジェクトに依存しないこと。
4)coreクラス
いかなるオブジェクトにも依存しないこと。
1)プラグイン
基本的に、プラグインのデストラクタは、他のプラグインのオブジェクトに依存しないこと。もし依存する場合は、個々のデストラクタ内で適切に処理すること。ただし、ライブラリの各機能は使用可能。
2)ライブラリ(sqlクラス・coreクラスを除く)
基本的に、ライブラリオブジェクトのデストラクタは、他のライブラリオブジェクトに依存しないこと。もし依存する場合は、個々のデストラクタ内で適切に処理すること。ただし、sqlクラス・coreクラスは利用可能。
3)sqlクラス
coreクラス以外のライブラリのオブジェクトに依存しないこと。
4)coreクラス
いかなるオブジェクトにも依存しないこと。
スキン変数<%blog%> [General]
2008年1月6日
スキン変数の<%blog%>は、最も重要な機能の一つ。今のところ次のように記述しているが、変更の余地は大いにあるのでメモしておく。
SQLテーブルの値を一気に読み込むべきか、個々にクエリーを発行するべきか。 [General]
2008年1月6日
jit.php のinit()で、次の命令によりskinvar, templatevarのテーブルが一気に読み込まれる。
これに要する時間は、クエリーの発行に約150μ秒、フェッチには一件当たり約7μ秒である。jit.phpでは、コンパイルの際にすべてのskinvarデータが必要だから、上記のように一度に読み込むのが最も効率が良い。一方で、個々にSQLクエリーを発行したほうが効率が良い場合もある。例えば、一つのページを表示する際に、テーブル中の一つのデータしか必要でないときなど。このケースでは、quickQuery()メソッドで一つ一つ呼び出すのが良い。
では、その中間ではどのように処理すればよいか。例えば、メンバー情報などは一つの例である。多数のメンバーが居る際、一つの表示ページ中に記事の著者が一人の場合はquickQuery()の方が早い。他方で、複数の著者の記事を含むページを表示する際は、quickQuery()の方が早い場合と、一気に読み込むほうが早い場合とがある。
self::unbuffered_query('SELECT subtype, name, method FROM jit_skinvar WHERE type=<%1%>',$type); $data=array(); while($row=self::fetch_array()){ $data[$row['subtype']][$row['name']]=$row['method']; }
これに要する時間は、クエリーの発行に約150μ秒、フェッチには一件当たり約7μ秒である。jit.phpでは、コンパイルの際にすべてのskinvarデータが必要だから、上記のように一度に読み込むのが最も効率が良い。一方で、個々にSQLクエリーを発行したほうが効率が良い場合もある。例えば、一つのページを表示する際に、テーブル中の一つのデータしか必要でないときなど。このケースでは、quickQuery()メソッドで一つ一つ呼び出すのが良い。
では、その中間ではどのように処理すればよいか。例えば、メンバー情報などは一つの例である。多数のメンバーが居る際、一つの表示ページ中に記事の著者が一人の場合はquickQuery()の方が早い。他方で、複数の著者の記事を含むページを表示する際は、quickQuery()の方が早い場合と、一気に読み込むほうが早い場合とがある。
クラスに空の内容のメソッドを持たせるべきか持たせざるべきか [General]
2007年12月30日
現在の仕様では、新しいクラスが呼び出されたときに、init()メソッドが存在すればそれを呼び出す仕組みになっている。クラスによっては、init()メソッドは必要ではないのであるが、その場合は、init()メソッド呼び出しの際の命令でWarningが発生する(@を用いているので、表示されない)。
このようなケースに、空の内容のinit()メソッドを記述しておいたほうが早いのか、何も記述しないほうが早いのか、調べてみた。
このようなケースに、空の内容のinit()メソッドを記述しておいたほうが早いのか、何も記述しないほうが早いのか、調べてみた。
テンプレート機能の動作を確認 [General]
2007年12月27日
スキン変数<%blog%>を作成して、テストしてみた。新たにblog.phpを作成したが、これは将来的にskin.phpに統合する可能性が高い。
jit.php [General]
2007年12月27日
スキンパースの、<% %>→<?php ?>変換部分をjit.phpとして独立させ、テンプレートのパースルーチンもここに加えた。
アイテムのパースは、ここでは行えない。というのは、コンパイルされたindex.phpではスキンパース・テンプレートパースはすでに行われているが、アイテムのパースは表示するごとに行う必要があるためである。アイテムのパースに同じルーチン(jit.php)を呼び出すと、スピードの上で効率が良くない。
そこで、アイテムパース時に必要なitemvarの情報は、各アイテムに埋め込むことにして、アイテムパース部分はjit.phpから独立させることにする。例えば、
testitemvar|class::method/testitemvar2|class::method/
などの文字列を記事保存時にアイテム用のテーブルに保存しておき、アイテムをパースする時に、この情報に従ってpreg_replaceする。
…かな?現在のところ、jit.phpは170行ほどだから、これをskin.phpに戻してアイテムパースもここから行うほうがいいのかも。
考え中。
アイテムのパースは、ここでは行えない。というのは、コンパイルされたindex.phpではスキンパース・テンプレートパースはすでに行われているが、アイテムのパースは表示するごとに行う必要があるためである。アイテムのパースに同じルーチン(jit.php)を呼び出すと、スピードの上で効率が良くない。
そこで、アイテムパース時に必要なitemvarの情報は、各アイテムに埋め込むことにして、アイテムパース部分はjit.phpから独立させることにする。例えば、
testitemvar|class::method/testitemvar2|class::method/
などの文字列を記事保存時にアイテム用のテーブルに保存しておき、アイテムをパースする時に、この情報に従ってpreg_replaceする。
…かな?現在のところ、jit.phpは170行ほどだから、これをskin.phpに戻してアイテムパースもここから行うほうがいいのかも。
考え中。
別ファイルに分けるべきか、分けざるべきか [General]
2007年12月27日
手元の環境で調べたところ、PHPコードのパース(JITによるコンパイル)には、平均して一行あたり約2.5μ秒かかっている。一方で、一つのクラスをファイルから呼び出すのに、最低500μ秒が必要。例えば、100行からなるファイルだと、2.5×100+500=750μ秒。現在までに8つほどクラスを作成したが、コードのパースにかかる時間は、ほぼこの計算値と一致している。
どの機能を別のクラスに分けて、どの機能は分けずに同じPHPファイル内に置くかの決断が難しい。別のクラスに分けることで500μ秒のロスがあるわけだから、クラスを分ける場合、このロスを解消できるだけの見返りが必要である。あまり細かくファイルを分けてしまうと、かえってスピードが遅くなってしまう。
どの機能を別のクラスに分けて、どの機能は分けずに同じPHPファイル内に置くかの決断が難しい。別のクラスに分けることで500μ秒のロスがあるわけだから、クラスを分ける場合、このロスを解消できるだけの見返りが必要である。あまり細かくファイルを分けてしまうと、かえってスピードが遅くなってしまう。
規約 [Regulations]
2007年12月26日
Jeans CMSで、コア・プラグインを書くときの規約(案)
1)グローバル変数、グローバル関数は利用しない(スーパーグローバルは除く)。
2)include, require, include_once, require_once は使用しない(index.php, config.php, core.php を除く)。
3)echo, print は使用しない(core.php を除く)。HTMLタブを出力するときは『core::echohtml()』を、タブ以外を出力するときは『echo::p()』を利用する。
4)SQLクエリーを作成するときは、『sql::fill()』もしくは、『sql::query()』の、フィリング機能を利用する。
5)『sqlite_query()』などのデータベース関連関数は直接利用せず、代わりに『sql::query()』などを利用する(sqlite.phpは除く)。
6)SQLiteでクエリー用の関数を作成する場合、原則としてMySQLやPostgreSQLなどでも利用できるものを使う。ただし、SQLiteの機能を最大限に利用するようなプラグインを作成する場合はこの限りではない。
7)プラグイン名は『jp_』から始まり、英数字のみ(アンダースコアは含まない)。『jp_プラグイン名_クラス名』という名のクラスを『jp_プラグイン名_クラス名.php』というファイル名で記述し、このphpファイルをプラグイン管理領域におけば、インクルードはコアが自動的に実行してくれる。
1)グローバル変数、グローバル関数は利用しない(スーパーグローバルは除く)。
2)include, require, include_once, require_once は使用しない(index.php, config.php, core.php を除く)。
3)echo, print は使用しない(core.php を除く)。HTMLタブを出力するときは『core::echohtml()』を、タブ以外を出力するときは『echo::p()』を利用する。
4)SQLクエリーを作成するときは、『sql::fill()』もしくは、『sql::query()』の、フィリング機能を利用する。
5)『sqlite_query()』などのデータベース関連関数は直接利用せず、代わりに『sql::query()』などを利用する(sqlite.phpは除く)。
6)SQLiteでクエリー用の関数を作成する場合、原則としてMySQLやPostgreSQLなどでも利用できるものを使う。ただし、SQLiteの機能を最大限に利用するようなプラグインを作成する場合はこの限りではない。
7)プラグイン名は『jp_』から始まり、英数字のみ(アンダースコアは含まない)。『jp_プラグイン名_クラス名』という名のクラスを『jp_プラグイン名_クラス名.php』というファイル名で記述し、このphpファイルをプラグイン管理領域におけば、インクルードはコアが自動的に実行してくれる。
テンプレート [General]
2007年12月26日
member.phpのログイン部分は完成。こちらの方は、Nucleus SHA encryption edition で経験済みだったので、それほど時間はかからず。特筆する点はそれほど無い(Nucleusとほとんど代わらない)が、一つの特徴は、メンバーログイン用のデータベースは、他のものから独立していること。これはセキュリティーを考えてのことで、仮にどこかでSQLインジェクションがあっても、パスワードやメールアドレスなどが洩れないようになっている。
また、skin.phpを少し改良し、parse_ifメソッドの中で呼び出しメソッド名の解決を行っていたのを、コンパイル時に解決しておくようにした。
次にテンプレート周りを完成させれば、あとはNucleusのスキン変数・テンプレート変数処理部分を次々と移植していくだけ。で、ここ2-3日、テンプレートの仕様を考えている。
また、skin.phpを少し改良し、parse_ifメソッドの中で呼び出しメソッド名の解決を行っていたのを、コンパイル時に解決しておくようにした。
次にテンプレート周りを完成させれば、あとはNucleusのスキン変数・テンプレート変数処理部分を次々と移植していくだけ。で、ここ2-3日、テンプレートの仕様を考えている。