MW211 EXIT

devlog
HTML/ファイルを名称変更してダウンロード
2011年09月30日
ファイル(csvファイルとか)をそのままダウンロードする方法は以下の通り。
┌──────────────────────────────────────┐
│<input type="button" value="入手" onclick="location.href='xxxx.xxx'"/>      │
└──────────────────────────────────────┘

これだと実際にあるファイルをそのままひっぱってくる感じだ。
さて、ここでファイル名を任意の名称に変更したい場合はどうすればよいか?
例えば内部管理用のファイル名と外見えのファイル名が違う場合とかだ。

簡単な方法がみつからない。
とりあえず、以下なら実現できる(ちとめんどくさい)。

まずはformで囲い、POSTメソッドで飛ばす。(たいていは自分に戻ってくるようにする)
ただし、その前にひと手間必要なので、JavaScript関数をはさむ。
┌──────────────────────────────────────┐
│<form method="post" action="">                                              │
│<input type="button" value="入手" onclick="dload(this.form,'xxxx.xxx')"/>   │
│</form>                                                                     │
└──────────────────────────────────────┘

JavaScript関数にて、「$_POST['download']」に変更前のファイル名を入れてsubmit。
┌──────────────────────────────────────┐
│<script type="text/javascript"><!--                                         │
│function dload(inForm, inValue){                                            │
│  var new_element = document.createElement('input');                        │
│  new_element.type  = "hidden";                                             │
│  new_element.name  = "download";                                           │
│  new_element.value = inValue;                                              │
│  inForm.appendChild(new_element);                                          │
│  inForm.submit();                                                          │
│}                                                                           │
│--></script>                                                                │
└──────────────────────────────────────┘
本当はsubmit(のvalueに)にファイル名をぶちこんであげれば楽なのだが
submitボタン名に表示されてしまうので、hidden属性を使う。
ボタン名に表示されても構わないのであればJavaScript不要で以下だけで可。
┌──────────────────────────────────────┐
│<form method="post" action="">                                              │
│<input type="submit" name="download" value="xxxx.xxx"/>                     │
│</form>                                                                     │
└──────────────────────────────────────┘

後はPOST先で、ファイル名を生成してダウンロード実行。
┌──────────────────────────────────────┐
│if (isset($_POST['download'])) {                                            │
│  header('Content-Disposition: attachment; filename="'
                                             . ダウンロードファイル名 . '"'); │
│  header('Content-Type: application/octet-stream');                         │
│  readfile(htmlspecialchars($_POST['download'], ENT_QUOTES));               │
│  exit();                                                                   │
│}                                                                           │
└──────────────────────────────────────┘
分類:HTML
JavaScript/POSTメソッドとGETメソッドをネストする方法
2011年09月28日
ということで前回(JavaScript/POSTメソッドとGETメソッドを切り替える方法)からの
続き(「怪獣殿下」を彷彿とさせる初の二話構成です)。

今度は、POSTメソッドの中にGETメソッドを入れる方法(をより真剣に検討)。
┌──────────────────────────────────────┐
│<form method="post" action="xxxx.php">                                      │
│  <input type="button" value="GET実行" onclick="submit2()"/>                │
│  <input type="submit" value="POST実行"/>                                   │
│</form>                                                                     │
└──────────────────────────────────────┘
までは(ほぼ)一緒です
#あ、実はsubmit2()の引数が(使わないから)こっそりなくなってる。

