MW211 EXIT

devlog
PHP/設定系エラー(1)
2012年04月14日
┌──────────────────────────────────────┐
│Fatal error: Allowed memory size of xxxx bytes exhausted                    │
│ (tried to allocate xx bytes) in …                                         │
└──────────────────────────────────────┘
【原因】
  PHPプログラム処理で使用するメモリが規定のサイズを超えた。
  →変数(配列)をいっぱい使うなど贅沢なメモリの使い方の処理をしているなど。
【処置】
  ・プログラムを見直して、使用メモリの省力化をはかる
  ・「php.ini」の「memory_limit」の設定を変更する
分類:PHP
PostgreSQL/シーケンス
2012年04月13日
serial型とかの自動でインクリメントしてれるIDがあった場合、
「表」に対して「表のシーケンス」的なものが自動で生成される。

「表のシーケンス」と「表」は同期を合わせなければならないので、
「表」を空っぽにしたら、以下のように「表のシーケンス」も
初期値に戻さなければならない。
┌──────────────────────────────────────┐
│SELECT SETVAL ('表のシーケンス', 1, false);                                 │
└──────────────────────────────────────┘
#第三パラメータに「false」を指定すると、「1」の手前、つまり「0」が設定される

その後、INSER文をそのシーケンス項目以外に実行してあげれば、
シーケンス項目は自動でインクリメントしてくれる。
┌──────────────────────────────────────┐
│INSERT INTO 表 (列) VALUES ('値');                                          │
│INSERT INTO 表 (列) VALUES ('値');                                          │
│INSERT INTO 表 (列) VALUES ('値');                                          │
└──────────────────────────────────────┘
この場合「1,2,3」が割り振られ、
「表のシーケンス」は「3」となり次回は「4」が割り振られる。

しかし、そのシーケンスを任意の値に指定した場合は、
シーケンスはインクリメントされない。
┌──────────────────────────────────────┐
│INSERT INTO 表 (id, 列) VALUES (1, '値');                                   │
│INSERT INTO 表 (id, 列) VALUES (2, '値');                                   │
│INSERT INTO 表 (id, 列) VALUES (3, '値');                                   │
└──────────────────────────────────────┘
「id」がシーケンス項目にあたるとした場合、自動インクリメントされないので
「表のシーケンス」は「0」のままだ。

┌──────────────────────────────────────┐
│INSERT INTO 表 (列) VALUES ('値');                                          │
└──────────────────────────────────────┘
これで「id」が一意キーであったとして、
次に上記のような「id」を指定しないINSERTをしたら
「id」に「1」が設定されるので、二重キーエラーとなってしまう。

ここは「表のシーケンス」を「3」にする必要がある。

それには、こうだ。
┌──────────────────────────────────────┐
│SELECT SETVAL('表のシーケンス', 3, true);                                   │
└──────────────────────────────────────┘

「pgAdmin」で、INSERT文形式でエクスポート(バックアップ)した時に、
何気に付随しているので要注目だ。
分類:PostgreSQL
ファイルパス「/」と「\」の違い
2012年04月11日
┌───────────┐
│ディレクトリ/ファイル │
├───────────┤
│ディレクトリ\ファイル │
└───────────┘
ディレクトリ(フォルダ)の区切りは「/」の場合と「\」の場合がある。

UNIX(LINUX)系は「/」で、Windows系は「\」らしい。

ちなみに「\」は「\」の半角、つまりバックスラッシュだったのだが、
日本語OSの場合、円マークが割り当てられてしまったので、
一見「/」(スラッシュ)と関連性はないようだが、意味するところは以下のような感じで
非常に似ているといえる。
┌───────────┐
│ディレクトリ/ファイル│
├───────────┤
│ディレクトリ\ファイル│
└───────────┘

以下のように覚えればよいか。
┌────┬───────────┐
│UNIX    │ディレクトリ/ファイル │
├────┼───────────┤
│Windows │フォルダ\ファイル     │
└────┴───────────┘
PDO/LIKE検索
2012年04月10日
┌──────────────────────────────────────┐
│SELECT 列 FROM 表 WHERE 検索列 LIKE '%検索値%';                             │
└──────────────────────────────────────┘
LIKE検索を行う場合、ベタだと上記のような感じだが、
PDOを使う場合は下記のような感じ。
┌──────────────────────────────────────┐
│SELECT 列 FROM 表 WHERE 検索列 LIKE :LIKE検索文字;                          │
└──────────────────────────────────────┘
で、プレースホルダに以下のような感じで「%」毎文字列としてbindしてあげる。
┌──────────────────────────────────────┐
│$sth->bindValue(':LIKE検索文字', '%'.$検索値.'%', PDO::PARAM_STR);          │
└──────────────────────────────────────┘

注意すべきなのは、検索文字の特殊文字をエスケープしてあげねばならぬこと。
「\」「%」「_」の先頭に「\」をつけてあげれよい。

