‘解決’ カテゴリーのアーカイブ

複数の入力欄にまたがるValidationのエラーを特定の入力欄に表示させたい場合

sfFormでSymfony 1.4のお話。

PostValidatorのエラーメッセージをどこに出せばいいんだ?という状況で使用できます。

class SomethingInputForm extends BaseForm
{
    public function configure()
    {
        // ...
        $this->validatorSchema->setPostValidator(
            new sfValidatorCallback(array('callback' => array($this, 'myCallbackFunc')))
        );
    }

    public function myCallbackFunc($validator, $values) {
        // 何かバリデーション
        if (!($values['input1'] == $values['input2'] == $values['input3'])) {
            $error = new sfValidatorError($validator, 'error message ...');
            throw new sfValidatorErrorSchema($validator, array('input1' => $error)); 
        }
        
        return $values;
    }
}

こんな感じで、input1のエラーとして出力できるので、テンプレートのエラー表示が楽になります。


Doctrine_Collectionをループする

Symfony 1.4+Doctrine
やたら不便(だと個人的には思っている)なDoctrineの、SELECTに関するメモ。

やりたかったことは、ある条件で抽出した複数行に1行ずつ処理を加えて書き戻すというフロー。
fetchArray()とかでは配列しか返ってこないので意味がなく、fetchOne()では先頭行しか返ってこない。
fetchOne()を複数回実行すればいいのかと思ったら無限ループに陥った。

findByではorderByをするのにフックを使わないといけないらしいのでパス。

一応、以下の方法で解決しました。

$collection = Doctrine_Query::create()
    ->select('u.*')
    ->from('Users u')
    ->where('u.flag = ?', '1')
    ->orderBy('u.id')
    ->execute();

var_dump(get_class($collection)); // Doctrine_Collection

$iter = $collection->getIterator();
var_dump(get_class($iter)); // ArrayIterator

while ($record = $iter->current()) {
    var_dump(get_class($record)); // Users
    var_dump($record->getId());
    $iter->next();
}

next()呼ばないといけないのは面倒だなと思ったら、foreachで使えたらしい。

$collection = Doctrine_Query::create()
    ->select('u.*')
    ->from('Users u')
    ->where('u.flag = ?', '1')
    ->orderBy('u.id')
    ->execute();

var_dump(get_class($collection)); // Doctrine_Collection

$iter = $collection->getIterator();
var_dump(get_class($iter)); // ArrayIterator

foreach ($iter as $record) {
    var_dump(get_class($record)); // Users
    var_dump($record->getId());
}

これでかなりマシになった。

最終的にはこれで。

$collection = Doctrine_Query::create()
    ->select('u.*')
    ->from('Users u')
    ->where('u.flag = ?', '1')
    ->orderBy('u.id')
    ->execute();

var_dump(get_class($collection)); // Doctrine_Collection

foreach ($collection->getIterator() as $record) {
    var_dump(get_class($record)); // Users
    var_dump($record->getId());
}

あとはループ内で$record[‘data’] = ‘hoge’;$record->save();とかしておけばOK。

追記:2010/03/30

全然違った。もっと簡単にできました。getIterator不要でした。

foreach ($collection as $record) {
    $record['data'] = 'hoge';
    $record->save();
}

慣れてくると意外と便利な気がしなくもないDoctrine。結合系と特に。


DELLモニタ2407WFP電源ボタンの直し方

DELLの2407WFPというモニタをずっと使っているのだけど、1年くらい前から電源ボタンを押しても反応しない状況になって困っていました。

幸い電源は入った状態だったので、以降は入力切替をS-VIDEOなどにして、自動スタンバイさせていました。

電源ボタンは、押してもクリック感がなく、最初から押し込まれているような状態。

分解して直そうと試みるも、裏のネジを外した後の分解方法がわからず…

同等の現象を検索してみたところ、

価格.com – 『皆さんのモニターの主電源ボタン壊れませんか?』 DELL 2408WFP のクチコミ掲示板

電源ボタンマークの「|」の部分が
時計でいう12時の向きにぴったりあってないとクリック
できません。

!?

確かに自分のモニタを見ると電源ボタンのマークが斜めになっている…

P1030002_s

テープなどで電源ボタンを粘着させて回転させてみる…

P1030001_s

できたーーーー!

発見した人すごいな。

今はポストイットで固定してます。

P1030003_s


Linuxで複数ユーザで使えるリモートデスクトップ環境を作る

今回やりたかったのは、社内で複数の人が一台の共有マシンを使って、とある時間のかかる処理をするための環境作成です。