さて、JavaScriptの中ですが、こんな感じでどうでしょうか。
┌──────────────────────────────────────┐
│<script type="text/javascript">                                             │
│function submit2() {                                                        │
│  // 念のためこれから作るformを削除しておく(ある時だけ)                     │
│  var oldForm = document.getElementById("newForm");                         │
│  if (oldForm) {                                                            │
│    oldForm.parentNode.removeChild(oldForm);                                │
│  }                                                                         │
│  // 新規formの設定                                                         │
│  var newForm = document.createElement("form");                             │
│  newForm.setAttribute("method", "get");                                    │
│  newForm.setAttribute("action", "oooo.php");                               │
│  newForm.setAttribute("id"    , "newForm");                                │
│  newForm.style.display="none";                                             │
│  // 新規属性の設定  ※いくつでも設定可能(このブロックを繰り返す)           │
│  var newInput = document.createElement("input");                           │
│  newInput.setAttribute("name" ,name属性名);                                │
│  newInput.setAttribute("value",値);                                        │
│  newForm.appendChild(newInput);                                            │
│  // 新規formの作成とsubmit                                                 │
│  document.getElementsByTagName("body")[0].appendChild(newForm);            │
│  newForm.submit();                                                         │
│}                                                                           │
│</script>                                                                   │
└──────────────────────────────────────┘
ま、JavaScriptの中でformの世界を創ってあげる(でsubmitする)感じですね。
これなら、submitボタン(にあたるもの)がどこにあっても文句をいわれません。
ただし、formの中に定義している各属性は(そのままでは)連れてこれないので
ひとつひとつ「setAttribute()」と「appendChild()」で
(ひっぱってきては)作り直してあげる感じでしょうか。
ひっぱってくる部分は、「getElementById(ID).value」とかでできます。

GETメソッドだったら、URIを作ってしまった方がはやいという話もありますね。
ま、これだとPOSTメソッドへの流用も可能です。
分類:JavaScript
JavaScript/POSTメソッドとGETメソッドを切り替える方法
2011年09月27日
formタグはネストすることができない。
┌──────────────────────────────────────┐
│<form method="post" action="xxxx.php">                                      │
│  <form method="get" action="oooo.php">                                     │
│    <input type="submit" value="GET実行"/>                                  │
│  </form>                                                                   │
│  <input type="submit" value="POST実行"/>                                   │
│</form>                                                                     │
└──────────────────────────────────────┘
だから、上記みたいにPOSTしたい範囲の中にGETしたい範囲があるなんてのは無理。
さて、どうしよう。
ということで、まずはgetのsubmitボタンをJavaScript化して
POSTメソッドのformなのに、GETメソッドとしてsubmitさせるという方法。

まずはformのネストを潔くあきらめて、submitボタンをただのボタンにして
JavaScriptに後を託す。
┌──────────────────────────────────────┐
│<form method="post" action="xxxx.php">                                      │
│  <input type="button" value="GET実行" onclick="submit2(this.form)"/>       │
│  <input type="submit" value="POST実行"/>                                   │
│</form>                                                                     │
└──────────────────────────────────────┘
で、JavaScriptの中でこんな感じで内容を書き換えてsubmitさせてしまうのだ。
┌──────────────────────────────────────┐
│<script type="text/javascript">                                             │
│function submit2(inForm){                                                   │
│  inForm.setAttribute("method","get");                                      │
│  inForm.setAttribute("action","oooo.php");                                 │
│  inForm.submit();                                                          │
│}                                                                           │
│</script>                                                                   │
└──────────────────────────────────────┘

これは、POSTとGETが(立場が)逆の場合も可。
というか、そっちの方がおすすめ。
なぜなら大抵、POSTする内容は量が多いので、GET化(URI化)すると
URIがものすごい長文になってしまい、あまり実用的ではない。
#IE7だと「res://ieframe.dll/dnserror.htm」エラーとかになる。

ということで、明日につづく。
分類:JavaScript
PostgreSQL/数値文字変換
2011年09月26日
本来数値である項目を事情があって文字型項目として保持してたりして
これを本来の数値型に変換して取得したい場合には、「TO_NUMBER()」を使う。
┌──────────────────────────────────────┐
│TO_NUMBER(列,'S999D0')                                                      │
└──────────────────────────────────────┘
こんな感じになる。
第二引数として、書式を指定してやるのがちょっとめんどくさいかも。

一方その反対に数値を文字型に変換するのは「TO_CHAR()」だ。
┌──────────────────────────────────────┐
│TO_CHAR(列,'S999D0')                                                        │
└──────────────────────────────────────┘
こんな感じ(TO_NUMBER()と同じ)。
日付型なんかは以下のような感じで変換できて便利。
┌──────────────────────────────────────┐
│TO_CHAR(列,'YYYY-MM-DD HH24:MI:SS')                                         │
└──────────────────────────────────────┘
さて、話は戻って「TO_NUMBER()」。
こいつが意外と厄介で、入力値(つまり参照する列)に文字列が混じっていると
エラーとなってしまうのである(NULLならOK、''はNG)。

