タイトル/名前 | 更新者 | 更新日 |
---|---|---|
Perl/codepiece/array_hash1 | msakamoto-sf | 2008-12-24 22:19:43 |
Perl/codepiece/static_vars1 | msakamoto-sf | 2008-12-24 22:11:19 |
Perl/codepiece/signal01 | msakamoto-sf | 2008-12-24 22:07:11 |
日記/2007/06/28/メモ | msakamoto-sf | 2008-12-23 23:40:31 |
日記/2007/07/23/メモ | msakamoto-sf | 2008-12-23 23:34:07 |
PHP/PokoX, pokopokoという黒歴史メモ | msakamoto-sf | 2008-12-23 16:25:00 |
日記/2007/02/25/findコマンドメモ | msakamoto-sf | 2008-12-23 15:13:01 |
技術/HTML/tableレイアウト(IE6とFirefox1.5) | msakamoto-sf | 2008-12-23 15:00:48 |
画像/reports_2006052101_03ff15.jpg | msakamoto-sf | 2008-12-23 14:52:02 |
画像/reports_2006052101_03ie6.jpg | msakamoto-sf | 2008-12-23 14:51:25 |
配列とハッシュの基本的な作成・アクセス方法を確認する。
use strict; use warnings; use Data::Dumper; my @ary1 = (1, 2, 3, (4, 5, 6), (7, (8, 9), ), ); print @ary1, "\n"; print Dumper(@ary1), "\n"; print $ary1[0], "\n"; print $ary1[@ary1-1], "\n";
123456789 # ← print @ary1 $VAR1 = 1; $VAR2 = 2; $VAR3 = 3; $VAR4 = 4; $VAR5 = 5; $VAR6 = 6; $VAR7 = 7; $VAR8 = 8; $VAR9 = 9; #(ここまでがDumper(@ary1)の出力) 1 # ← print $ary1[0] 9 # ← print $ary1[@ary1-1]
配列作成時の"(...)"は、配列の実体(*1)を作成するコンストラクタ。
従って、変数の"ary1"は、常にリストとして"@"でアクセスする必要がある。
print Dumper($ary1), "\n";
は、
Global symbol "$ary1" requires explicit package name at hoge.pl line 7. Execution of hoge.pl aborted due to compilation errors.
となる。すなわちスカラーとしての"ary1"をシンボルテーブルから探そうとしてしまう。
次の記法にも注意。
print $ary1[@ary1-1], "\n";
要するに配列の最大要素数-1により、配列の末尾にアクセスしている。ここで@ary1 を -1 することで、
ということで、配列の末尾要素にアクセスできている。
my $ary2 = [ 1, 2, 3, (4, 5, 6), [7, 8, 9] ]; print $ary2, "\n"; print Dumper($ary2), "\n"; print $ary2->[0], "\n"; print $ary2->[6], "\n"; print $ary2->[6][0], "\n"; my $ary_buf = $ary2->[6]; print $ary_buf->[0], "\n"; print $ary_buf->[@$ary_buf - 1], "\n";
ARRAY(0x18c35ac) # ← print $ary2 $VAR1 = [ 1, 2, 3, 4, 5, 6, [ 7, 8, 9 ] ]; 1 # ← print $ary2->[0] ARRAY(0x274e6c) # ← print $ary2->[6] 7 # ← print $ary2->[6][0] 7 # ← print $ary_buf->[0] 9 # ← print $ary_buf->[@$ary_buf - 1]
"[", "]"は''名無し配列コンストラクタ''(Effective Perl)であり、その返すものはリファレンスである。従って、リファレンス全般で要素アクセスに使われる"->"を用いて各インデックスの値にアクセスできる。
前掲のコードピースでは名無し配列を多段に組んでいる。この場合、入れ子になった配列のリファレンスを取り出し、$ary_bufとしてアクセスできている。
$ary2->[6][0]
も、
$ary_buf->[0]
も、両方同じ"7"を取得できている。
my @ary3 = (1, 2, 3); print join(" ", @ary3), "\n"; # ... (a) for(my $i = 0; $i < @ary3; $i++) { $ary3[$i]++; } print join(" ", @ary3), "\n"; # ... (b) foreach my $e (@ary3) { $e++; } print join(" ", @ary3), "\n"; # ... (c) foreach (@ary3) { $_++; } print join(" ", @ary3), "\n"; # ... (d) for my $i (@ary3) { $i++; } print join(" ", @ary3), "\n"; # ... (e) for (@ary3) { $_++; } print join(" ", @ary3), "\n"; # ... (f)
1 2 3 # (a) 2 3 4 # (b) 3 4 5 # (c) 4 5 6 # (d) 5 6 7 # (e) 6 7 8 # (f)
(a)は基本中の基本であるが、よりエレガントに見える書き方は (d) や (f) であろう。いずれにせよ、どの書き方も正しく配列の要素を+1できている。
なお、前掲のコードピースは配列の実体を対象にしてのコードだった。下記に、同じ出力結果になる、名無し配列リファレンスを使用した場合のコードを示す。
my $ary3b = [1, 2, 3]; print join(" ", @$ary3b), "\n"; for(my $i = 0; $i < @$ary3b; $i++) { $ary3b->[$i]++; } print join(" ", @$ary3b), "\n"; foreach my $e (@$ary3b) { $e++; } print join(" ", @$ary3b), "\n"; foreach (@$ary3b) { $_++; } print join(" ", @$ary3b), "\n"; for my $i (@$ary3b) { $i++; } print join(" ", @$ary3b), "\n"; for (@$ary3b) { $_++; } print join(" ", @$ary3b), "\n";
print するだけのミニマムテストでは分かりづらいが、
print $ary[0]
と
print @ary[0]
は異なる。
前者は"$"が付いている為スカラーコンテキストで評価され、配列の要素としてアクセスされる。後者は"@"が付いている為、配列、すなわち''スライス''としてアクセスされる。
my @ary4 = ("abc", "def", "ghi", "jkl", "mno"); print $ary4[0], "\n"; print @ary4[0], "\n"; # ← (a) print $ary4[1, 2], "\n"; # ← (b) print join(" ", @ary4[1, 2]), "\n"; print join(" ", @ary4[1 ... 4]), "\n"; print join(" ", @ary4[1 ... 5]), "\n"; # ← (c)
Scalar value @ary4[0] better written as $ary4[0] at ... (a) Multidimensional syntax $ary4[1, 2] not supported at ... (b) abc # ← print $ary4[0] abc # ← print @ary4[0] ... (a) ghi # ← print $ary4[1, 2] ... (b) def ghi # ← print join(" ", @ary4[1, 2]) def ghi jkl mno # ← print join(" ", @ary4[1 ... 4]) Use of uninitialized value in join or string at ... (c) def ghi jkl mno
(a), (b) のようにスカラーが予想される値を"@"としてアクセス(a)したり、スライスが予想される値を"$"としてアクセス(b)すると、警告が発せられる。
またスライスでも、要素INDEXを越えてアクセスしようとすると(c)のように警告が発せられる。
書いている本人自身も実は何回も間違えているように、Perl初学者にとってはとにかく間違いやすい。 Perlにおいてはコンテキストが重要であり、変数がどのコンテキストで評価されるのかは、その冒頭に付く文字($, @, %, *)で判断される (それに加えて、前後のコードも関係する)。これについて、人間側で感情的な割り切りを行えれば、大分Perlの学習と理解も進むのかも知れない。
my @ary5 = ("abc", "def", "ghi", "jkl", "mno"); #--------------------- (a) : 末尾要素を削除 my $buf = pop @ary5; print join(" ", @ary5), "\n"; print $buf, "\n"; #--------------------- (b) : 末尾要素に追加 $buf = push(@ary5, 7); print join(" ", @ary5), "\n"; print $buf, "\n"; #--------------------- (c) : 先頭要素を削除 $buf = shift @ary5; print join(" ", @ary5), "\n"; print $buf, "\n"; #--------------------- (d) : 先頭要素に追加 $buf = unshift(@ary5, "xyz"); print join(" ", @ary5), "\n"; print $buf, "\n"; #--------------------- (e) : スカラーコンテキストで評価 print scalar(@ary5), "\n";
#--------------------- (a) : 末尾要素を削除 abc def ghi jkl mno # 削除された要素の値 #--------------------- (b) : 末尾要素に追加 abc def ghi jkl 7 5 # 追加後の配列の要素数 #--------------------- (c) : 先頭要素を削除 def ghi jkl 7 abc # 削除された要素の値 #--------------------- (d) : 先頭要素に追加 xyz def ghi jkl 7 5 # 追加後の配列の要素数 #--------------------- (e) : スカラーコンテキストで評価 5
undef代入の幾つかのパターンと、空のリストで有ることをどうやって判別を示す。
#--------------------- (a) my @ary6 = (); if(@ary6) { print Dumper @ary6, "\n"; } else { print "ary6 is not defined.(a)\n"; } #--------------------- (b) @ary6 = undef; if(@ary6) { print Dumper @ary6, "\n"; } else { print "ary6 is not defined.(b)\n"; } #--------------------- (c) @ary6 = 1 .. 5; @ary6[2, 4] = undef; print Dumper @ary6, "\n"; #--------------------- (d) undef @ary6; if(@ary6) { print Dumper @ary6, "\n"; } else { print "ary6 is not defined.(d)\n"; }
#--------------------- (a) ary6 is not defined.(a) #--------------------- (b) $VAR1 = undef; $VAR2 = ' '; #--------------------- (c) $VAR1 = 1; $VAR2 = 2; $VAR3 = undef; $VAR4 = 4; $VAR5 = undef; $VAR6 = ' '; #--------------------- (d) ary6 is not defined.(d)
注意すべきは、 defined は Perl5.004以降、スカラー変数を対象とするようになり、配列やハッシュは非推奨になっている 点である。
このため、下記のコードはwarningを生成する。
if(defined(@ary6)) { ... → defined(@array) is deprecated at ... (Maybe you should just omit the defined()?)
では、厳密な意味で "@ary6" がundefなのか、空リストであるのか、をどうやって見分けるのか?については残念ながら現段階では調べ切れていない。%::などを用いて直接シンボルテーブルにアクセス・・・しても、lexical変数であればそれも無意味である。
とりあえず、
my @ary = (); # or undef @ary;
は偽になるが、
my @ary = undef;
は偽にならないという点に十分注意する。
ハッシュについてはその基本操作の殆どが、冒頭でリンクとして挙げたPerl講座で網羅されている。ここでは実体のコンストラクタである"(", ")"と、リファレンスコンストラクタ"{", "}"の差異をメインに、ざっと流すに留める。(*3)
my %h1 = ( abc => 123, "def" => 456, 'ghi' => 789 ); #--------------------- (a) print Dumper(%h1), "\n"; #--------------------- (b) print $h1{'abc'}, "\n"; #--------------------- (c) while(my ($key, $val) = each(%h1)) { print "[$key] = $val\n"; }
#--------------------- (a) $VAR1 = 'def'; $VAR2 = 456; $VAR3 = 'abc'; $VAR4 = 123; $VAR5 = 'ghi'; $VAR6 = 789; #--------------------- (b) 123 #--------------------- (c) [def] = 456 [abc] = 123 [ghi] = 789
for my $key (sort(keys(%h1))) { print "[$key] = ", $h1{$key}, "\n"; } → [abc] = 123 [def] = 456 [ghi] = 789
"(", ")"を用いるとハッシュの実体を作成できた。続いて、 名無しハッシュ のコンストラクタである"{", "}"の使用例を示す。
my $h2 = { abc => 123, "def" => (4, 5, 6), "ghi" => [7, 8, 9 ] }; #--------------------- (a) print Dumper($h2), "\n"; #--------------------- (b) print $h2->{'abc'}, "\n"; print $h2->{'def'}, "\n"; print $h2->{'ghi'}, "\n"; print $h2->{'ghi'}->[0], "\n"; print $h2->{'ghi'}->[1], "\n"; print $h2->{'5'}, "\n"; #--------------------- (c) while(my ($key, $val) = each(%$h2)) { print "[$key] = $val\n"; }
#--------------------- (a) $VAR1 = { 'def' => 4, 'abc' => 123, 'ghi' => [ 7, 8, 9 ], '5' => 6 # ← !!注意!! }; #--------------------- (b) 123 # $h2->{'abc'} 4 # $h2->{'def'} ARRAY(0x275028) # $h2->{'ghi'} 7 # $h2->{'ghi'}->[0] 8 # $h2->{'ghi'}->[1] 6 # $h2->{'5'} #--------------------- (c) [def] = 4 [abc] = 123 [ghi] = ARRAY(0x275028) [5] = 6 # ← !!注意!!
実際のところ、"=>"を使用せずともハッシュは作れるようである。要は変数が"%"としてハッシュコンテキストで実体が代入されるか、"{", "}" で囲まれたリストとしてハッシュのリファレンスで代入されるか、どちらでもハッシュとして扱えるようである。
my %h3 = ( "abc", 123, "def", 4, 5, 6, "ghi", [7, 8, 9] ); my $h4 = { "abc", 123, "def", 4, 5, 6, "ghi", [7, 8, 9] }; #--------------------- (a) print Dumper(%h3), "\n"; print Dumper(%$h4), "\n"; #--------------------- (b) print Dumper(\%h3), "\n"; print Dumper($h4), "\n";
#--------------------- (a) # %h3 $VAR1 = 'def'; $VAR2 = 4; $VAR3 = 'abc'; $VAR4 = 123; $VAR5 = 'ghi'; $VAR6 = [ 7, 8, 9 ]; $VAR7 = '5'; $VAR8 = 6; # %$h4(ハッシュコンテキストで評価) $VAR1 = 'def'; $VAR2 = 4; $VAR3 = 'abc'; $VAR4 = 123; $VAR5 = 'ghi'; $VAR6 = [ 7, 8, 9 ]; $VAR7 = '5'; $VAR8 = 6; #--------------------- (b) # \%h3(リファレンス経由で評価) $VAR1 = { 'def' => 4, 'abc' => 123, 'ghi' => [ 7, 8, 9 ], '5' => 6 }; # $h4 $VAR1 = { 'def' => 4, 'abc' => 123, 'ghi' => [ 7, 8, 9 ], '5' => 6 };
見ての通り、コンテキストさえ合わせればどちらも同じ形式で扱えるようである。
my %h5 = ("abc" => 123, "def" => 456, "ghi" => 789); my $h6 = {"abc" => 123, "def" => 456, "ghi" => 789}; #--------------------- (a) print join(" ", @h5{"abc", "ghi"}), "\n"; print join(" ", @$h6{"def", "ghi"}), "\n"; #--------------------- (b) @h5{"ghi", "abc"} = @h5{"abc", "ghi"}; @$h6{"def", "abc"} = @$h6{"abc", "def"}; for my $key (sort(keys(%h5))) { print "[$key] = ", $h5{$key}, "\n"; } for my $key (sort(keys(%$h6))) { print "[$key] = ", $h6->{$key}, "\n"; } #--------------------- (c) @h5{"abc", "ghi"} = (undef, undef); @$h6{"abc", "def"} = (undef, undef); print Dumper(%h5), "\n"; print Dumper(%$h6), "\n"; #--------------------- (d) my %h7 = (); if(keys(%h7)) { print Dumper(%h7); } else { print "%h7 is empty.\n"; }
#--------------------- (a) 123 789 456 789 #--------------------- (b) # %h5 [abc] = 789 [def] = 456 [ghi] = 123 # $h6 [abc] = 456 [def] = 123 [ghi] = 789 #--------------------- (c) # %h5 $VAR1 = 'def'; $VAR2 = 456; $VAR3 = 'abc'; $VAR4 = undef; $VAR5 = 'ghi'; $VAR6 = undef; # $h6 $VAR1 = 'def'; $VAR2 = undef; $VAR3 = 'abc'; $VAR4 = undef; $VAR5 = 'ghi'; $VAR6 = 789; #--------------------- (d) %h7 is empty.
例:delete @hash_slice{'keyA', 'keyC'};
#!/usr/bin/perl #use strict; <<<< 末尾のprintを使用しなければ有効化して大丈夫。 package test; { my $count; sub countup { $count++; $count; } } package main; print &test::countup(), "\n"; print &test::countup(), "\n"; print &test::countup(), "\n"; print &test::countup(), "\n"; print '$count is not defined', "\n" if !defined($count); print '$test::count is not defined', "\n" if !defined($test::count);
1 2 3 4 $count is not defined $test::count is not defined
只の"{}"でsubを囲む。lexical変数の場合、本当の意味で"機械的に"スコーピングしてくれる為、只の"{}"といえど、その中のmyはその中で保持される。これにより、"staticに見える"状況を創り出している。
シグナルは非常に扱いが難しいです。ここにまとめた文章は依然として「メモ」扱いです。より正確で厳密な記述に、将来書き換えられる可能性もありますし、あるいはそうした外部リソースのリンクが追記される可能性があります。つまり・・・あの、その、これ、まだ私的なメモの段階なので、あんまり信用されるとちょっとまずいです。という感じです。
Inter Process Communication (IPC) でのシグナル(signal)は、非常に奥が深い。というのも
などなど、"同時性"についてかなり面倒くさい考慮が必要になる機構だからだ。
Cから使えるAPIにしても、以下の二系統が存在する。
一般に関数のI/Fが簡便であるのはsignal(2)の方である。シグナルをブロックしたり、ブロック対象のシグナルを細かく制御したりする場合、また子プロセスの終了を緻密に検出したい場合などは、sigaction(2)系を用いると良いらしい。
前掲のperlipcで"signal(3)"で検索すれば見つかるが、Perlでのシグナル処理は基本的にsignal(3)をベースにしている。そのため、sigprocmask(2)やsigsetopts(3)を経由したシグナルのブロッキングはそのままではできない。(POSIXを利用すれば別だが、そうすると次にメモした"Deferred"シグナル機構を迂回してしまう。)
シグナルのブロッキングについては、"local"を用いた巧妙な手法がperlipcに載っている。
sub sig_blocked { local $SIG{ALRM} = 'IGNORE'; &blocked_routine; } sub blocked_routine { # SIGALRMについてブロック中である }
"local"により、%SIGの元の値はスタックに積まれ、sig_blockedを抜けると戻される。blocked_routine()中はSIGALRMを受信しても無視されるようになる。
perlipcに専用の節が設けられているほど重要である。
つまり、Perl 5.7.3 以降については、%SIGを用いる限り、 Perlの内部処理中にシグナルハンドラに飛ぶような事は無くなった と言うことらしい。
たとえIOを処理中であっても、Perlは内部で 適当に区切りの良いところで シグナルが受信されたかチェックしており、もしIO読み書き中でも、シグナルハンドラ処理後ちゃんと再開してくれるらしい。内部的には、Perlはopコードを順繰りに読み進めているわけだが、ちょうどopコードの切れ目のタイミングでシグナルをチェックしてくれているらしい(*2)。
これにより、例えばopコードそれ自体の処理中(メモリIOが発生するタイミングなど)で突然シグナルハンドラに飛んでしまう、というような事はなくなり、全般的に安定性の向上につながっているようだ。
sigaction(2)系を使用したい場合、POSIXモジュールからクラスや関数が提供されている。詳細はPOSIXモジュールのperldocを参照。
但し、perlipcの"Deferred"シグナルの節でもきっちり釘を刺されているが、POSIXを使用する場合、%SIGによる"Deferred"シグナル機構の恩恵を享受できなくなる。つまりPerl内部処理中にシグナルハンドラに入ることによるメモリ・IOの不具合が発生しうるという点に注意する必要がある。
載ってるかなあ・・・。Amazonに注文はしてありますが、まだ届いてないです。
・JSでXMLRPC調べてたら、こんなのがあった。
http://jamritas.sourceforge.net/
ちょっと小さいかな・・・。
・畜生!やられた!!PHP内部コードまで?バイナリアンを自称するだけある・・・。
https://www.codeblog.org/blog/moriyoshi/
・・・なんか、馬鹿らしくなってきたよ・・・。っつーか、HTTPSにしてる理由が分からないけど。
・おお!?大垣さんが、GIHYOでセキュリティ連載!?要チェック!
http://gihyo.jp/dev/serial/01/php-security
あら、こんなのも・・・。
「検索エンジンを作る」
http://gihyo.jp/dev/serial/01/make-findspot
はぁん・・・FINDSPOTね・・・。Hyper EstraierやSennaやLuceneは知ってたけど、これは知らない・・・。
で、Xhwlayではbcidやpage, eventがリクエストで来るわけだけど。一応これ、やばめ除去用のコードは入れてある。
preg_match("/^[0-9A-Za-z_\-,]+$/m")
なんだけど・・・
http://gihyo.jp/dev/serial/01/php-security/0005?page=3
!!げ!? "D"?mじゃなくて?
と思って確認してみたら、意味的にはmでも大丈夫な見たい。
http://jp.php.net/manual/ja/reference.pcre.pattern.modifiers.php
あー、よかった・・・。一応、\r\nや\r混じり、%00交じりをrawurldecodeさせたやつとかでも確認とってるから、大丈夫だとは思ってたんだけど・・・。
とはいえ、XHWLAY_VAR_NAMESPACE_REQUESTとかに入れるのはまずいかもしれない。XHWLAY_VAR_NAMESPACE_INTERNALみたいなの作って、それ使ったほうがイイかなあ・・・。
・「つくるぶ」。ここの「まとめ」、結構イカス。
http://www.tkrb.jp/
2005年頃、"PokoX"というWebアプリのフレームワークを作っていました。第5回PHP勉強会でオレオレフレームワークということで発表したりもしました。
過去のPukiWikiデータを整理していてPokoX関係のデータをこちらに移すか悩んでいたのですが、今更参照する事も無いと思いました。とはいえコンテンツから完全に消去するのも忍びないので、思い出と共にメモしておきます。
Linuxサーバ管理のバイトで、PHP+PostgreSQLのプログラミングを勉強がてら始めた時代に作ったリリース。
当時はDBのマスタ管理画面を作る事が多くて、それをパターン化したもの。
まだ PHP3 の時代で、セッション管理などは PHPLIB とかいうライブラリで実装していた。
テンプレートエンジンの存在など知らない、デザパタも知らない、そんな時代に作成。
ページャ機能も無くて、DB抽象レイヤーも無い。
ようやくSmartyとかADODBとかを知り、少しはまともなアプリが組めるようになり、PEARとかも使い始めた。
大学の卒業と就職の年。
poko1をSmarty/ADODB/PEARのページャ機能を使って作り直したのがpoko2。
とはいえ、poko2は実際に使う事は無かった。フレームワークという考え方にどっぷりはまってしまい、すぐPokoXの作成に移ってしまったから。
基本的にマスタ管理に特化した作りになっていて、DBのテーブル定義をPHPの連想配列で組んでおけば、基本的なマスタ管理画面を自動的に表示してくれる。
ベース部分の作り込みがクラスライブラリで提供されていて、画面やフォームを弄りたければ該当箇所のメソッドをオーバーライドしたクラスを用意する仕組み。
テンプレートの存在を知らないか、知っていても使いこなせていない時代だったので、HTMLの出力はPHP側でクラスのメソッドの中で行っていた。
ヘッダーやフッターもベース部分で全部ハードコードしていた為、HTMLをカスタマイズしようと思ったら相当の苦労が必要だった。
poko1, poko2 は確かにマスタ管理では役に立ったのだけれど、一般公開する表側の画面を作るのには向いていなかった。
ちょうどMojaviやEthnaなどPHPフレームワーク花盛りの頃で、「このままpokoシリーズを続けるか、Mojavi/Ethna/Mapleに転向するか」かなり悩んだ記憶がある。
仕事でPHPをメインとしているわけではなく、どちらかといえば趣味で続けていたため、オレオレフレームワークでも特別困る事が無かった。
悩んだ末に、poko1/2でのキモだったDB機能をごっそりと削り落とし、画面遷移の中核だけを取り出して組み直すことにしたのがPokoX。
PokoXはそれなりに使えて、実際に仕事でも何度か使った。作りが単純なのが幸いして、「フレームワーク側が勝手に処理してるので手を出せない」という事は無かった。使いやすいとは言えないが、決して「作りが悪い」訳ではなかった・・・というのは当然作者の自画自賛なわけだけど。
この「自由度を高くしてアプリ側の制御範囲をなるべく残しておく」という「マージン優先」思想はXhwlayにも受け継がれている。オレオレフレームワークは作者が自分一人の為、機能強化が難しい。ならばいっそのこと、アプリ毎に変動幅が大きい部分は一切タッチせず、コア部分だけを好き勝手弄りやすいようにしておこうというのがPokoX以来の自分なりのフレームワークのポリシー。
2008年時点ではsymfonyやCakePHPなどが台頭し、かなりFW側でがっちり組んでしまっているが、その分Webアプリの作り方がパターン化され、おおよそFW側で殆どカバーできるようになったからだろう。また実際にWebアプリの制作を本業としているプロ達が多数開発に関わっているのだから、FW側の機能も殆どの場合に満足できる質量になったのだろう。
PokoXが一通り落ち着いた後は、memoriesというWikiソフトに舵を切り替えた。
memoriesはYakiBikiの前身で、完成しなかったソフト。
PokoXをベースとして、ADODB抽象化レイヤー、Smartyテンプレートエンジン、log4phpによるロガーを組み込んだ。
ユーザ管理・グループ管理・カテゴリ管理・Blog的なコンテンツ管理のベース部分まで作り込んでいた。
Webアプリとしての「元ネタ」部分は一通り出来上がっていたので、FW的に幾つかのサイトで使った。
完成しなかったのは、やはりWikiエンジンとACLの部分に悩まされていたから。
2006-2007年にPiece Frameworkを知り、Xhwlayの作成に舵を転換。
2007年後半、実際にあるサイトのマスタ管理画面でXhwlayを適用して実用を確認。YakiBikiへ継承。
2007年はsymfonyやCakePHPが浸透した年と記憶している。
そして2008年の1-3月にWebベンチャーでアルバイトをして、symfony/CakePHP/Akelosとかを弄る。
結局、自分の技術ではとてもじゃないが本職が束になって開発したFWに勝てない。
オレオレフレームワークに実に数年に渡りプライベートタイムを費やしてきたが、成果としては実を結んでいないのが実情。まぁXhwlayとYakiBikiが作れたからいっか。
ファイル検索コマンドであるfindは重宝するが、中々使うコツが掴みづらい。自分もコマンドを極めているわけではないが、日常よく使用する例に絞って取り上げる。
ちなみに、以下に紹介するfindの各オプションは、同時に組み合わせることも可能である。
/opt/php ディレクトリ以下で、ファイル名が完全に分かっている場合の例:
$ find /opt/php -name cls_dbmgr.php
/opt/ 以下で、拡張子が.tar.gzのファイルを検索したい場合の例:
$ find /opt -regex ".*\.tar\.gz$" ^^^^^^^^^^^^^^ 正規表現を使用できる。
/opt/php 以下のディレクトリの一覧を取得したい場合の例:
$ find /opt/php/ -type d /opt/php/ /opt/php/libs /opt/php/libs/poko ... /opt/php/logs
"-type"は検索ターゲットのオブジェクトの種類を指定できる。自分が使用しているLinuxのfind(findutilsパッケージ:4.1.20)においては、以下の種類が利用可能である。
b | ブロックデバイスファイル |
c | キャラクタデバイスファイル |
d | ディレクトリ |
p | 名前付きパイプ(FIFO) |
f | 通常のファイル |
l | シンボリックリンク |
s | UNIXソケット |
Webデザインで今も昔も非常に重要な要素である、tableのレイアウトについて気になる点があったので調査しました。
table用のスタイルシートである「table-layout」プロパティを調査し、カラムの幅を固定できるようにする。カラムの幅はem, ex, pt, pxのいずれかで決定できるようにする。
Webデザイン系、業務アプリケーション系を問わず、tableのカラム幅の設定は頭痛のタネである。中に表示するデータの文字数や文字種によって様々に変動してしまうtableに対して、どうやって列幅を固定するか。そのための具体的な手法を調査することで、今後の開発時におけるHTMLレイアウト修正作業を軽減する。
http://www.htmq.com/style/index.shtml#tab
今回調査対象としたもののみを挙げる。
他に以下のプロパティがあるが、IEに対応していなかったり使用頻度が著しく低かったりするため今回の調査では対象外とした。
今回調査対象とした四つの単位についてまとめる。
em, ex指定は文字Mあるいはxの 高さ を基準にしているのであって、幅を基準にしているのではない点に十分注意する必要がある。
通常、サイズ指定を考えるときは「このセルの幅は何文字か」という具合に桁数ベースで考える。もしもこのとき、em/exを幅の単位と考えて使用してしまうと、想定していた幅通りにならない。 桁数ベースで幅を決定するなら、高さと幅が同一の(ように見える)全角文字の等幅フォントを使用するほかない。(文字種も全角文字のみとなる)
pt <> px 変換の中心となるのが、DPIである。 DPIはOSによって異なり、例えばWindowsであれば72DPI, Macであれば96DPIとなっている。 これより、以下の計算式が成立する。(*1)
1pt = 1/72 inch 1px(dot) = 1/72 (win) 1/96 (mac) inch -> (win) 1px = 1/72 inch * 72 px = 1 pt (mac) 1px = 1/96 inch * 72 px = 3/4 pt win : mac = 1 : 3/4 = 4 : 3
よって、 macでの1ptはwinでの4/3ptになる。 ちなみにこれをpx単位で考えると、逆にwinでの1pxはmacでの3/4pxに相当する。
実はこれまでの計算はOS内部における論理的な扱いである。これを実世界のデバイスであるディスプレイに表示する場合は、 PPI(pixels per inch) が関わってくる。これはディスプレイにより変わってくる。
以上見てきたように ユーザーのOSやディスプレイのより、1ピクセルの現実世界における表示サイズが変わってしまう 点に十分留意する必要がある。
数種類のバリエーションのtableを作成し、Firefox 1.5 と IE6 とで表示を比較する。実際に作成したファイルを次のリンクに示す。
http://www.glamenv-septzen.net/medias/reports_2006052101_01.html
作成するテーブルのバリエーションの観点を以下に示す。
幾つか注目に値するバリエーションについて、FF1.5およびIE6での結果を載せる。
FF1.5ではtdタグのborderがtableタグのborderを上書きしているように見える。一方のIE6ではその逆のように見える。枠線と、その中のセルを区切る罫線についてはデザイン上重要な要素であるが、ここまで挙動に違いがあると、border-collapseだけでFF1.5/IE6で同じ見栄えにするのは難しい。
これもFF1.5とIE6では全く挙動が異なる。
tdの幅を超えた部分の文字列をどうするかで、中身の文字列の種類に応じ、FF1.5/IE6でそれぞれ挙動が異なる。まとめると、次のようになる。
文字列種類 | FF1.5 | IE6 |
---|---|---|
連続文字列 | はみ出して表示 | 切り捨て |
全角英語・日本語混在の連続文字列 | 文字種の切れ目を適当に折り返し表示 | 文字種にかかわらず折り返し表示 |
空白混じり | 折り返して表示 | 折り返して表示 |
特に注意が必要なのが連続文字列で、FF1.5だとデフォルトでははみ出して表示してしまう。他の周りのTRやTABLEの属性指定やスタイル指定の影響がどう出るのかは不明だが、いずれにせよこの差異を認識していないと、頭痛のタネになることは間違いない。
MS-DOS/Windowsクライアント系の画面と、HTMLの画面はそもそも制御方法がまるで異なると言うことを理解して欲しい。
その上で、真実、 文字の幅・桁数を基準にして幅を「精密に」指定することは、HTMLでは「技術的に不可能」 のようである。
ただし、emやexというのは恐らく、どんな文字でもこの幅を超えることはないという基準点なのではあるまいか?であれば、ぴったり○○文字の幅という制御はできなくとも、"最大"○○文字まで入る、という使い方は十分に出来るはずである。精密に幅を指定するのが不可能であっても、最大文字数幅で合わせておけば、少なくとも途中で情報が切れてしまうことは避けられる。恐らく対応を迫られた場合、その辺りが妥協点となるのではないだろうか。