15時49分13秒やっと見つかりましたがな以前「Paint.NETがインストールできない」というエントリを書いたが、なんとかインストールできるものが入手できた。それまでに若干の紆余曲折があったのでメモっておこう。1.1.」と拒絶された。実は今回のクリーンインストールでは、.NET関連は2.0のみインストールして1.1は入れていなかったのだ。2.0に移行していたのは知っていたが、サイドバイサイドで動くと思ってそのまま試してみたがインストールすらできなかった。Archiveだのみとなる。以前のバージョンは現在の公式ページに移転する前に入手していたのでそちらの古いサイトのアーカイブを探って、いくつかページをたどってみた。後半のほうはすでに移転先へのリダイレクトになっていたが、2006/07/15以前はかろうじて元ページが残っていたのでそこからダウンロードページへ移動、ダウンロードリンクをクリックしてみたが、リンクされているダウンロードサイトでも現在のバージョンしかダウンロードできない。ファイル名がわかれば、ひょっとして...しかし、上記ダウンロードページにたどり着いたことで、もともとのダウンロードファイル名が判明(PaintDotNet_2_xx.exe)したので、これで検索してみることにした。ぐる先生に「PaintDotNet_2_63.exe」を尋ねて返ってきたのをいくつかたどると、なぜかゲーム系のサイトのダウンロードページへ。いってみたらダウンロードできた。いやぁ、探せばなんとかあるもんだ。日本語化WEB」さんから2.5向けの非公式言語パックをダウンロード、だめ元で適用してみたらうまくいってメニュー周りも日本語化され、快適な状態で使えるようになった。リソースファイルだけなのでランタイムバージョンには依存しないか。これでやっと、ひと段落。アプリケーションとしての使い勝手は3.0系には及ばないんだけど、まあちょっとした画像加工とかなら間に合うからこれでいいか。書いていたが、2.x系の最終はどうやら2.72が最終らしく、このバージョンですでにWin2Kのサポートが切られているみたい。対応OSはWin2K/WinXP(Server2003も入るかも。.NET2.0ベース。最終は2.64みたい。.NET2.0ベース。Win2Kサポート打ち切り。.NET2.0ベース。対応はWinXP/Vista/Server2003。2007.9.1現在の最新は3.10といった感じか。Win2Kも限界かなぁ。安定していて良いOSだと思うんだけど。17時02分49秒ものすごい勢いでパフォーマンス改善してますが。script.aculo.usベースのUIライブラリ「Spinelz」に対して無責任に文句たれてたら、なんと開発者ご本人よりコメントをいただいてしまった。現在開発段階ではありますが、全体的にかなりパフォーマンス改善されております。表示内容の変更や、複数Datepickerをバインドしてもストレスなくご利用いただけると思います。いう情報をいただき、さらに正式リリース前にもかかわらず、現在の最新版のsvnリポジトリを教えていただいたので試してみた。試してみると、年・月の切り替え時のもたつきがまったくなく、IEでも快適に使用できるように、劇的ともいえる改善がなされていた。innerHTML書き換えに変更しているみたいなのだが、それだけ(というには修正ボリューム大きいけど)でここまで改善されるとはちょっと予想外だった。dara-jのアプローチ文句たれてるエントリでも書いたが、現在はとりあえず自分でスクラッチしてみている。自作するにあたり、以下のような拙い工夫をしてみている。複数インスタンス設置時の、ポップアップの排他(DatePicker1表示中にDatePicker2を表示させたら自動的にDatePicker1が閉じる、といった具合)といったおまけ実装もしてるんだけども。テンプレートのcloneNode()が本当に有効かどうかはちと微妙なのだが、表示更新時にテーブルを再構築するのではなく表示内容のみを書き換える方法は結構自信があったのだが、どうも体感上はSpinelzの最新版のほうがパフォーマンスがいいような気がする。俺の2日間っていったい...orz自作版については、急にSafariでNGになったりとちょっと不安定なところがありそうなので、もう少し検証してよく安定しているようであればまたSpinelzに戻すかも。俺の2日間って...orz改めて御礼Spinelzを開発されている木下さん、無責任な悪口とも言えるエントリに貴重なコメントを寄せていただき、本当にありがとうございました。ご教示いただいたとおりDatePickerのパフォーマンスに関して劇的ともいえる改善が見られ、今後の開発の進捗に大変期待しております。IEがむかつくSpinelzに「IECover」というクラスがあり、DatePickerがそれを利用しているのはソースを見てしっていた。IE対策なのもコメントから伺える。これが「IEのselect要素が常に最前面に表示される」ことへの対策なんだろうってこともわかる。いざ自分で作ってみると「IEのselect要素が常に最前面に表示される」ことが以下に腹立たしく、なるほどIECoverのような工夫がライブラリレベルで必要なのはそういったことかと感心させられた。IECoverが行っている、iframeを用いた回避方法なんてdara-jには自力で思いつくはずもなく、それだけでもUIライブラリに必要なスキルが多岐にわたり深いものが必要なのだなぁと思い知らされる。IECoverなんてIE以外に必要ないんだけども。Enjoy*Study)などなど、もっとも大きいシェアがあるブラウザにあるまじき低レベルぶりに、Sybianさんならずとも「さっさと市ね」といいたくなる。根本的な部分でサードパーティのブラウザと事情が違うのはわかる(実態として、OSを構成するコンポーネント上にアプリケーションを構築しているので。mshtmlもmsxmlもWindowsスクリプティングも捨てられないのはわかる)んだけども、それが足枷になって他のモダンブラウザの足を引っ張るようでは存在意義が問われてしまうと思うのだが。02時08分59秒のっけからお詫びすみません、このエントリ書くまで気づきませんでしたが、前回示したフォルダツリーで、ビュースクリプト関連で1階層抜けてました。具体的には「htdocs/zf1/application/views/scripts/index/」の「scripts」部分が抜けてました。2つ目のアクションメソッド気を取り直して、本題です。期間が空いてしまいましたが、前回の続きでアクションコントローラを扱います。前回はデフォルトのアクションメソッド(indexAction)のみの実装でしたが、まずは2つ目のアクションメソッドを実装するところからはじめましょう。アプリケーションは前回のものをそのまま流用しますので、これからやる作業はIndexController.phpにアクションメソッド「secondAction」を追加するsecondActionに対応するビュースクリプト「second.phtml」を/views/scriptsに作成するの2点です。/application/controllers/IndexController.phpを以下のようにします。);}}IndexController.php対応するsecond.phtmlは、とりあえずindex.phtmlをそのままコピーしてリネームしてください。ここまでの作業で、ファイル一式は以下のようになります。Apacheを使用している方はこれを忘れずにこの状態で「http://<host名>/zf1/index/second」にアクセスすると、「2つ目のアクション」と表示されるはずです。以降、基本的には、「アクションメソッドを増やしたら、対応するビュースクリプトを追加する」というような拡張方法になります。相互にリンクを張ってみるさて、せっかくアクセスできるURLが2つに増えたのに、それぞれいちいちURLを直接打ち込んでいたら面倒この上ないので、それぞれのアクションメソッド(のビュー)からお互いにリンクを張ってみることにします。ビュースクリプト中に直接記述してもいいのですが、リンクアドレスの情報はコントローラ側で管理し、ビュースクリプトはそれをレンダリングするだけに分離するのが筋だと思いますので、そのようにしてみます。2つのアクションメソッド内で「$this->view」にリンクさせるアドレスをassignさせます。こんな感じでしょうか。);}}そしてビュースクリプトです。index.phtml、second.phtmlとも以下の内容に修正します。?></a></body></html>index.phtml、second.phtmlさて、まずは「http://<host名>/zf1/」にアクセスしてみてください。以下のようになるはずです。Frameworkへindex/secondhttp://<host名>/zf1/ここまでは従来と変化がほとんどないので問題ないはずです。確認点としてはリンクがちゃんと表示されているか、くらいでしょうか。次にページ中のリンク「index/second」をクリックしてみてください。以下のようになります。2つ目のアクションindex/indexhttp://<host名>/zf1/index/second/ちゃんと表示が変わっているでしょうか?リンク先がなんだかヘンさて、ここまで特に問題はないはずなのですが、どこかおかしい所はないでしょうか?index/secondに表示されているリンクをよく確認してください。未訪問の色のままになっていませんか?リンク「index/index」にカーソルを合わせてみるとわかると思いますが、実は現在のサンプルのままでは、リンク先が「http://<host名>/zf1/index/index/index」になってしまいます。Frameworkのコントローラモデルでは、すべてのアクセスがディレクトリパスに展開されるため、相対でリンクを示すと常に現在のパスに対して階層が追加されてゆくことになってしまいます。これが、アプリケーションがホストのトップであれば、「/index/second」などと絶対パスが使用できるので問題ありませんが、アプリケーションごとにホストを用意したりバーチャルホストを用意したりするのはあまり現実的ではありません。ドキュメント中に出現するURLはリンク先だけではありません。JavaScriptやCSSなどのリソース、画像、さらにはformのpost先など、1つのWebアプリケーション内でアプリケーション内のほかのURLを指定する必要があるところはたくさんありますので、このままではちょっと困ったことになってしまいます。やって解決したものでしょうか...base要素を活用これはdara-j的なアプローチですが、リンクの解決にbase要素を使用してみましょう。href="http://<host名>/zf1/"></base>」が出力されてさえいれば、前述のように「コントローラ名/アクション名」形式でリンクを指定することができます。base要素に指定するアプリケーションのルートURLですが、直接ビュースクリプト中に指定してもよいのですが、他のアプリケーションを構築する際にもそのまま流用できるように関数を作成することにします。起動スクリプト「index.php」に以下のような関数を追加します。$request->getBaseUrl();}引数として受け取る「$request」は、Zend_Controller_Request_Httpというオブジェクトになります。このオブジェクト(クラス)は従来$_GETや$_POSTなどのスーパーグローバル変数から取得していたリクエスト情報を一元的に集約したバリューオブジェクトです。Framework上でも従来のスーパーグローバル変数へアクセスはできますが、せっかくのオブジェクト指向プログラミングでもあり、なるべくこちらを使うようにしたほうがよいと思います。アクションコントローラの初期化機構では、このgeApplicationUrl関数を使用して、実際にbase要素を出力するようにしてみましょう。引数にZend_Controller_Request_Httpが必要ということもあり、アクションコントローラからgetApplicationUrlを呼び出して値を取得し、ビュースクリプトへassignするというアプローチにしてみたいと思います。これまでと同じように、各アクションメソッド内から$this->view->assignとしてもよいのですが、これはコントローラ内での共通処理とするような内容なので、どこか一箇所に集約しましょう。アクションコントローラは固有の初期化処理用として、「init」メソッドを用意しています。これはZend_Controller_Actionのコンストラクタから始まる一連の初期化処理の中でサブクラス固有の初期化処理用として用意しているもので、これをオーバーライドすることになります。initメソッドをオーバーライドし、base要素向けのベースURLをビューへassignするコードを追加したIndexController.phpは以下のようになります。);}}IndexController.php(初期化処理を追加)ちょっと補足になりますが、getApplicationUrl()に渡すリクエストオブジェクトを「Zend_Controller_Request_Http」と説明していましたが、コード中のコメントでは「Zend_Controller_Request_Abstract」としています。これは別に先の説明で嘘をついていたとか間違っているとかではなく、Zend_Controller_Action::getRequest()メソッドは抽象クラス「Zend_Controller_Request_Abstract」を返す仕様になっていて、httpアクセス環境化ではhttp通信向けサブクラスである「Zend_Controller_Request_Http」を返している、ということです。getApplicationUrl()内ではZend_Controller_Request_Httpであることを前提としているのであまりよいコードではないのですが、この連載中ではCLIなどは想定していないのでこのままでご容赦ください。secondActionメソッドの最後に「$this->_helper->viewRenderer('index')」という見慣れないコードを追加していますが、これはまったく同じ内容の2つのビュースクリプトを定義しているのが気持ち悪いため、2つのアクションメソッドで1つのビュースクリプトを共用するためのコードです。_helperやviewRendererがいったい何なのかはこの連載でもいずれ取り上げますが、「viewRendererヘルパーの(暗黙のメソッドである)setRenderメソッドでレンダリングするビュースクリプトを変更できる」ということができる、ということだけ理解してくだされば問題ないと思います。別のビュースクリプトの選択」をご覧ください。他のソースの改変init内で「baseUrl」として割り当てられたURLをbase要素として出力するよう改変したindex.phtmlは以下のようになります(second.phtmlは不要になったので削除してください)。?></a></body></html>index.phtml(base要素の出力を追加)base要素の出力時で、href属性の最後に「/」を記述しているのは、単にgetApplicationUrl()が末尾に「/」がない状態の文字列を返すからです。base属性は末尾が「/」ではない場合有効に機能しないので注意してください。getApplicationUrl関数を追加した、最終的なindex.phpは以下のようになります。$request->getBaseUrl();}index.php(getApplicationUrl関数追加)今回の最終的なファイルツリーは以下のようになります。getApplicationUrl()関数を追加.htaccess今回のまとめ今回のポイントは以下のようになります。次回は(今回やる予定だった)エラーの処理方法の概要と、関連して複数のアクションコントローラを使用する例を扱ってみたいと思います。[コメント(0)|トラックバック(0)]連載記事って大変だわ。03時34分51秒いやはや、思ったより大変だ...なにを思ったのか、先日より「ZendFramework入門」なる連載記事をはじめてみたのだが、これが思ったよりも大変。先ほどあげた記事なんかは、もともと漠然とした構成は頭の中にあったので「1時間くらいでできるかな?」などと考えていたのだが、結局3時間ほどかかってしまった。書いているうちに「あれも必要では?」「これはどこに差し込もう?」なんて迷いがいろいろでるというのもあるし、なによりテキストエディタでHTMLを直接書いているという前時代的な作業が遅くなる原因なんだろうけど。間違えるしもともとHTML書くのにツールを使う習慣がないので、通常の記事であればエディタでしこしこHTML書くのはそんなに苦にならないんだけど(量を書かないからね)、今回ネックになるのはHTMLのソースフォルダツリーの2点で、前者は実体参照が、後者はリストの入れ子が結構大変。こんなの手作業でやるのはなんか間違っている気はするのだが、ほどよいツールがなく結局しこしこと書くハメになってしまっている。うれしいこともあるもちろん大変なことだけではなく、うれしいこともある。はじめたばかりで海のものとも山のものともつかないしょぼい連載なのだが、いくつかのサイトさんでこの連載をご紹介くださっているのだ。紹介してくだすったお礼も兼ねて(兼ねられるのか?)、リンクを示しておこう。Framework入門・準備編あるSEのつぶやきさん、PHPの種さん、ご紹介ありがとうございます。へこむこともあるただ、上記の「PHPの種」さんのところで別の入門記事(というかクイックスタート)を紹介されているのだが、こんなの見ると「俺やってる意味あんのかな」とかへこんだりへこまなかったり。[ラボラット]ほんとにラボラットさんの記事は簡潔にうまくまとめてるので、正直ここの連載より役立つと思いますorzこっちなんか2回(準備編入れて3回か)も費やしてるのに内容的にはラボラットさんとこより薄いもんなぁ。今後はもう少し内容を濃くするようにがんばろう。01時28分16秒HttpWebRequestでCookieを使う先週までのLL漬けからうって変わって、今日から久しぶりに.NETプログラミング。いや~、半年振りくらいのC#だもんで、結構コードかけなくなってるし。明日くらいまではちょっとリハビリ状態かしらん。これ知らずに今日は結構時間使ったのでメモ。.NET1.1だからいまやあまり役にたたん情報かも。手順でコード書いてみたらうまくいかない。Webアプリ側では認証とおってないリクエストはすべてログインフォームがあるページに飛ばすようにしてるんだけど認証リクエストの戻りからすでにログインフォームのコンテンツが返ってきてる状態。おんなじ処理をJScriptでXHR使ってやってみたらこっちは認証とおって目的のデータがちゃんと取れてる。1.1のWebClientはかなり割り切った使い方をするものらしく(いままであんまり使ったことなかった)、URL直接食わせてコンテンツをダウンロードするくらいのインターフェイスしかないみたいなので、不精せずにHttpWebRequestに切り替えてみたんだけどこれも結果変わらず。Webサーバのログを見てみると、一応希望のURLへのアクセスで200を返しているみたいだけどしつこくログインフォームのコンテンツだけが返ってくる。「ひょっとしてヘンなキャッシュ引いてるんじゃね?」とか思ったんだけどどうもそうでもない。レスポンスヘッダ調べてるうちにPHPが返すセッションの値がリクエストごとに違っている。なんだ、そんな話かよ。要するにサーバがCookieセットしようとしてるけどWebRequest側でそれを受け付けてないので、当然認証していないことになってたわけだ。CookieContainerと、ここまでわかったけどはて、どうやってCookieサポートするんだ?でMSDNとにらめっこしてたらHttpWebRequestにCookieContainerやらいうプロパティがあることを発見。クラスのインスタンスを提供します。オブジェクトをそのプロパティに割り当てる必要があります。わかるようなわからんような記述がある。HttpWebRequestでCookieの文言があるメンバも他に見当たらんし、これを使ってみるのかな。このCookieContainerプロパティは型がまんま「System.Net.CookieContainer」クラスで、これがパラメータなしコンストラクタをサポートしてるので、こんな感じのコードを書いてみた(注:コード未検証。抜けとか間違いあるかも)。データを取得}で試してみると、これで正解だったみたい。いやー、わからんかった。定番処理っぽいちと時間くったけど、まぁ最悪「MSXMLをtlbimpするかぁ?」とか考えてたワケで、それに比べればマシなのでほっとしてたんだけど、あとでなんとなくぐぐってみたらいっぱい引っかかるじゃん。吊ブックマークレットtumblrのキーボードショートカットが便利になっとる。Chrome編dataスキームの画像をブロックしてみるローカルストレージを確認したり消したりするブックマークレットそうそう、いまさらTwitter始めました。(9)このブログについてJavaScriptとかC#とかPHPとか。