最初はxinetd+Xvfb+x11vncでgdmをあーやってこーやって…って色々試していたのですが、Windowsのリモートデスクトップ接続をクライアントに使えた方が便利だなぁとか思ってRDPで転送する方法がないか調べたところ、むしろさっきまで小難しくやろうとしていたすべてをまるっとまとめてやってくれるxrdpというものを発見!

これならシンクライアントっぽいものが一瞬で作れる!ということでさっそく導入してみたので手順解説します。

WS000001

このxrdp、デフォルトのままならリモートデスクトップユーザからシステムに変更を加える作業はできないので、今回の用途に最適です。

xrdp | Get xrdp at SourceForge.net

ユーザの追加も、通常通りLinuxにユーザ追加するだけで、リモートデスクトップログインできるようになります。

VNCに対する利点は多分こんなところ

  • 画像解像度がクライアント側から変更できる
    WS000000
  • Windowsユーザに追加クライアントをインストールしてもらう必要がない

設定にあたってはこちらのブログのエントリが大変参考になりました。これがないとまともにキーボード使えませんでした。

サーバはUbuntu Server 9.10(Karmic Koala)を使いました。別にUbuntuデスクトップ版でも良かった説。

とりあえずインストール時にこれらを選択しておきます。インストール後なら$ sudo taskselでもOK。

  • Basic Ubuntu server
  • OpenSSH Server
  • Ubuntu desktop

xrdpですが、aptやSourceForgeからtar.gzでダウンロードできるものはバージョンが古く、Windows7のリモートデスクトップ接続クライアントに対応していません。なので、cvsレポジトリから最新を持ってくる必要があります。

今回チェックアウトしたものは2009-12-26に最終更新されたバージョンです。

まずは下準備とチェックアウトまで。

$ sudo aptitude update
$ sudo aptitude install cvs autoconf libtool libssl-dev libpam0g-dev libx11-dev libxfixes-dev tightvncserver scim scim-anthy
$ cd ~/
$ mkdir xrdp
$ cd xrdp
$ cvs -d:pserver:anonymous@xrdp.cvs.sourceforge.net:/cvsroot/xrdp login
$ cvs -z3 -d:pserver:anonymous@xrdp.cvs.sourceforge.net:/cvsroot/xrdp co .
$ cd xrdp

で、前述のブログを参考にいくつかファイルを修正します。

$ vi xrdp/lang.c
          if ((code >= 0) && (code < 128))


          if ((code >= 0) && (code < 135))

に。

$ vi xrdp/xrdp_types.h
    struct xrdp_key_info keys_noshift[128];
    struct xrdp_key_info keys_shift[128];
    struct xrdp_key_info keys_altgr[128];
    struct xrdp_key_info keys_capslock[128];
    struct xrdp_key_info keys_shiftcapslock[128];

    struct xrdp_key_info keys_noshift[135];
    struct xrdp_key_info keys_shift[135];
    struct xrdp_key_info keys_altgr[135];
    struct xrdp_key_info keys_capslock[135];
    struct xrdp_key_info keys_shiftcapslock[135];

に。

$ ./bootstrap
$ ./configure
$ make
$ sudo make install

次は日本語キーボード用にキーマップを作成します。キーマップファイルは/usr/local/bin/xrdp-genkeymapを使って作ることもできるのですが、「\」や「_」のキーが効かなくなる現象があるので、さきほどのエントリからコピーしてきます。

とは言ってもファイル単体では公開されていないので、xrdp-0.5.0-instfiles.patchから当該部分を引っこ抜いてくる形になります。

ちなみに自分で生成する場合は、GUI上の端末から(ここ重要)
$ sudo /usr/local/bin/xrdp-genkeymap /etc/xrdp/km-0411.ini
でOKです。

それ以外は普通にSSHから作業できます。認識する名前別にキーマップの複製。lnでもいいかも。

$ cd /etc/xrdp/
$ sudo cp km-0411.ini km-e0200411.ini
$ sudo cp km-0411.ini km-e0210411.ini
$ sudo cp km-0411.ini km-e0010411.ini
$ sudo vi /etc/xrdp/startwm.sh

startwm.shの内容は前述のエントリからまるごとコピペして上書きします。が、Ubuntuで試したところ、ログイン後にキー配列がめちゃくちゃになる現象(「qwerty」が「c.gvn 」になる)があるので、一行追加して対策します。

export XKL_XMODMAP_DISABLE=1

を、for WindowManager in $SESSIONSの前にでも入れておきます。

で、あとは起動するだけです。

$ sudo /etc/xrdp/xrdp.sh start

WS000002

複数のユーザが同時にログインしても問題なく動作します。1200×1920とかの解像度でもストレスなく作業できました。