「preg_replace()」で置換する例としては以下のような感じだ。
┌──────────────────────────────────────┐
│$検索値 = preg_replace('/\\\\/', '\\\\\\\\', $検索値);  // \→\\            │
│$検索値 = preg_replace('/%/'   , '\%'      , $検索値);  // %→\%            │
│$検索値 = preg_replace('/_/'   , '\_'      , $検索値);  // _→\_            │
└──────────────────────────────────────┘

なおこれらは、「standard_conforming_strings」の設定とは別の話だから注意。

ってことで、初心者が陥りやすいミスはこんな感じ。
┌─┬────────────────────────────────────┐
│  │$sql = 'SELECT * FROM 表 WHERE 列 LIKE %:like%';                        │
│×│$sth = $PDO->prepare($sql);                                             │
│  │$sth->bindValue(':like', '値', PDO::PARAM_STR);                         │
├─┼────────────────────────────────────┤
│  │$sql = 'SELECT * FROM 表 WHERE 列 LIKE :like';                          │
│○│$sth = $PDO->prepare($sql);                                             │
│  │$sth->bindValue(':like', '%値%', PDO::PARAM_STR);                       │
└─┴────────────────────────────────────┘
分類:PDO
PHP/「\」の扱い
2012年04月09日
PHPにおける「\」の扱い(*1)
  ・「\\」は「\」に変換され、残った「\」は「\」の扱いとなる
  →「\」の数を2で割って端数を切り上げた数が、実質的な「\」の数となる
  *1:「'」もしくは「"」で囲われた文字列中の場合

PostgreSQLにおける「\」の扱い(*2)
  ・「\\」は「\」に変換され、残った「\」は無視される
  →「\」の数を2で割って端数を切り捨てた数が、実質的な「\」の数となる
  *2:「standard_conforming_strings = off」または「E''」の中での扱い

よって、記述内容と、実質的な意味の関係はこんな感じ。
┌─────┬───┬───┬───┬───┐
│          │   \d │  \\d │ \\\d │\\\\d │
├─────┼───┼───┼───┼───┤
│   PHP    │   \d │   \d │  \\d │  \\d │
├─────┼───┼───┼───┼───┤
│PostgreSQL│    d │   \d │   \d │  \\d │
└─────┴───┴───┴───┴───┘
分類:PHP
PHP/バックスラッシュ
2012年04月08日
PHPにおいて、「'」(もしくは「"」)で囲われた文字列中の
「\」(バックスラッシュ)は特別な意味をもつ…らしい。

どんな、特別な意味を持つのか、echoしてみれば一目瞭然
┌──────────────────────────────────────┐
│echo '\';       →閉じるの「'」をエスケープしてしまいエラー                 │
│echo '\\';      →「\」                                                     │
│echo '\\\';     →閉じるの「'」をエスケープしてしまいエラー                 │
│echo '\\\\';    →「\\」                                                    │
│echo '\d';      →「\d」                                                    │
│echo '\\d';     →「\d」                                                    │
│echo '\\\d';    →「\\d」                                                   │
│echo '\\\\d';   →「\\d」                                                   │
└──────────────────────────────────────┘

つまりは、以下のとおり。
  (1) 「\」は直後の文字をエスケープする(エスケープ用文字)
  (2) 「\\」は文字としての「\」に変換される(先頭から順に)
  (3) よって、連続する「\」の数が奇数の場合、最後の「\」はエスケープ用文字となる
  (4) エスケープ用文字「\」は「'」や「"」など、文字囲いには影響を与えるが
      いわゆる正規表現の文字(\dや\w)となっても、
      その文字列なだけでその中身([0-9]とか)にはならない

「preg_match()」など正規表現を使う時には、まず上記の一時変換がなされた後に
その結果を元に正規表現として変換するので
「preg_match('/\d/',…)」も「preg_match('/\\d/',…)」も
「\d」と入力されたのと同じものとして、「[0-9]」的なものに変換される。

但し、「\」を検索文字としたい場合には、正規表現上「\\」でなければならず
そのように変換される元の文字は「\\\\」(もしくは「\\\」)なので
「preg_match('/\\\\/',…)」とPHP上は表記することになる。
※「\\\」が許容されるのは「/\\\/」が「/」+「\\」+「\/」と区切られるのではなく
  「/」+(「\\」+「\」)+「/」と区切られるからのようだ

つまり「preg_match('/\\d/',…)」的な方が正しいのかもしれないが
結果オーライで「preg_match('/\d/',…)」が使用されているのが多数派。
ただし「preg_match('/\\\\/',…)」の意味がよくわからなくなり
「preg_match('/\\\/',…)」も許容されるので訳がわからなくなるという感じか。
分類:PHP
PHP/「\」を「\\」に置換する方法
2012年04月07日
「\」(バックスラッシュ)は、PHPとしても、正規表現としても特殊な意味をもつので
その取扱いがややこしい。