そこで、ISNUMERIC的なことをして条件分岐させたいところだが、見当たらない。
ならばということで、正規表現で数値を抜き出す方法を代案として考えた。
┌──────────────────────────────────────┐
│SUBSTRING(列 FROM E'^\-*[0-9]+\.?[0-9]*$')                                  │
└──────────────────────────────────────┘
これならエラーを回避できる。
┌──────────────────────────────────────┐
│TO_NUMBER(SUBSTRING(列 FROM E'^\-*[0-9]+\.?[0-9]*$'),'S999D0')              │
└──────────────────────────────────────┘
文字列が混じっている場合は、NULLになる。
分類:PostgreSQL
定数の値
2011年09月25日
定数の値はたいてい「1,2,3…」とかだ。
┌─┬─┐
│ 1│男│
├─┼─┤
│ 2│女│
└─┴─┘
みたいな感じ。

ふと、数値じゃなくてもいいんじゃね?とか思い、「male、female」の頭文字をとって
┌─┬─┐
│m │男│
├─┼─┤
│f │女│
└─┴─┘
な~んて定義してみる。

同じじゃん。こっちの方が直感的でわかりやすいし。オレって天才。
なんて思っていると実は落とし穴に嵌っていることに後から気づく。

そう、ソート順のキーに指定した場合「女→男」の順なってしまうのだ。

定数の値は、並び順の番号と心得るべし。

#順番については男尊女卑ではありませんのであしからず
分類:SQL、注意、設計
SQL/INSERT文に一意制約をつける
2011年09月24日
一意属性(UNIQUE)をつけたいのにつけられない項目があるとする。
例えば、削除区分とかを使って削除レコードを履歴として残している場合の
実質的なキー項目とかの場合だ。
#削除レコードを除いて中では一意になる項目とかのこと

ま、とにかく事情があって一意属性はつけられないが
一意であって欲しい場合、INSERT時に制約をかけるとするなら
一旦SELECTで読み込んで存在を確認した上で
存在していない場合のみINSERTするとかいう処理になると思う。

これを一回のSQL文で実現させることができないものかと考えていたのだが
「相関副問い合わせ」ってやつを使えばできてしまうのだ。
┌──────────────────────────────────────┐
│INSERT INTO 出力表 (出力列)                                                 │
│    SELECT 入力列                                                           │
│        FROM 入力表                                                         │
│        WHERE 条件                                                          │
│          AND NOT EXISTS (SELECT *                                          │
│                              FROM 出力表                                   │
│                              WHERE 出力.出力列 = 入力表.入力列);           │
└──────────────────────────────────────┘

「副問い合わせ」までで挫折して「相関副問い合わせ」なんかとは縁がなかったが
こうやって使ってみると便利なものだ。(ってこの使い方が正しいのかはやや不安)

★この方法には問題があることがわかりました、後日加筆修正します
分類:SQL
SQL/呉越同舟?Ⅱ
2011年09月23日
以前、まったく違う列を結合したかのように取得する方法を取り上げた。
┌──────────────────────────────────────┐
│SELECT 表1.列11,                                                            │
│       表2.列21                                                             │
│  FROM 表1,                                                                 │
│       表2                                                                  │
│  WHERE 表1.列11 = '値'                                                     │
│    AND 表2.列21 = '値';                                                    │
└──────────────────────────────────────┘
上記のようにすれば、あたかも以下の結果を横に並べたようになるのである。
#但し、双方ともに一件ずつ該当し、結果が一件になるような場合が望ましい
┌──────────────────────────────────────┐
│SELECT 表1.列11                                                             │
│  FROM 表1                                                                  │
│  WHERE 表1.列11 = '値';                                                    │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│SELECT 表2.列21                                                             │
│  FROM 表2                                                                  │
│  WHERE 表2.列21 = '値';                                                    │
└──────────────────────────────────────┘