Mac OS Xな人々にはRemote Desktop Connection Client for Mac 2もあるのでばっちりです。

追記:あ、右シフトキーが効かない現象がありました。謎。


Virtual PC上でdebianのeth0が消えた現象

Windows Vista Ultimate x32上のMicrosoft Virtual PCからWindows 7 Enterprise x64のWindows Virtual PCにDebian lennyの仮想マシンのデータをそっくり移して使おうとしたら、eth0がなぜか消えてしまった…

loしか残ってないという状況。

結論から言うと、/etc/udev/rules.d/70-persistent-net.rulesを削除した後、rebootしたら直りました。

/etc/init.d/networking restartとかでは直らず。

ゲストOSが64bitじゃないからいけないのかとか思ってdebianの64bit版とか別にインストールしようと試みて、ゲストOSには32bitしか受け付けないことを知ったり。なので、そこは問題ではなかった。


iPhoneな人への地図URLの送り方

iPhone/iPod touchでもPCでも共通で見られるGoogleマップのURLを作りたくなったのでメモ。

というか、iPhone上のSafariから、Googleで場所を検索すると出てくるリンクですね。iPhoneの場合、このURLを開くと地図アプリが開きます。

http://maps.google.co.jp/?q=東京都新宿区西新宿2丁目8−1

http://maps.google.co.jp/?q=248-0006

PCのGoogleマップで地図のURL開くとめちゃくちゃ長くなってしまうので、こういう指定の仕方覚えておくと便利かも。

何がやりたかったかって言うと、twitterで○○の場所どこ?って聞かれて、とっさに住所だけ答えてしまったけど、iPhoneで使える地図のURLにしたほうが便利だったな、って思って。


SilverlightのTestPage.htm自動生成をやめる

やめる、というか、HTMLのobject要素内にparamとか追加したかったので、別ページを用意して、そのファイルをビルド時に実行してくれるようにしたいのです。

ASP.NETのプロジェクトがくっついている場合はそちらを修正すればいいのですが、Silverlightプロジェクトを単体で作ってしまった場合用。

環境はVisual Studio 2010 ベータを使っています。

メニューの[プロジェクト]から、[新しい項目の追加]、[HTMLファイル]を選択して1ページ作成してやります。

スケルトンのHTMLがエディタに表示されるので、Silverlightを呼び出すタグを書きます。自動生成されたTestPage.htmの内容でもコピーして作ると楽。

ちなみに実行自体はプロジェクトのルートフォルダにできるので、xapファイルのパスの前にBin/debug/などをつけてやる必要あり。(出力ディレクトリにコピーできるけど、コピーしてもそちらが実行されるわけではない)

で、プロジェクトのプロパティで、デバッグ→開始動作のラジオボタンを[テスト ページを動的に生成する]から[ページを指定する]に変更して、htmlファイルを選択。完了。


Encoding.GetString(Byte[])はSilverlightで使えない

今日のびっくり。

‘System.Text.Encoding.GetString(byte[])’ はアクセスできない保護レベルになっています。

Encoding.UTF8.GetString(data);

こんなコードを書くとビルド時エラーになります。

なぜか、Encoding.GetString(Byte[], Int32, Int32)は使えます。

Encoding.UTF8.GetString(data, 0, data.Length);

こうしておけばOK。何だろう、この仕様。


今日の微妙エラー

コントロールはひとつの case ラベル (‘default:’) から別のラベルへ流れ落ちることはできません。

switch (message)
{
    case "hoge":
        funcA();
        break;
    default:
        funcB();
        break; // これがないとエラー
}

他の言語のクセでbreak書かなかったら起きた。

「フォールスルー」ってことなんですね。

ちなみにcaseのあとのブロックにコードを書かなければフォールスルーはできるという話。


Windows 7 x64でのVirtual PCとdebian

Windows 7 x64環境のWindows Virtual PCに、以前Vista 32bit版のMicrosoft Virtual PC 2007で使っていたdebian Lennyの仮想マシンを持ってきて起動させようとしたら、ブートの途中で何もエラーも表示せずに応答しなくなってしまったので対策を調査。

多分Windows 7どうこうではなくて、64bit版だということが問題っぽい。

MicrosoftVirtualPc2007/lenny – Debian Wiki

noreplace-paravirtパラメータを追加しておけば良いだけ。

まぁ、すでに設定していた場合は何もせずに移行できたって話ですね。Windows Virtual PCとVirtual PC 2007間での互換性問題はほとんどなさそう。

追記

NICを認識しない…やっぱりdebianを64bit版にするしかないのか…?