結論からいうと、「preg_replace()」を使った場合、以下のような感じだ。
┌──────────────────────────────────────┐
│$置換後 = preg_replace('/\\\\/', '\\\\\\\\', $置換前);                      │
└──────────────────────────────────────┘

┌──────────────────────────────────────┐
│(1) PHPとして、「'」で囲われた文字中の「\\」は「\」になる                   │
├──────────────────────────────────────┤
│(2) 正規表現として、文字としての「\」を表すのは「\\」(※)                   │
│    ※検索文字だけでなく置換後文字についても該当するので注意                │
└──────────────────────────────────────┘
よって「\」数の「1→2」を行いたい場合「1×4→2×4」=「4→8」となる。

ただ、(1)の原則は時に忘れられがちなので注意が必要だ。

例えば次の二つは同じ意味になるから、たいていは(a)を使う。
┌──────────────────────────────────────┐
│(a) $置換後 = preg_replace('/\d/', '_', $置換前);                           │
├──────────────────────────────────────┤
│(b) $置換後 = preg_replace('/\\d/', '_', $置換前);                          │
└──────────────────────────────────────┘

さきほどの(1)を補足するならば、以下のような感じだろうか。
┌──────────────────────────────────────┐
│(1) PHPとして、「'」で囲われた文字中の「\\」は「\」になる                   │
│    (が、端数の「\」は「\」になる)                                          │
└──────────────────────────────────────┘
#「\」の後続に続く文字によって挙動が変わるという言い方もある

結局のところ「\」自身を使う場面でなければ(1)の原則はあまり意識されない。
日頃から原則に従って(b)を使うように徹底すれば、なんてことはないのだが
突然「\」を使う段になって、(1)のような話に出くわすと結構焦る。
(a)もすべて(b)に置換しなきゃダメなのかという恐怖感に襲われたりして。

なので、(b)を徹底しないまでも(徹底する必要もないのかもしれないが)、
この考え方はしっかり覚えておくべきだろう。
分類:PHP
PostgreSQL/9.0と9.1の違い(2)
2012年04月06日
PostgreSQLの9.0と9.1では「standard_conforming_strings」の既定値が変更になった。
┌────┬─────────────────┐
│9.0以前 │standard_conforming_strings = off │
├────┼─────────────────┤
│9.1以降 │standard_conforming_strings = on  │
└────┴─────────────────┘

比較すると、こんな感じ。
┌────────┬───────┬───────┬───────┐
│                │ E''で囲った  │ 9.0以前(off) │ 9.1以降(on)  │
├────────┼───────┼───────┼───────┤
│特殊文字「\d」  │E'\\d'        │'\\d'         │'\d'          │
├────────┼───────┼───────┼───────┤
│「\」の一致     │= E'\\'       │= '\\'        │= '\'         │
├────────┼───────┼───────┼───────┤
│「\」のLIKE一致 │LIKE E'%\\\\%'│LIKE '%\\\\%' │LIKE '%\\%'   │
└────────┴───────┴───────┴───────┘

これまでは、常時「正規表現ですよ」という臨戦態勢だったのが、
これからは、「E''」で囲った時だけ特別に「正規表現ですよ」という風になった。

なお、PDOではこの設定値をみて、差異を吸収してくれるので
「standard_conforming_strings = on」状態のような感じで
値を指定してあげれば(「\」とかおおめに指定しなくてもよい、これまでもそう)、
よろしくやってくれる。
分類:PostgreSQL
PostgreSQL/9.0と9.1の違い(1)
2012年04月05日
PostgreSQLの9.0と9.1では「standard_conforming_strings」の既定値が変更になった。
┌────┬─────────────────┐
│9.0以前 │standard_conforming_strings = off │
├────┼─────────────────┤
│9.1以降 │standard_conforming_strings = on  │
└────┴─────────────────┘

エスケープ文字の扱いは以下のように違う。
┌──┬───┬───┬───┬───┐
│    │'     │"     │\     │\     │
├──┼───┼───┼───┼───┤
│off │'\''  │'"'   │'\\'  │E'\\' │
├──┼───┼───┼───┼───┤
│on  │''''  │'"'   │'\'   │E'\\' │
└──┴───┴───┴───┴───┘

よって、サニタイズの仕方も以下のように違ってくる。
┌───────┬───────┐
│ 9.0以前(off) │ 9.1以降(on)  │
├───────┼───────┤
│「'」→「\'」 │「'」→「''」 │
├───────┼───────┤
│「"」→「\"」 │  (そのまま)  │
├───────┼───────┤
│「\」→「\\」 │              │
└───────┴───────┘
分類:PostgreSQL
競馬オッズの注意点
2012年04月04日
単勝一番人気は「オッズが最小のもの」ではない。
一票も得票がない「0倍」が一番人気になってしまう危険性がある。

よって、「オッズが0倍を除く最小のもの」としなければならない。

「得票数が最大のもの」だと安全なのだが、
たいていはオッズの方のみが公開されてるものだ。
分類:注意、設計
前へ 1 2 3 次へ