これに集合関数が絡んでくるとひと工夫必要なことがわかったので追記する。
┌──────────────────────────────────────┐
│SELECT 表1.列11                                                             │
│       MAX(表2.列21)                                                        │
│    FROM 表1,                                                               │
│         表2                                                                │
│    WHERE 表1.列11 = '値'                                                   │
│      AND 表2.列22 = '値'                                                   │
│    GROUP BY 表1.列11;                                                      │
└──────────────────────────────────────┘
当然ながら、結果一件なのだが「GROUP BY」がないと建て前として
集合関数との整合性がとれないので、これは(必須な場合は)必須みたいだ。
分類:SQL
HTML/テーブルタグのセンタリング
2011年09月22日
昔はCENTERタグってものがあって、以下のように囲えばOKだった。
┌──────────────────────────────────────┐
│<CENTER><TABLE>…</TABLE></CENTER>                                          │
└──────────────────────────────────────┘

でも、CENTERタグなんか使うなってことになって、以下のような感じになった。
#実はこの辺があやふや(なにせCENTERタグをバリバリ使ってしまっていたから)
┌──────────────────────────────────────┐
│<TABLE align="center">…</TABLE>                                            │
└──────────────────────────────────────┘

そんでもって、CSSってのになって以下のような形で現在に至っています。
#style属性じゃなくてstyleタグにまとめればなおいいけど、説明の便宜上こちらに
┌──────────────────────────────────────┐
│<table style="margin:auto;">…</table>                                      │
└──────────────────────────────────────┘

…ところが、IEがこれに対応していない。
ってことで、妥協案としてこんな感じになります。(ああ、ややこしい)
┌──────────────────────────────────────┐
│<div style="text-align:center;">                                            │
│<table style="margin:auto; text-align:left;">…</table>                     │
│</div>                                                                      │
└──────────────────────────────────────┘
分類:CSS、HTML
PHP/宣言していない変数の扱い
2011年09月21日
PHPの変数は宣言不要で、値を格納した時点で宣言して初期化されたような状態になる。
逆にいえば、値を格納していない変数は宣言されていないものとみなされる。

┌──────────────────────────────────────┐
│$変数 = '値';                                                               │
│echo $変数                                                                  │
└──────────────────────────────────────┘
上記はOKでも、下記はNGである(でもエラーではない)。
┌──────────────────────────────────────┐
│echo $変数                                                                  │
└──────────────────────────────────────┘

この場合、「Notice: Undefined variable: 変数 in 行番号」のような警告が出る。

「@」を使えば、警告は抑止されるので以下のようにすれば、事実上支障はなくなる。
┌──────────────────────────────────────┐
│echo @$変数                                                                 │
└──────────────────────────────────────┘

では以下のように代入した場合はどうなるのか?
┌──────────────────────────────────────┐
│$代入先 = @$変数;                                                           │
└──────────────────────────────────────┘

この場合は「NULL」が格納されているものとみなされ、代入先にも「NULL」が入る。

つまり以下のような処理の場合、条件に該当しなければ、
代入先に「NULL」が入ってくれるということになる。
┌──────────────────────────────────────┐
│if (条件) {                                                                 │
│  $変数 = '値';                                                             │
│}                                                                           │
│$代入先 = @$変数;                                                           │
└──────────────────────────────────────┘

なお、「is_null()」と「isset()」が正反対の関係、
つまり「is_null() = !isset()」の関係にあるのは
これを元に考えれば辻褄が合う。

