今週はNFSシフトを買う気満々だったのですが、たまたまデモをプレイして買うのを止めました。
なんでレースゲームになっちゃってるんだよ。
NFSはチェイスゲームだろう。
レースがしたけりゃForza買うっての。
とある魔術の禁書目録19
☆☆☆☆☆
お前一発キャラじゃ無かったのかよ!
てか、初登場時はこんなプラスなキャラじゃ無かったような気がするんだが。
まあ女性キャラはやたら多いがカップルの少ない本作では珍しいバカップルなので、今後も是非登場願いたいところではありますが最近主人公影薄くない?
あと、どうでもいいんだが科学側って層薄いよね。
魔法の料理かおすキッチン3
☆☆☆☆
リョーリングストーンで魔法の力を手に入れたヒロインが悪役達をやっつけるお話が昔の少女漫画タッチで描かれます。
とりあえず必殺技を紹介してみると、マジカル茶巾絞り(敵を茶巾で包んで以下略)、マジカルミキサー(敵をミキサーに突っ込んで略)、マジカルおろし金(敵を…)……大体方向性はわかったと思いますが、そういう内容です……そういう内容だったのは最初の方だけでした。
最終巻となる今巻で登場するのはスケベとシュールと童貞とラブ?コメだけです。
整合性とか伏線とか気にしていては始まらないお馬鹿漫画なので心せずに読むべし。
キツネル可愛いよキツネル。
ゲームサイドVol21
☆☆☆☆
ダライアスとゲームボーイ特集
ダライアスはYAMATOが出てないのだけが残念だったがけっこう読み応えがあって良かった。
まあワンコインクリアできるほどプレイしたのはツイン、外伝、Gダラだけなんですが。
あとサーガイアとサターン版IIを持っていたくらい。
しかしバーストは何故PSPなんだろうなあ……据え置きが良かった。
さて、今回はいつもより読み物記事が充実していた印象。
まあ私がついて行ける作品が多かっただけなのかもしれませんが。
唐突に次回から季刊に戻ってしまうことに。何故だ。
BTOOOM!01
☆☆☆☆
はい、ゲームサイドの記事見て買いました。
解説は一言で済みます。
リアルボンバーマン。
いきなり浚われて爆弾持たされて殺し合ってもらいますってそれなんてバトルロワイヤル……いや、どっちかというとクリムゾンの迷宮かな、雰囲気的に。
まあ上記と違って7人殺せばOKという比較的緩いルールなので大丈夫……なわけは当然無く、生死隣り合わせのサバイバルゲームが始まります。
どうも主人公以外の人物が殺し慣れているような連中ばかりでどこの戦場帰りだよ、という気もしないでもないですが、そのぶん主人公の卑小さが際立って極限状況感がアップします。
こんなゲーム実現しようと思ったら国家レベルじゃないと無理だろとかいうのはありますがそういう細かいことは気にしない。
「あんな思いをあと6回もくり返すのか…?」
最初のチップ回収してなかったように見えるんだが。
うん、もっと細かいことを気にしていたのは俺だった。
RPGW(・∀・)rld3
☆☆☆☆
MMORPGをプレイしてたらゲーム中に入っちゃったというクリスクロスから、もしかしたらクラインの壺から連綿と続いている仮想現実もの。
珍しいのはレベル1からではなく、その時点でのキャラクタのレベルからいきなり始まっちゃった点。
またゲーム内の登場キャラクタがNPCではなく自由意志を持っている人間ということで、ゲーム外からやってきたキャラとのギャップや差別化が面白いところでもあります。
ゲーム内キャラが数十年かけてレベル20とか30とかにるというところにいきなり外部から50とか60とかの素人に入ってこられた日にはどうかと思うわな。
ただそんな強キャラでも決して無敵というわけではなく、戦力と戦術によってはどうにかなる程度の力の差になっています。
本作では作中最強クラスのレベルを誇る主人公が負けるかもしれない、と挫折し、そしてなお立ち上がる様が描かれます。
まあいいんだけど現代人の高校生がここまで覚悟完了できるものなんかね。
2日目は設計だけなのでスルーということで。
前回プロジェクトとアプリケーションを作りました。
今回はモジュールを作成します。
がその前に、とりあえずデータベースと接続アカウントを作成します。
CREATE DATABASE `jobeet` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE `jobeet_dev` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE USER 'jobeet'@'localhost' IDENTIFIED BY 'jobeetpass';
GRANT ALL PRIVILEGES ON `jobeet` . * TO 'jobeet'@'localhost';
GRANT ALL PRIVILEGES ON `jobeet_dev` . * TO 'jobeet'@'localhost';
次に、O/RマッパをデフォルトのPropelからDoctrineに変更します。
何故Doctrineを選んだかって言われても特に深い意味はありません。
config/ProjectConfiguration.class.phpの
$this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin'));
となっている行を
$this->enableAllPluginsExcept(array('sfPropelPlugin', 'sfCompat10Plugin'));
に変更します。
見ての通り、sfPropelPluginとsfCompat10Plugin「以外を」使用する、という設定になります。
で、sfCompat10Pluginって何?
Doctrineを使用可能にするために以下のコマンドを実行します。
>php symfony cc
>php symfony plugin:publish-assets
Propelで使用していた以下のディレクトリ、ファイルを削除します。
web/sfDoctrinePlugin/
config/propel.ini
config/schema.yml
config/databases.yml
データベース情報を設定します。
>php symfony configure:database --name=doctrine --class=sfDoctrineDatabase "mysql:host=localhost;dbname=jobeet" jobeet jobeetpass
config/databases.ymlが作成されるので、中身を編集します。
| all: doctrine: class: sfDoctrineDatabase param: dsn: 'mysql:host=localhost;dbname=jobeet' username: jobeet password: jobeetpass dev: doctrine: class: sfDoctrineDatabase param: dsn: 'mysql:host=localhost;dbname=jobeet_dev' username: jobeet password: jobeetpass |
このようにすることで、index.phpからアクセスした場合はallの方のDBが、frontend_dev.phpからアクセスしてきた際はjobeet_devのDBが自動的に使われるようになります。
今後拡張子がymlのファイルがよく出てきますが、これはYAMLというデータ形式です。
スペースが意味を持つ形式なので、勝手にタブにしたりスペースを広げたりといったことはできません。
XMLのように面倒なタグなどを考える必要が全くないので、データを突っ込むのに非常に便利な形式となっています。
ということで次にYAMLでスキーマファイルを作成します。
http://www.symfony-project.org/jobeet/1_2/Doctrine/ja/03からconfig/doctrine/schema.ymlをそのままコピペ。
スキーマファイルとは要するにデータベースの設計図です。
これを書いておくと、DBからデータを読み込んだり逆に書き込んだりする際の助けになります。
それどころかDoctrineではスキーマファイルからCREATE TABLE文を作成してテーブルを自動作成したりといったことまで行うことができます。
というわけで一件便利なスキーマファイルですが、データベースの設計変更があった場合の修正が非常に面倒という問題があります。
自動作成コマンドだとテーブルの中身が綺麗さっぱり削除されたりするので運用開始後に設計変更とかが入ってきた場合どうにもならないんですよね。
この点、データベースからスキーマを取得してくるCakePHPとは真逆の思想です。
スキーマファイルの準備ができたら以下のコマンドを実行します。
>php symfony doctrine:build-model
>php symfony doctrine:build-sql
>php symfony doctrine:insert-sql
順にモデルを作成するコマンド、テーブルを作成するSQLを作成するコマンド、SQLを実行してテーブルを実際に作成するコマンドになります。
build-modelを実行すると、lib/model/doctrineディレクトリ内にテーブル毎にモデルファイルが作成されます。
これを編集することで、データの挿入や検索等をカスタマイズすることができるようになります。
最後に
>php symfony cc
としてキャッシュを削除し、作成したモデルを読み込むようにします。
これでスキーマとモデルが完成しました。
次にテストデータを登録します。
直接SQLを作成する必要はなく、スキーマ同様YMLファイルに記述しておき、それをコマンドで突っ込むことになります。
チュートリアルではこれがよい方法とか言っていますが、既存データを残しておきたい場合はどうするんだよといった疑問には答えてくれません。
data/fixtures/categories.ymlおよびdata/fixtures/jobs.ymlをそのままコピペ。
他に追加したいデータがあれば同じ形式で追加します。
といってもモデルオブジェクトとか意味がわかりませんが。
fixturesを保存した後、
>php symfony doctrine:data-load
を実行すると各YMLからデータを読み込んでデータベースに入れてくれます。
同時に該当のテーブルにそれまで蓄積されていたデータは全て消えます。
これだけやってようやくモデルの作成という下準備が終了しました。
モジュールを作成してみます。
>php symfony doctrine:generate-module --with-show --non-verbose-templates frontend job JobeetJob
jobeet_jobテーブルを閲覧、登録、更新、削除するモジュールができました。
ブラウザから
http://symfony.localhost/frontend_dev.php/job
とかそんなかんじでアクセスすると閲覧することができます。
どうなってるの?
さあ?
Symfonyの記事一覧
渚あああああああああああああああああああああ!!!!
CLANNAD
実績1000/1000
CLANNADは人生
CLANNADは人生。
人生というより家族といった方がしっくり来るのは確かだが、まあ確かに人生と言っても間違いではあるまい。
本作は二部構成になっています。
第一部は、はっきり言って普通のギャルゲーです。
確かに多くのシナリオは作り込まれていて見所は多いし細かな分岐や整合性も整えられており名作と呼ぶにふさわしい出来ではありますが、それでもジャンルとして見るならば「名作ギャルゲー」の域を出るものではありません。
ましてや人生などと称えられることなど無かったことでしょう。
問題は第二部。
第二部は渚エンドの続き、という立ち位置ですが、そこで描かれるのは安易なハッピーエンドではありません。
高校生同士でちちくりあってハッピーエンドでめでたしめでたし、というゲームが世には溢れていますが、ではその後どうなったかに思いを馳せると、めでたいとはとても思えないシナリオも数多く存在します。
このシナリオでは、そんな"その後"の世界を思う存分見せつけられます。
変わりたいと願った彼、変わりたくないと願った彼女。
いつしか彼女は変わることで強くなり、いつしか彼は変わらないことで弱くなった。
彼女を蝕む"何か"、それは同時に彼女の源でもあり、世界の象徴でもある。
変わっていく、変わっていってしまう"町"が最後に見た夢は。
お約束
キャラランキング一位は言うまでもなく渚。
第一部だけなら別のキャラのが上ですが、あのアフターは反則だ。
いつの間にかとてもとても強い子に成長した渚、でもそんな彼女を待っていたのは幸せなだけの毎日ではありませんでした。
それでも強く前向きに生きていこうとする渚に惚れない男がいるだろうか。いや居ない。
第二部がなければ一位の座をもぎ取っていたはずの彼女の名は、それはことみ。一ノ瀬ことみ。
基本的に共通しているはずの主人公の背景設定を捏造してまで作り上げた過去と現在の繋がりもさることながら、このシナリオが最も好きな理由は、仲間が居ることです。
大抵のギャルゲーでは、個別ルートに入ってしまえば他の女性は出てこなくなってしまいます。
それまでどんなに仲が良くてもいきなり何故か問答無用で排除。
酷い話もあったもんです。
本作では多くのシナリオで複数の女性を絡ませるなど相当の努力はなされていますが、それでもやはりハブられるキャラはどうしても出てきてしまいます。
ゆきねえやことみは旧校舎ルートに行かない限り出てこなくなりますし、風子は存在すら削除されてしまいます。
あれだけ絡みのある渚や杏ですらフェードアウトしてしまうことだってあります。
そんな中、最後まで多くの仲間が揃っているのがことみです。
何故か春原だけ居なくなってしまいますが、朋也、渚、杏、椋、そして仁科に杉坂と多くの友人と一緒に笑っていられます。
まあことみが好きな最大の理由は、ことみ好きだあああ!!!なんですがね。
有紀寧と早苗は完璧超人過ぎて却ってついて行けません。なにこの現人神達。
まあ実際私が朋也になったとしたら資料室に入り浸るのは間違いないけどな。
むしろ何で他に入り浸っている連中が居ないんだと。
杏は嫌いではない、というか本来非常に好きな部類のキャラなんだが、どうも一点引っかかる。
なんというかあれだ、轢き逃げは普通に犯罪ですから。
椋は椋ルートが杏ルートの引き立て役にしかなっていなかったことが残念すぎる。
実際杏ルートのほうが椋もかわいいし。
何かの山を乗り越えることでヒロインとの結びつきを高めるというギャルゲーによく見られる手法は本作にも取り入れられていますが、何故か椋ルートだけそれがありません。
お陰で他のキャラに対してシナリオが少し霞んでしまっています。
もうちょっと杏ルートのちょっぴり強気な椋みたいなかわいさがほしかったところだ。
あと杏ルートの最後のあれを本人が聴いていないというのはどうなんだろう。
智代は残念。
相手が雲の上の存在になってどうするかと思いきやどうもせず、結局相手が自分のとこまで堕ちてきて終わりとか。
智代のキャラ自体は悪くないのにシナリオががっかり過ぎる。
春原は嫌い。
こいつ基本的に屑ですから。
たまにかっこいいこと言ってますが、これってあれだろ、不良がたまたま一回子猫に優しくしただけですげーいい奴に見える効果だろ。
早苗とのデートが彼の本性ですよ。
だからといって虐待レベルの暴力を繰り返す朋也や杏もどうかと思うが。
また、主人公以外のルートが用意されているのが特徴的で、面白いところでもあります。
バカップルを見守るだけのルートだったりやたら分岐が凝ってる野球ルートとか無闇矢鱈といい話で終わったりするルートといったなかなかよくわからないシナリオがあったりなかったりして、恋愛ばかりで食傷したときの箸休めにいいかんじ。
全シナリオ合わせるとテキストもフラグ管理も相当膨大な量になっています。
幻想世界
さて、シナリオベタ褒めの本作であるが、根幹となる部分でひとつ文句を言いたい。獣についてだ。
設定資料を見ていないのでポイントを外しているのかも知れないが、とりあえず言っておきたい。
設定資料によると無機的な獣は自然を破壊する建機であり、迷子から助けてくれたのはだんご大家族であり、雪から助けてくれた小さな獣はヒトデだということらしい。
がっかりだ。
建機は自然を破壊し、"町"を削り、町の姿を変えていきます。
姿の変わった町に現れるのは、ファミレスであり、病院であり、高速道路です。
"町"を削った後にファミレスが出来、渚がそこで働き、人々が集い、町は発展していきます。
渚が命を受け取った場所に病院が出来、隣町まで行かなくても医療を受けられるようになりました。
病院なだけに多くの別れや負の感情もあるかもしれませんが、それ以上に病気や怪我の治療、新たな生命の喜びもあるはずです。
高速道路は特に描写はありませんが、道路が通じることで流通や交流が増え、町が発展するといったこともあるでしょう。
それなのにそれらをネガティブにしか捉えられない"町"。
迷子になったガラクタを助けに来た獣は高速道路を通ってきた何物かであり、雪に埋もれた二人を助けてくれたのは町を行き交う人々。
そんな解釈をしていたのに台無しだ。
朋也は街灯を立て、配線を行い、電気工事を行います。
朋也が働けば働くほど、町の景観は変わっていきます。
朋也が渚のために働くこと、それ自体が渚を破壊することになっていたのでしょうか。
何故だんご大家族はOKなのか。
建機は駄目で植物ならOKなのか。
だんご大家族は自然を壊さないからOKなのか。
だんご大家族の工場は自然を壊さないのか。
だんご大家族の工場は町の中には無く、"町"を破壊しないからOKなのか。
何故ヒトデはOKなのか。
建機は駄目で彫刻刀ならOKなのか。
ヒトデには風子の心がこもっているからOKなのか。
ヒトデのために木々を伐採するのはOKなのか。
ヒトデのための木々は"町"のものではないからOKなのか。
ファミレスや病院や高速道路には設計者や建築者や利用者の心がこもっていないから駄目なのか。
"町"の視点は歪んでいる。
過去のゲームレビュー
チュートリアルに従って学習を進めていきます。
いつものように文体が教える形式になっていますが、単にその方が書きやすいというだけで、基本的に自分が学習するために書いてます。
あまり気にしないが吉。
とりあえず真っ先にSymfonyの問題点を挙げておくと、APIの日本語リファレンスが無い。
習得にあたり、SmartyやZFがほぼ完全なリファレンスを提供しており、CakePHPも不完全ながら主要コンポーネント等については一覧を用意しているのに対し、大きなハンデとなっています。
あるのはチュートリアルのようなものばかりです。
http://symfony.xrea.jp/
http://www.symfony-project.org/jobeet/1_2/Doctrine/ja/
英語版は存在しますが、"form_tag"で検索しても何も出てこないなど、何処に何があるのか先に知っておかないと使えないという全く意味のないリファレンスになっています。
単にフォームを表示したいだけなのにオブジェクトがどうとかメソッドがどうとかいった内容をデザイナーに押しつけるという馬鹿げた発想が無くならない限り、積極的に使いたいとは到底思えないんですが。
確かにエスケープやフォームの肩代わりをしてくれるのは楽といえば楽なのですが、そのぶん参入障壁も非常に高くなっているので、入口を整備しないとなかなか入り込めないのですが。
あとフォームやDBの内容を取得すると無駄に馬鹿でかいオブジェクトが入ってくるので、var_dump()等目視によるチェックが行いにくいというのも難点です。
なにやらいきなり文句ばかりになりました。
最終日までに解消されればいいのですが。
インストールそのものは簡単です。
チュートリアルではダウンロードして解凍してといったことが書かれていますが、Pearを利用した方が楽です。
コマンドラインから
> pear channel-discover pear.symfony-project.com
> pear remote-list -c symfony
> pear install symfony/symfony
とするとPEARパッケージとしてインストールされます。
今回はバージョン1.2.9。
次にプロジェクトを作成します。
ディレクトリ構成なんかを簡単に作ってくれるバッチファイルがあります。
プロジェクトを作成したいフォルダに移動し、コマンドを一行打つと完了です。
勿論先にphpとsymfonyにパスを通しておきます。
> cd C:\xampp\htdocs\symfony
> symfony init-project jobeet
> symfony init-app frontend
サブドメインを作成します。
httpd.confを編集。
| NameVirtualHost *:80 <VirtualHost *:80> DocumentRoot "C:\xampp\htdocs\symfony\web" DirectoryIndex index.php ServerName symfony.localhost <Directory "C:\xampp\htdocs\symfony\web"> AllowOverride All Allow from All </Directory> </VirtualHost> |
hostsに
127.0.0.1 symfony.localhost
以上を追加することで、
http://symfony.localhost/
でC:\xampp\htdocs\symfony\webがDocumentRootになります。
まあ、元々
http://localhost/
でC:\xampp\htdocsにアクセスできるようにしているのでこのディレクトリ構成だとセキュリティ的には全く意味がありませんが。
根本からディレクトリを分け、プロジェクト作成後に現れるwebディレクトリだけが外部公開され、それ以外のすべては外部から見えないところに隠される、という状態にすべきです。
以上でjobeetプロジェクトと、frontendアプリケーションが作成されました。
同時に開発環境も作成されます。
http://symfony.localhost/index.php
http://symfony.localhost/frontend_dev.php
というURLでそれぞれアクセスできます。
データベース等を開発環境用と本番用で分けたりするといったことができる他に、開発環境では実行したSQLや発生した例外の内容などを見ることができるようになっています。
とりあえずアクセスすると、CSSも画像も認識されず状態になっていました。
開発環境で使用する画像は何故か全然別のフォルダに入っています。
私の場合
C:\php5\pear\data\symfony\web\sf
とかいうところにありました。なんで。
sfディレクトリをwebディレクトリ内にコピペするか、シンボリックリンクで参照できるようすると、インデックスにアクセスできるようになります。
チュートリアルではhttpd.confを設定しろみたいな話になっているのですが、DocumentRootやAllowOverride等は仕方ないとして、たかがWebアプリケーションのためにわざわざhttpd.confでエイリアス設定させる思想ってどうなんですかね?
さて、上記の記事を書いたときには公式のコマンドはinit-projectだったはずなのですが、今見たらいつのまにかgenerate:projectに変わってました。
何故。
どちらを使用しても結果は同じになります。たぶん。
Symfonyの記事一覧
今週はどえらい散財してしまった。
だが反省はしていない。
後悔はしている。
ヘヴィーオブジェクト
☆☆☆☆
全長数十メートル、圧倒的な攻撃力と防御力によって核攻撃にすら耐え、既存の戦車や戦闘機といった戦闘手段を一気に過去の遺物に押しやってしまったオブジェクト。
そんな物体同士の戦いに生身で挑む羽目になってしまった一般人のお話です。
どう考えても陰惨な話にしかなりそうにないというか一撃でストーリー終了以外の展開が思いつきませんが、何故かコメディになっていました。何故。
基本的に頭を空にして読むタイプの本なのであまり深く考えてはいけません。
面白いのは主役級キャラ男二人の掛け合いで、ヒロインは基本的に空気です。
さて先日、数十個の爆弾処理ミッションを成功させてきた伝説の兵士が死亡、というニュースを見て本作のことを思い浮かべました。
http://gigazine.net/index.php?/news/comments/20091105_legendary_eod/
やはり現実には主人公補正など無いんだな。
ソードワールド2.0リプレイ 拳と魔封の物語2
☆☆
昔誰かが何処かで言ってたような気がするんだ。
設定に凝りすぎるといいこと無いと。
バブリーズのころはやりたい放題の野放図といった感じのリプレイが多かった気がするのですが、2.0のリプレイはどうも設定が決まりすぎててGMの筋道から外れられない、そんな印象を受けることが多いです。
シナリオ集とかノベルとかではなくせっかくのリプレイなんだから、もっと螺旋を外してもいいのではないかと。
真伝勇伝・堕ちた勇者の伝説5
☆☆☆
相変わらず話が進まないね、この人は。
真になったら超スピードアップするよ、とかいう話をどこかの後書きで見たような気がするんだが気のせいだったようです。
今巻のあらすじを紹介してみます。
ルシル・エリスが化け物になるまでの話。
ああ、一行で終わってしまった。
まあ、ついつい読み進めてしまう文章、内容の面白さはあるのでいいのですが、このままあかほりのような駄文製造機に成り下がり果てないことを祈ります。
せんせいになれません6
☆☆☆
やっぱり小坂俊史はこうだよな。
どうしようもないダメ教師達によるダメ日常漫画。
中央モノローグ線はやっぱりなにかの間違いだったんですよ、きっと。
しかしさすがにそろそろ池田の犯罪行為は出版コードの壁を越えそうな気がしないでもない。
スカイクラッドの観測者
☆☆☆☆☆
新品でCD買ったの随分久しぶりだ。
Steins; GateのOP「スカイクラッドの観測者」ED「AnotherHeaven」のフルコーラスが収録されています。
OPなんかは作中では一番しか聞けないのでこの価格なら十分に買う価値はあると言っていいでしょう。
本編をコンプリートした者だけがわかりあえる、シュタインズゲートの世界と密接にリンクした、美しい曲です。
OPはゲーム版の終わり方が好きなのでそこだけちょっと残念ですが、無理にケチを付けようとしてもそのくらいしか言うところがありません。
そういえば全然どうでもいいんだけど最近8センチCDって見ませんね。
タユタマ
未プレイ。
360ギャルゲは制覇するのでタユタマを買ってきたはいいが、今プレイしてしまうとシュタゲの後遺症で酷い評価をしてしまいそうだ。
しばらく封印ですかね。
ところで入浴剤は四万温泉でした。
こんなものわざわざ特典に付けておいて実は何の意味もないとか言われたら怒るぞ。
ナムコミュージアム バーチャルアーケード
☆
というわけでしばらくナムミューかなとも思ったんだが、レビューを読んでみると随分残念なことになっているみたいでどうしたものやら。
せめて買う前にレビュー見ておくんだったぜ。
実際ちょっと起動してみましたが、XBLAだとゲーム内のメニューの戻ることができず360のメニューまで戻されるとか手抜き感に溢れています。
実績もLAと共通なので既に持っているパックマンCEとかディグダグとかドリラーとかゼビウスとかはこっちでプレイする意味が全くない。
値段が安いのだけが取り柄ですかね。
懺・さよなら絶望先生
☆☆☆☆☆
懺なんて言葉使わないよ、ということで絶望先生、第二期まではリアルタイムで追ってたのですが、第三期は気がついたら終わっていたというかんじで全然見ていません。
たまたまDVDコーナーを覗いてみたらいつの間にか出ていたのでまとめて買ってしまいました。
相変わらずクオリティ高いですね、このシリーズは。
しかし2巻続けて見るとさすがに疲れる。
あと、一時停止とコマ送りを駆使しなければならないので360だと閲覧が辛いですな。
ところで不服袋には結局何が入っているのでしょうか。
CakePHP1.2には標準でページャが付属しています。
前作ったcake_samplesテーブルでページャを実現してみます。
とりあえず適当にサンプル投入。
cake.php
1
2
3
4
5
6
7
|
$pdo=new PDO('mysql:dbname=cakephp;host=localhost','cakephp','cake');
for($loop=1;$loop<1000;$loop++){
$sql="INSERT INTO cake_samples (title,body,created) VALUES
('タイトル:".md5($loop)."','ボディ:".(int)($loop/50)."',NOW())";
$pdo->exec($sql);
}
|
中身は全く意味はないです。
コントローラを作成。
app/controllers/cake_sample_controller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/*
CakeSampleコントローラ
*/
class CakeSampleController extends AppController{
//自分の名前
var $name = 'CakeSample';
//CakeSample/form
public function form() {
//入れる
$this->set('cake_sample', $this->paginate('CakeSample'));
}
}
|
コントローラ側の使い方はfind()と概ね同じですが、呼び方は
$this->CakeSample->paginate()
ではなく
$this->paginate('CakeSample')
となります。
$paginateは引数が無かった場合の初期値となります。
ビューは$paginatorを適当に呼び出すだけ。
ページャーのリンクは$paginateから呼び出しますが、実際のデータ自体はコントローラでsetした値から取得することになります。
app/views/cake_sample/search.ctp
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
|
$options=array();
$options['modulus']='10';
$options['update']='Ajax';
$paginator->options($options);
//最初、最後へ
print($paginator->first('最初へ'));
print($paginator->last('最後へ',$options));
//前後へのリンク
print($paginator->prev('前へ',$options,'前はない',$options));
print($paginator->next('次へ',$options,'次はない',$options));
//前後数ページを表示
print($paginator->numbers($options));
//件数取得
print($paginator->counter('
合計 %pages% ページ中の %page% ページ目です。
総レコード %count% のうち、 %start% 行目から %end% 行目までの
%current% 行を表示しています')
);
//チェック
//現在のページ数
$paginator->current();
//10ページ目が存在するか
$paginator->hasPage(10);
//CakeSampleモデルの10ページ目が存在するか
$paginator->hasPage('CakeSample',10);
//前後のページが存在するか
$paginator->hasNext();
$paginator->hasPrev();
//現在のソート状態
$paginator->sortKey(null,$options);
$paginator->sortDir();
//ページャに関する情報を取得
$paginator->params();
//ソートする基準を選択
print($paginator->sort('ID順','id',$options));
print($paginator->sort('CakeSample.title'));
//データ取得
var_dump($cake_sample);
|
大文字だったり小文字だったり_だったりキャメルだったりうっとおしいことこの上ありません。
アクセスすると「前へ」「次へ」「ID順」等のリンクが現れ、クリックするだけで自動的に遷移します。
動作原理が全く分からないので非常に気持ち悪いですが、とりあえずページャが動きました。
では複数のページャーはどうすればいいかとか、検索結果に対してのページャはどうすればいいかとかはわからないままです。
CakePHPの記事一覧
cakePHPのDBアクセスは、基本的にはモデル作って関係を記述してコントローラからfindするだけで自動的に行ってくれます。
が、これだと常に全フィールドをそのまま持っくることしかできません。
"MIN(books.id)"が欲しい、といった場合はfind内に記述することで実現できます。
$this->Book->find('all',array('fields'=>'MIN(Book.id) AS hoge'));
が、"books.created + INTERVAL 1 HOUR"が欲しいんだよ、とばかりに
$this->Book->find('all',array('fields'=>'Book.created + INTERVAL 1 HOUR AS hoge'));
とか書くとSQLエラーになります。
SQL的には何故か勝手に"SELECT `Book`.`created + INTERVAL 1 HOUR` AS `hoge`"と変形されていました。
こういう場合のためにqueryメソッドで直接SQLを書くことが出来ます。
$this->Book->query('SELECT Book.created + INTERVAL 1 HOUR AS hoge FROM books AS Book');
それはまあいいのですが、実はモデルに対して知らないメソッドが来るとそのままSQLに渡されます。
$this->Book->{'SELECT Book.created + INTERVAL 1 HOUR AS hoge FROM books AS Book'}();
両者の結果は同じになります。
あんまり意味がないというか意味がわからない機能だ。
こんな書き方しかできないのかといえばそうでもなく、イレギュラーなSQLは基本的にモデルに追いやります。
これでコントローラからモデルに依存するコードを排除することができます。
/app/controllers/book_controller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/*
Bookコントローラ
*/
class BookController extends AppController{
//自分の名前
var $name = 'Book';
//Book/indexAction
public function index($id=false) {
//任意のSQLを実行
$this->set('books', $this->Book->getAfter1Hour($id));
}
}
|
実装自体はモデルで地道にSQLを書きます。
本当はこんな書き方ではなく正しい方法があるのかもしれませんが、よくわかりませんでした。
app/models/book.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Book extends AppModel {
//自分の名前
var $name = 'Book';
//Book::getAfter1Hour
public function getAfter1Hour($books_id=false){
//SQL
$sql=" SELECT books.created + INTERVAL 1 HOUR AS hoge FROM books";
if($books_id){
App::import('Sanitize');
$sql.=" WHERE books.id = '".Sanitize::escape($books_id)."'";
}
//実行
return $this->query($sql);
}
}
|
作成したメソッドを呼び出せば任意のSQLを実行することが出来ます。
また、queryメソッドの第二引数に配列を与えるとバインドしてくれます。
app/models/book.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Book extends AppModel {
//自分の名前
var $name = 'Book';
//Book::getAfter1Hour
public function getAfter1Hour($books_id=false){
//SQL
$sql=" SELECT books.created + INTERVAL 1 HOUR AS hoge FROM books";
if($books_id){
$sql.=' WHERE books.id = ?';
}
//実行
return $this->query($sql,array($books_id));
}
}
|
http://localhost/Book/index/1'%20OR%201=1
↑というふうに引数を渡すと、SQLは↓というふうにになります。
SELECT books.created + INTERVAL 1 HOUR AS hoge FROM books WHERE books.id = '1\' OR 1=1'
CakePHPの記事一覧
☆☆☆☆
イエスとブッダが安アパートで共同生活するという国によっては作者極刑ものの漫画。日本は平和だな。
前巻までは色々と派手な演出もあったりしましたが、今回は基本的に地味な内容が多いです。
ですが、地味ながらなんかじわじわ来るので困る。
☆☆☆
とりあえず敵役がキャラ・動機ともにしょっぱいのはどうにかならんものか。
男子校行けよ、の一言で終了だし葵は一瞬にして空気化。
何故モモが加入したのかできたのか、何故心変わりしたのかとかそこらへんも一切スルーだし。
まあそういう細かいことはどうでもいいとして紗夜がかわいいからよし。
☆☆☆☆☆
ギャルゲーをリアルでやってみた、という設定のメタ的漫画ですがやはり面白い。
世界背景もほんの少しですが明らかになりました。
実際問題として本当に悪人が大量脱走してたらココロのスキマお埋めしますなんてわけのわからん方法で一匹ずつ捕獲とかそんな非効率的なことするわけねーとか思いますが、まあ気にしない。
☆☆☆☆☆
あんだけアングラなバイトしまくっていたハヤテがいまだ童貞だとか女性の機微に疎いとかいう設定が信じがたいのですが。
まあそれはともかくフラグクラッシャーハヤテは今回もフラグバキバキのはずなのに全然折れてないってのはどういうこった。
さて単なるハーレム漫画と思いきや実に意外なことに色々と伏線や隠し設定があったりする本作、ようやくそれらが表に出てき始めました。
作者の弁を信じるならばアテネ編で一区切りつくそうですが、はたしてどうなることやら。
ていうか今巻で歩ルートに入ったのは間違いないよな。
☆☆☆☆
久々に出た本編。
と思ったらいつの間にかQとか出てたんだな。全然気付いてなかったわ。
本編とは別に年鑑シリーズというものもありますが、こちらは発表会かなんかの様子を単に収録しているだけで非常に読みにくいものになっています。
こちらはきちんと読める形なのでご安心を。
さてアポロ捏造説(無論捏造説が妄想)のくだりでこのような発言が出てきます。
>アポロ陰謀説を信じてしまうような人間には、あの本は理解できないのではないか。彼らには中学生どころか、小学生レベルの知識すらないのではないか
>しかし、信じている人間は、千人に一人とか一万人に一人といった少ない数字ではないだろうと推測できる。
これはちょっと違うのだと思うのです。
アポロ捏造論者には二種類が居ると思うのです。
まず、消極的捏造論者。
こちらは、そもそもアポロ自体に興味がないので特に科学知識をもって考えたりといったこと自体を行わないのだ。
どこかで聞きかじったアポロ陰謀説を特に批判することもなく受け入れ、なんとなく捏造じゃないかと思っている。
月が西に沈むのか東に沈むのかといったことにも興味がないのでどちら沈むのかを知らず、月面が無重力かどうかなんてどうでもいいので無重力だと思っているのです。
こういった層はうまく説得すればまともな人間に戻ってこれると思います。
もう一種類が問題で、こちらがいわゆるビリーバー。
こちらの人種には共通して「自分が正しい」というスタート地点が存在するので、外部から何を言おうが完全に無駄ということになります。
ググればそういう系のサイトは幾らでも出てきますが、これはあくまでそういった連中は自己主張が激しいという事実を表しただけであり、比率としてはさほど高くないものと思われます。
だってやすしみたいなのが何万人もいるような世界とか嫌すぎる。
前回のでbooksテーブルと直接繋がっているテーブルは結合できましたが、更に連鎖した先のテーブルを結合することも出来ます。
とりあえず前回のテーブル群にレーベルテーブル追加。
| CREATE TABLE `labels` ( `id` int(8) NOT NULL AUTO_INCREMENT, `publisher_id` int(8) NOT NULL, `name` varchar(32) NOT NULL, `comment` text NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`id`), KEY `publisher_id` (`publisher_id`), KEY `publisher_id_2` (`publisher_id`), CONSTRAINT `labels_ibfk_1` FOREIGN KEY (`publisher_id`) REFERENCES `publishers` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
どう考えてもbooks.label_id→labels.publisher_id→publishersが正しい流れですが所詮サンプルなので気にしない。
次はモデルを追加です。
Books→Publishersの関係はBookモデルに書いてありますので、次はPublishers→Labelsの関係を記述する必要があります。
ではPublishersモデルを作成しましょう。
app/models/publisher.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Publisher extends AppModel {
//自分の名前
var $name = 'Publisher';
//publishers.idはlabels.publisher_idから外部キー
var $hasOne = array(
'Label' =>
array(
'className' => 'Label',
'foreignKey'=> 'publisher_id'
)
);
}
|
毎回全リレーションを呼び出しているとパフォーマンス的に大変なので、デフォルトでは1段階しか呼ばれないようになっています。
Booksを呼び出した場合はPublishersまでしか呼ばれないということです。
これを2段階まで呼び出すようにする必要がありますが、単にコントローラに一行追加すればOKです。
app/controllers/book_controller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//Bookコントローラ
class BookController extends AppController{
//自分の名前
var $name = 'Book';
//Book/indexAction
public function index() {
//Bookモデルを2階層までキーを追う
$this->Book->recursive=2;
//Bookモデルを取得
$this->set('books', $this->Book->findAll(array('Book.id <>'=>'1')));
}
}
|
このように2段階目まで簡単に取得することができます。
SELECT (略) FROM `books` AS `Book`
LEFT JOIN `authors` AS `Author` ON (`Book`.`author_id` = `Author`.`id`)
LEFT JOIN `publishers` AS `Publisher` ON (`Book`.`publisher_id` = `Publisher`.`id`)
WHERE `Book`.`id` <> 1
前回LIMIT 1が取れない、みたいなことを言いましたが、単にfindが一件取得で、findAllが全件取得だっただけでした。
CakePHPの記事一覧