MW211 EXIT

devlog
PHP/NULLを文字列結合すると文字型になる
2011年10月25日
「gettype()」って便利な関数があって、変数のデータ型を調べられるのだが、
以下のような結果となった。
┌──────────────────────────────────────┐
│echo gettype(NULL);                                                 →NULL  │
│echo gettype(NULL . NULL);                                          →string│
└──────────────────────────────────────┘
つまりは、NULLを文字列結合すると文字型扱いとなるのだ。

ってことは、「is_null(NULL . NULL)」は偽となってしまうのである。

これは変数を介した時にハマりやすい罠だ。
「$c = $a . $b;」で「if (is_null($c)) {…」とかって処理を書いてしまうと
「$a」も「$b」もNULLの場合、当然真になる…なんて間違いを犯してしまうことになる。
分類:PHP、注意
PHP/配列でSQL抽出
2011年10月24日
配列$idに抽出したいIDを格納しておいて、
これを元にSELECT文を発行したい場合には、以下のような感じに
「implode()」で「,」区切り一直線に連結して「WHERE IN()」の中にぶち込むとよい。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE "ID" IN ({implode(',', $id)});                                    │
└──────────────────────────────────────┘
#これはあくまでイメージで、実際には「.」とかで文字列結合してください

すると以下のようになるわけだ。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE "ID" IN (1,2,3);                                                  │
└──────────────────────────────────────┘

しかし、配列$idに一件もIDがないと、以下のようになって当然エラー。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE "ID" IN ();                                                       │
└──────────────────────────────────────┘

ということで、これを回避するには、「WHERE IN()」の部分に
ありえない値を入れるのが手っ取り早いのではないだろうか。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE "ID" IN (0);                                                      │
└──────────────────────────────────────┘
※IDが「1」から始まり「0」がないことが前提

万全を期すならば「WHERE IN()」の部分を「WHERE FALSE」に
(条件分岐で)置換してあげるという手もある
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表                                                                 │
│    WHERE FALSE;                                                            │
└──────────────────────────────────────┘

間違っても、WHERE句毎削除してはいけない。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│    FROM 表;                                                                │
└──────────────────────────────────────┘
全件ひっかかってしまう(該当ありになってしまう)からだ。
分類:SQL、PHP配列
PostgreSQL/順番の末尾にデータを追加したい場合
2011年10月23日
順番を示す項目について、データを追加する場合に
その時点で存在するデータの最大値に+1して追加したい場合、
以下のようにSELECTで最大値をひっぱてきて、それに+1してINSERTする。
┌──────────────────────────────────────┐
│INSERT INTO "表"                                                            │
│           ("名前","順番")                                                  │
│    SELECT '文字',                                                          │
│           MAX("順番") + 1                                                  │
│        FROM "表";                                                          │
└──────────────────────────────────────┘
しかし、これだと最初に追加する場合、エラーになってしまう(データが追加できない)。
つまり、順番を示す項目の最大値が該当なしでNULLとなってしまい、+1できないのだ。

そこで、ひと手間。
以下のようにNULLの場合に0に変換する「COALESCE()」をはさんであげるとよい。
#COALESCE()は引数(配列)中のNULLじゃない最初のデータを採用する関数
┌──────────────────────────────────────┐
│INSERT INTO "表"                                                            │
│           ("名前","順番")                                                  │
│    SELECT '文字',                                                          │
│           COALESCE(MAX("順番"), 0) + 1                                     │
│        FROM "表";                                                          │
└──────────────────────────────────────┘
ちなみに、SELECTは()で括れば個別に引用できるので、以下のようにもできる。
┌──────────────────────────────────────┐
│INSERT INTO "表"                                                            │
│           ("名前","順番")                                                  │
│    VALUES ('文字',                                                         │
│            COALESCE((SELECT MAX("順番")                                    │
│                          FROM "表";                                        │
│                     ), 0) + 1;                                             │
└──────────────────────────────────────┘
これだと複数のテーブルから様々な項目を参照できる。
分類:PostgreSQL
PHP/try&catchのサブ関数化
2011年10月22日
元々、こんな感じでtry&catchな処理を行っているとする。
┌──────────────────────────────────────┐
│public function メソッド() {                                                │
│  try {                                                                     │
│    $dbh = new PDO(…);                                                     │
│  } catch (PDOException $e){                                                │
│    echo $e->getMessage();                                                  │
│  }                                                                         │
│}                                                                           │
└──────────────────────────────────────┘
だけど、一部、サブ関数化(サブメソッド化)して他に持っていきたい場合がある。
例えばこんな感じ。
┌──────────────────────────────────────┐
│public function メソッド() {                                                │
│  try {                                                                     │
│    $dbh = $this->サブメソッド;                                             │
│  } catch (PDOException $e){                                                │
│    echo $e->getMessage();                                                  │
│  }                                                                         │
│}                                                                           │
├──────────────────────────────────────┤
│public function サブメソッド() {                                            │
│  $dbh = new PDO(…);                                                       │
│  return $dbh;                                                              │
│}                                                                           │
└──────────────────────────────────────┘
でもtryの中身を他に持っていくと、catchができなくなる。
メイン側で、サブ関数から戻ってきた直後にエラー判定して、
疑似的にエラーにして、catchに拾ってもらう?
いやいや、そんな面倒なことはしなくてよい。
「throw」してやればいいのだ。
┌──────────────────────────────────────┐
│public function メソッド() {                                                │
│  try {                                                                     │
│    $dbh = $this->サブメソッド;                                             │
│  } catch (PDOException $e){                                                │
│    echo $e->getMessage();                                                  │
│  }                                                                         │
│}                                                                           │
├──────────────────────────────────────┤
│public function サブメソッド() {                                            │
│  try {                                                                     │
│    $dbh = new PDO(…);                                                     │
│  } catch (PDOException $e){                                                │
│    throw $e;                                                               │
│  }                                                                         │
│  return $dbh;                                                              │
│}                                                                           │
└──────────────────────────────────────┘
エラー情報のたらいまわしですな。
分類:PHP
JavaScript/formの送信項目を送信しない
2011年10月21日
form内にhidden属性か何かで入力項目を設定しておくと、
submit時にその項目が飛び先に送られる。
飛び先側では、「$_POST['項目名']」とかでその値を参照できる。

しかし、事情により、formの中に項目は設定してしまったんだけど
submit時に除外したい場合の方法(を模索中)。
(submitしないで、link系でページ遷移すればいいじゃんというのはナシ)
┌──────────────────────────────────────┐
│<form method="post" action="飛び先.php">                                    │
│<input type="hidden" name="項目名" value="値"/>                             │
│<input type="submit" value="送信したふり"                                   │
  onclick="document.getElementsByName('項目名')[0].removeAttribute('name');"/>│
│</form>                                                                     │
└──────────────────────────────────────┘
これだと、飛び先に「$_POST['項目名']」は送られない。

submit時に「removeAttribute()」で自身の属性名自体を削除して
自身の存在を消している(ようにしている)。

もっといい方法がありそうだが、DOMを熟知していないので、今はここまで。
分類:JavaScript
JavaScript/submitボタンを明細毎につける
2011年10月20日
以下のような「選択」ボタンが明細毎に存在する画面があって
ボタンを押した飛び先に、明細のIDを渡したい場合がある。
┌─┬───────────────────────────────┌──┐┐
│ 1│明細1                                                        │選択││
├─┼───────────────────────────────├──┤┤
│ 2│明細2                                                        │選択││
├─┼───────────────────────────────├──┤┤
│ 3│明細3                                                        │選択││
└─┴───────────────────────────────└──┘┘

GETパラメータで渡すのは簡単で、以下のようにURIを編集してlinkしてあげればよい。
┌──────────────────────────────────────┐
│<input type="button" value="選択" onclick="window.open('飛び先.php?id=1',… │
│<input type="button" value="選択" onclick="window.open('飛び先.php?id=2',… │
│<input type="button" value="選択" onclick="window.open('飛び先.php?id=3',… │
└──────────────────────────────────────┘

しかし、POSTパラメータとして渡すとなるとsubmitボタンとなり、
以下のように識別子が入り込む余地がない(ように見える)。
┌──────────────────────────────────────┐
│<form method="post" action="飛び先.php">                                    │
│<input type="submit" value="選択"/>                                         │
│<input type="submit" value="選択"/>                                         │
│<input type="submit" value="選択"/>                                         │
│</form>                                                                     │
└──────────────────────────────────────┘

ベタな方法としては、以下のようにname属性を分けて、
飛び先で、$_POSTを全件ループして、キーが「submit_id_xxxx」のものを抽出し、
さらに「submit_id_」を除外すればidが取得(復元)できる。
┌──────────────────────────────────────┐
│<form method="post" action="飛び先.php">                                    │
│<input type="submit" name="submit_id_1" value="選択"/>                      │
│<input type="submit" name="submit_id_2" value="選択"/>                      │
│<input type="submit" name="submit_id_3" value="選択"/>                      │
│</form>                                                                     │
└──────────────────────────────────────┘

JavaScriptが使えるならもう少しスマートな方法がある。
┌──────────────────────────────────────┐
│<form method="post" action="飛び先.php">                                    │
│<input type="hidden" name="id"/>                                            │
│<input type="submit" value="選択" onclick="this.form.id.value='1';"/>       │
│<input type="submit" value="選択" onclick="this.form.id.value='2';"/>       │
│<input type="submit" value="選択" onclick="this.form.id.value='3';"/>       │
│</form>                                                                     │
└──────────────────────────────────────┘
これなら、「$_POST['id']」で一発で受け取ることができる。
分類:JavaScript
PHP/データ量の多い折れ線グラフ描画
2011年10月19日
X軸一目盛に対してY軸の値が一つずつ並んでいるような配列があるとする。

例えばGDを使って以下のように折れ線グラフを描画したりできるような配列だ。
┌──────────────────────────────────────┐
│for ($x = 1; $x < 100; $x++) {                                              │
│  imageline(出力先, $x - 1, $y[x - 1], $x, $y[x], 色);                      │
│}                                                                           │
└──────────────────────────────────────┘

このデータが10倍になったけど描画する領域がそのままの場合。
つまり描画できる横幅よりもデータが多い場合に、
1/10に圧縮して、ローソク足グラフのように、縦幅のあるグラフを描画する方法。
┌──────────────────────────────────────┐
│for ($x = 0; $x < 1000; $x++) {                                             │
│  $y1 = min(array_slice($y, $x, 10));                                       │
│  $y2 = max(array_slice($y, $x, 10));                                       │
│  imageline(出力先, $x, $y1, $x, $y2, 色);                                  │
│}                                                                           │
└──────────────────────────────────────┘
上記のような感じで、「min()、max()、array_slice()」を駆使すればよい。
これで、最小値から最大値までの縦幅のもつ線が横にずらっと並んでいく。
まるで、横に押しつぶしたかのようにだ。
分類:PHP
PHP/ゼロパディング
2011年10月18日
「1」を「0001」とかのいわゆる書式付文字列にして出力する方法。
C言語の「sprintf()」関数を流用する。
以下のような感じ。
┌──────────────────────────────────────┐
│sprintf("%04d", 1)                                                          │
└──────────────────────────────────────┘
分類:PHP
PHP/画像ファイルのアップロード
2011年10月17日
まず、「$_FILES[識別名]['type']」で、ファイル種類を取得できるが、
信用できないらしい。
情報元がブラウザに依存し、ブラウザによっては情報を提供しないものがあり
必ずしも取得できるわけではない(らしい)。
とにかく、アテにしない方がいいみたい。

で、代替案…(つづく)
分類:PHP
PHP/画像のアップロード
2011年10月16日
入力方法としては、formの中に以下のinputタグを置き、submitさせる。
┌──────────────────────────────────────┐
│<input type="file" name="識別名"/>                                          │
└──────────────────────────────────────┘
※上記タグは以下のような入力欄となる。
┌──────────────────────────────────────┐
│┌────────┐┌───┐                                              │
││                ││参照..│                                              │
│└────────┘└───┘                                              │
└──────────────────────────────────────┘

アップロード処理は「move_uploaded_file()」で行う。
さきほどのタグによる入力欄に投入した情報は、「$_FILES[識別名]」に格納される。
┌──────────────────────────────────────┐
│if (move_uploaded_file($_FILES[識別名]['tmp_name'], 新ファイル名)) {        │
│  chmod(新ファイル名, 0644);  // Windowsの場合は不要                        │
│} else {                                                                    │
│  echo 'エラー:アップロードできませんでした';                              │
│}                                                                           │
└──────────────────────────────────────┘
Unix系の場合はファイルアクセス権限があるので「chmod()」で適宜変更してあげる。

「$_FILES[識別名]」の中身はこんな感じになっている
┌──────────────────────────────────────┐
│Array (                                                                     │
│  [name]     => xxxx.png       アップロード時のファイル名                   │
│  [type]     => image/x-png    アップロードしたファイルの種類               │
│  [tmp_name] => xxxx/xxxx.tmp  アップロード直後の一時ファイル名             │
│  [error]    => 0              エラーコード                                 │
│  [size]     => 1024           ファイルサイズ(バイト単位)                   │
│)                                                                           │
└──────────────────────────────────────┘

なお、事前にいろいろチェックして不正なデータをはじく必要がある。

まずはファイルを指定されたかのチェック。
┌──────────────────────────────────────┐
│if ((!isset($_FILES[識別名]))                                               │
│ || (!is_uploaded_file($_FILES[識別名]['tmp_name']))) {                     │
│  echo 'エラー:ファイルを指定してください';                                │
│}                                                                           │
└──────────────────────────────────────┘

ファイルサイズが大きすぎないかのチェック。
┌──────────────────────────────────────┐
│$filesize = filesize($_FILES[識別名]['tmp_name']);                          │
│if ($filesize > (1 * 1024 * 1024 * 1024)) {  // 1Gバイト                    │
│  echo 'エラー:ファイルのサイズが大きすぎます';                            │
│}                                                                           │
└──────────────────────────────────────┘

ファイルの種類が意図したものかのチェック(GDを使用)。
┌──────────────────────────────────────┐
│$getimagesize = getimagesize($_FILES[識別名]['tmp_name']);                  │
│switch ($getimagesize['mime']) {                                            │
│  case 'image/png':                                                         │
│  case 'image/jpeg':                                                        │
│    break;                                                                  │
│  default:                                                                  │
│    echo 'ファイルの種類が不正です';                                        │
│    break;                                                                  │
└──────────────────────────────────────┘
分類:PHP
前へ 1 … 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 次へ