つまり、setされていない変数はNULL扱いなのだ。
分類:PHP
PHP/一覧中のチェックボックスの処理
2011年09月20日
┌──────────────────────────────────────┐
│┌─┬────┬──────────────┬──────┬───┬────│
││№│  氏名  │            住所            │  電話番号  │ 区分 │        │
│├─┼────┼──────────────┼──────┼───┼────│
││ 1│武田信玄│                            │            │■源氏│        │
│├─┼────┼──────────────┼──────┼───┼────│
││ 2│上杉謙信│                            │            │□源氏│        │
│├─┼────┼──────────────┼──────┼───┼────│
││ 3│徳川家康│                            │            │■源氏│        │
│├─┼────┼──────────────┼──────┼───┼────│
└──────────────────────────────────────┘
上記のような、(複数)明細を入力する画面で、同一列の項目を入力させるには
以下のようにname属性に「[]」をつけて配列にしてあげればいい。
┌──────────────────────────────────┐
│<input type="text" name="氏名[]" value="値"/>                       │←1行目
│<input type="text" name="氏名[]" value="値"/>                       │←2行目
│<input type="text" name="氏名[]" value="値"/>                       │←3行目
└──────────────────────────────────┘
するとPOST後、以下のように配列で値を取得できる。
・$_POST['氏名'][0]  →1行目に入力された氏名  →武田信玄
・$_POST['氏名'][1]  →2行目に入力された氏名  →上杉謙信
・$_POST['氏名'][2]  →3行目に入力された氏名  →徳川家康

しかしこれがチェックボックスの場合は厄介なことになる。
┌──────────────────────────────────────┐
│<input type="checkbox" name="区分[]" value="TRUE" checked="checked"/>       │
│<input type="checkbox" name="区分[]" value="TRUE"/>                         │
│<input type="checkbox" name="区分[]" value="TRUE" checked="checked"/>       │
└──────────────────────────────────────┘
上記のように、テキスト同様定義してあげて、
チェックの有無により以下のように配列で取得できればよいのだが…
・$_POST['区分'][0]  →1行目はチェックあり  →TRUE
・$_POST['区分'][1]  →2行目はチェックなし  →FALSE
・$_POST['区分'][2]  →3行目はチェックあり  →TRUE

実際には以下のようにチェックなしは、その存在自体が無視されてしまう。
・$_POST['区分'][0]  →1行目はチェックあり  →TRUE
・$_POST['区分'][1]  →3行目はチェックあり  →TRUE
(結果的には「■□■」と入力したものが「■■-」と認識される感じだ)

これでは不都合なので、以下のように対処する。

まず、各行にキーとなるものを定義しておき、チェックボックスのvalue属性に設定。
┌──────────────────────────────────────┐
│<input type="checkbox" name="区分[]" value="キー1" checked="checked"/>      │
│<input type="checkbox" name="区分[]" value="キー2"/>                        │
│<input type="checkbox" name="区分[]" value="キー3" checked="checked"/>      │
└──────────────────────────────────────┘
ちなみにキーは以下のような感じで設定しておく。
┌──────────────────────────────────────┐
│<input type="hidden" name="キー[]" value="キー1"/>                          │
│<input type="hidden" name="キー[]" value="キー2"/>                          │
│<input type="hidden" name="キー[]" value="キー3"/>                          │
└──────────────────────────────────────┘

これらは、行ごとに一組になる感じだ。
┌──────────────────────────────────────┐
│<input type="hidden" name="キー[]" value="キー1"/>                          │
│<input type="checkbox" name="区分[]" value="キー1" checked="checked"/>      │
└──────────────────────────────────────┘

それで、以下のように判定すれば、
チェックありの場合はTRUE、チェックなしの場合はFALSEに判定することができる。
・in_array($_POST['キー'][0], $_POST['区分'])
・in_array($_POST['キー'][1], $_POST['区分'])
・in_array($_POST['キー'][2], $_POST['区分'])

注意:全ての明細がチェックボックスをはずしている場合には、
      「$_POST['区分']」自体が存在しないことになり
      「in_array()」が成立せずエラーとなってしまうので
      条件分岐などの考慮が必要です
      以下みたいな感じでしょうか
┌──────────────────────────────────────┐
│if (isset($_POST['区分'])) {                                                │
│  return in_array($_POST['キー'][0], $_POST['区分']);                       │
│} else {                                                                    │
│  return FALSE;                                                             │
│}                                                                           │
└──────────────────────────────────────┘

#わかりやすいように変数名を日本語にしていますが、実際は英語です
#POST送信を例にしています、GETでも同じです
分類:PHP
前へ 1 2 3 次へ