FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

フォームの完全resetにはリロードを

relodad.png
ごくカンタンなサンプル検索フォームだが、わざわざ"リロード"というボタンを追加しているのには理由がある。

relodad2.png
品番を入力すると該当商品のタイトルを表示するだけという機能なのだが、ここでのお題は reset が効かない事への対策。
"入力クリア"ボタンには、入力項目をすべて空値にするための <input type="reset" value="入力クリア">で、type="reset" を設定しているが、一度でも検索を実行するとその後は空値にならない、すなわち入力された項目値が表示されたままになる。つまり、

再読込(リロード)が発生すると reset が無効になる !

何でや !? ((´゙゚'ω゚')) ※検索を実行するまでは正常動作する
さんざん悩んで調べた結果、reset はページが読み込まれた直後の状態に戻す機能なのだからこれが当たり前となる。( ´・ω・`)
reset とは、入力項目を空値にするのではなく、初期状態に戻すという機能 なのだった。たしかに名前の通りの機能。
PHPでPOST送信を実行した場合は、その結果がサーバーから返されるので、フォームの入力項目には検索結果が表示された状態でページが生成されている。そのため、reset が効いていないように見えるのだ。

そんなわけで、サンプルフォームでは一度でも検索を実行してしまうと二度と"入力クリア"ボタンが機能しないのは正常といえる。
どうしても完全に初期状態にしたいには、ページの強制リロードしかない。
そんなわけで、検索ページのファイル名を pathinfo(__FILE__, PATHINFO_BASENAME) で取得して、"リロード"ボタンの onclick イベントで読み込むURLとしてセットしてやればOKとなる。(´∀`)

<?php
$商品名="";$商品番号="";
$ファイル名=pathinfo(__FILE__, PATHINFO_BASENAME); // ファイル名の取得
if(isset($_POST["商品番号"])){
$DBHOST="mysql:host=localhost;dbname=sakila;charset=UTF8";
$DB=new PDO($DBHOST,"access","pass1234");
$SQL="Select * from film_list Where FID =".$_POST["商品番号"];
$DATA=$DB->query($SQL);
$ROW = $DATA->fetch(PDO::FETCH_ASSOC); // 先頭行の取得
$商品名=$ROW["タイトル"];$商品番号=$ROW["FID"];
}
?>

<h1>商品検索サンプル</h1>
<form method="POST" action= <?=$ファイル名?>>
商品番号 : <input name="商品番号" value=<?=$商品番号?>>
<input type="submit" value='検索'>
タイトル : <input type="text" value='<?=$商品名?>'>
<input type="reset" value="入力クリア"><br>
<input type="button" value="リロード"
onclick="location.href='<?=$ファイル名?>'">
</form>
スポンサーサイト

Windows7のワナ - リンクテーブルが開けない

閉鎖予定の前シリーズをチェックしてみたら、以外に人気のある記事があったので原文のまま転載しておく。
業務の都合上、Windows7+Xpモードという環境で開発せざるを得なかった頃のものなので、今更誰の役にも立たないかもしれないが、驚くべき事に現時点で56もの拍手がついているので、このまま消え去る運命というのももったいないかなと・・・(*´・ω・)


今回はMySQLとは無関係のお話。
重い腰を上げて、2011年2月から、OSを XpPro から Windows7 Pro にした。
と言っても、更新したわけではなく新OS付きのPCを購入しただけである。

そして、2ヶ月経ってようやく 7の操作にも慣れて来たところで、ついに出た互換性問題。(*`Д´*)
Accessのみで構成した社内システムで、リンクテーブル自動更新機能を持たせたアプリが複数あり、そのひとつで障害が発生したのである。
Xp環境で問題なく動作していた機能が突然正常動作しなくなり、原因究明に半日費やす事になった。
リンク更新機能には、訳あって "On Error Resume Next" 文を書いていたため、余計に気づくのが遅くなったという事情もある。
現象としては
全角文字を使用したテーブル名があるとリンク更新出来ない
というものである。半角文字だけのテーブルは正常にリンク更新されている。しかし、すべてのAccessデータベースではなく、Access97以前の形式の mdbでのみ発生する事を突き止めた。
・・・とエラそうに書くほどの事でもないのだが。
問題のリンク先mdbを開こうとすると、エラーメッセージが出て開く事すら出来ないのである。

権限がありません

他社のシステムとのやり取りの都合上、97形式とはしばらく縁が切れそうにないため、MicroSoft の推奨対策もしてみたが、別の問題が発生してしまって使えない状態。
引数が不正

しかし、開発環境で作成した実行ファイル(*.accde)をXpマシンで動かすと、何事もなかった如く正常に動作するのである。文字コードの微妙な仕様の差異から生じる障害なのかもしれないが、迷惑な体験であった。

Xp互換モードで障害発生のつづき。
"エラーメッセージで止まる" ・・・ だけではあまりに能がなさすぎと反省し、原因を探ってみた。
エラートラップ処理を停止して動作させると、エラー発生箇所は、

リンクファイル名 = Left(リスト, InStr(リスト, ".mdb") - 1)

の部分であった。リストボックスにmdbファイルのリストを表示し、選択されたファイル名でリンクテーブルを更新するようになっている部分である。どうも Instr関数がまともな値を返さないようだと判って調べてみたら、やはりあった。しかも・・・(`・ω・´)

Windows Vista および Windows 7 で Access 97 ファイル形式のデータベースを Access 2007 または Access 2010 ファイル形式に変換できないことがある

だと。Instr関数以前に、テーブルリンク処理自体を失敗するという不具合であり、なかなか究明できなかった。(*`Д´*)
どうも、このバグは修正されてないようである。しかし、これだけのためにコードを修正など出来ない。
こうなると、残るは VertualPC のXp Mode か。しかし、ドライブ番号固定のアプリが多数を占めるし、考えただけでメンドくさい。
そこで、対策。97形式mdb関連で互換性問題が発生するアプリは、Xpマシンで開発する。これで完全解決。とはいえ、おそらく他の誰の役にも立たない体験であった。(^^;)

しかし、良く調べもせずに"文字コード仕様の違い"などと勝手に断定した間抜けさを忘れないため、前回の記事はそのまま残すことにした。

唯一の収穫は、Xp互換モードなら、97形式のmdbを問題なく開く事が出来るのが判った事くらい・・・

※補足としてこの記事についたコメントも紹介しておこう。

あるシステムのあるバックアップファイル。これがMDB形式で、中にテーブルが詰まっている。そこでこの中のデータを取り出そうと、Win7 64bit / Access2007 and Access2010でやってみたところ。同じ問題に遭遇。

Access.exeの互換性チェックで「管理者としてこのプログラムを実行する」にチェック
その後
ローカルセキュリティポリシー ⇒ ローカルセキュリティ ⇒ セキュリティオプションを開く
その後
ユーザアカウント制御:管理者承認モードですべての管理者を実行するを選択し、右クリック->プロパティ
現在の設定が「無効」になっていると思われるので、これを「有効」にし、OKを押してマシンを再起動。

これでできるようにはなりました。どうやらACC97のMDBをACC2007に変換するプログラムがUACによって封じられている為、管理者権限を与えてあげないと変換できず、結果読み込めないということになるようで。

Access / VBAによるオートナンバー型のリセット

たまには Access のお話。
MySQLのAUTO_INCREMENTと同様の機能である、Access のテーブルのオートナンバー型フィールド。
両者の機能は同じだが、Accessでの作業用テーブルなどの一時的利用用途としては連番のリセットが面倒だった。
しかし、VBAで容易に可能なのだと最近になって分かったのでメモとして。( ´ー`)

  • VBAでのSQL操作の方法
  • SQLコマンドでフィールドの Counter というプロパティを変更するだけなのだった。
      SQL = "Alter Table テーブル名  Alter Column フィールド名 Counter(1,1)"
    CurrentDb.Execute SQL
    とすればOK。実にカンタンではないか。※ここの記事を参考にさせてもらいました
    これまでネット上のほとんどの情報ではフィールドの削除と復旧ばかりだった。
    ただし、SQLコマンド実行前にテーブルの全レコード削除の後でクローズしておく事が前提なので、このような処理を多用する場合にはユーザー定義関数を作成する事が必要。
    • 汎用的な関数化とするとこんな感じ
    • Function オートナンバー型初期化(テーブル As String, フィールド As String, Optional 初期値 = 1) As Boolean
      On Error GoTo エラー
      DoCmd.Close acTable, テーブル
      SQL = "Delete from " & テーブル
      CurrentDb.Execute SQL
      SQL = "Alter Table " & テーブル & " Alter Column " & フィールド & " Counter(" & 初期値 & ",1)"
      CurrentDb.Execute SQL
      オートナンバー型初期化 = True
      Exit Function
      エラー:
      MsgBox Error, vbCritical, Format(Err, "エラー番号 0")
      End Function
      Counterプロパティの第一引数が初期値となるので、任意の数値から開始するにはここを変更すれば良い。

      こちらも参考になる。
      オートナンバー型フィールドが上限値を超えた場合はどうなる?

Access ユーザーのためのWeb アプリ開発まとめ - データ送受信

$_POST 変数による、データ送受信。

修行を開始した当初の「フォームの入力と結果表示」について手さぐりで悪銭苦闘していた時期。
ちょっと古い参考書から始めて、そこにはPHPしかなったため当初はこの方法しか知らなかったのだが・・・一応まとめておく。

検索処理まとめ01
ヒィヒィ嘆きながら何とかMySQLのデータを取得する方法が分かり、いそいそと簡単な検索処理に挑んでみた。

もう捨ててしまったが、最初に書いたPHPファイルはこんな感じ。
<?php
$商品名="";
if(isset($_POST["商品番号"])){
$DBHOST="mysql:host=localhost;dbname=sakila;charset=UTF8";
$DB=new PDO($DBHOST,"access","pass1234");
$SQL="Select * from film_list Where FID =".$_POST["商品番号"];
$DATA=$DB->query($SQL);
$ROW = $DATA->fetch(PDO::FETCH_ASSOC);
$商品名=$ROW["タイトル"];
}
Print "<h1>商品検索</h1>";
Print "<form method='POST'>";
Print "商品番号 : <input name='商品番号'>";
Print "<input type='submit' value='検索'>";
Print "商品名 : <input type='text' value=".$商品名.">";
Print "</form>";

?>
たったこれだけのスクリプトにさんざん試行錯誤しながら、しかし、無事にデータが表示された時には感動だった。(´∀`)

検索処理まとめ02しかし・・・数秒後には嘆息。「入力した商品番号」が消えてる・・・こんなのアカン !! (´д`)
しばし悩んで気がついた。POST送信すると全部再描画となるのだから、検索結果だけではなく、入力した値もすべてPOSt変数として処理しなければならないという事か !! ( ;´・ω・`)

検索処理まとめ03
またまた試行錯誤しつつ、何とか目的が達成出来た。
<?php
$商品名="";$商品番号="";
if(isset($_POST["商品番号"])){
$DBHOST="mysql:host=localhost;dbname=sakila;charset=UTF8";
$DB=new PDO($DBHOST,"access","pass1234");
$SQL="Select * from film_list Where FID =".$_POST["商品番号"];
$DATA=$DB->query($SQL);
$ROW = $DATA->fetch(PDO::FETCH_ASSOC);
$商品名=$ROW["タイトル"];$商品番号=$ROW["FID"];
}

Print "<h1>商品検索</h1>";
Print "<form method='POST'>";
Print "商品番号 : <input name='商品番号' value=".$商品番号.">";
Print "<input type='submit' value='検索'>";
Print "商品名 : <input type='text' value=".$商品名.">";
Print "</form>";

?>
赤文字が追加した処理だが、入力綱目や表示項目が増えるとかなり面倒くさくなりそう・・・( ;´・ω・`)
が、しかし更に問題が !
別の商品番号をテストしようと、キーボードの[F5(更新)キー]を押してもテキストボックスがクリアされない !!
こんなの参考書にも書かれてないし、何とか見つけたネットの情報で Firefox 特有の問題と判明した。
たしかに、クロームなど他のブラウザでは問題なくクリアされるのだった。
しかし、欠陥ではなくて、これはこれで親切な仕様という場合もありそうだ・・・Firefox 捨てたくないし、どうする ??( ;´・ω・`)

ネット情報でかなり面倒くさい方法がいくつか紹介されていたが、どれも一長一短で確実にクリアされる方法は見つけられなかった。
ctrl + F5 キーというのは有効そうだが、現在の最新版(たしか58以降くらい)では効かないのだった。※ESR版では効果があった
そうだ、手を抜いてフォームの Action に何も書いてなかったではないか !! と、気がついた。
$ファイル名=pathinfo(__FILE__, PATHINFO_BASENAME);
Print "<h1>商品検索</h1>";
Print "<form method='POST' action=".$ファイル名." >";
Print "商品番号 : <input name='商品番号' value=".$商品番号.">";
Print "<input type='submit' value='検索'>";
Print "商品名 : <input type='text' value=".$商品名.">";
Print "</form>";
PHPの完全ファイル名は __FILE__ プロパティ、じゃなかった定数で取得出来るので、pathinfo 関数と組み合わせてやれば、実行中のファイル名を取得出来る事も覚えた。
・・・が、きっちりコードを書いても効果はなかった・・・残るはRESETか・・・( ;´・ω・`)
Print "<input type='reset' value='クリア'>";
とりあえず"クリア"ボタンを置いてリセットとする事にしてから・・・って、何とこれまた効果なし !! (;´Д`)

Fifefox で完全リロードする

あきらめて他のあれこれに取り組みつつ、ある日ふとしたはずみで解決方法を発見した。何と、コードに自身のURLをきちんと書いてやるだけで良かったのだ !!
ただし、フォームとPOSTではなくボタンのクリックイベントで。
Print "<input type='button' value='リロード' 
onclick='location.href="."\"".$ファイル名."\""."'>";
何度もエラーに悩まされながら、慎重にエスケープ文字で変数を組み立ててと。
検索処理まとめ04ゾンビのような入力文字がようやく消えてくれた。
javaScript で自在に要素をコントロール出来る事を知るまでは、こんなつまらない苦労が耐えなかった・・・
まとめになってないが、今回はここまで。( ;´・ω・`)

Access ユーザーのためのWeb アプリ開発まとめ - データベース処理

これまでに分かった事のまとめ。
Webアプリ開発には基本的なHTMLとCSSタグ以外に最低でも MySQL・PHP・JavaScript の三種のソフトウエアのコマンドや関数の理解と使い分けが必要なためいったん整理する事にした。
不特定多数ユーザー対象ではなくあくまで小規模企業の社内システム前提につき緻密なエラー処理は省略しているし、日本語の変数名や関数名も遠慮なく使用している。
PHPとJavaScriptの文法やコマンドは共通している部分も少なくないので、その場合は説明文の末尾に [JS] と記述。

MySQLデータベースへの接続

[PHP]
$DBHOST="mysql:host=localhost;dbname=sakila;charset=UTF8";
$DB=new PDO($DBHOST,"access","pass1234");
  • 赤色部分はデータベース運用内容に応じて変更※$DBHOST$DBという変数名は任意
  • 別サーバーのDBを指定する場合はそのIPアドレスを書く(引用符は不要 ex: host=192.168.0.50)
  • ページ内での同一データベースの使用であれば接続処理は一度だけで良い

SQL実行

[PHP]※二重スラッシュはPHPやJavaScriptでのコメント文
$SQL = "Select * from film_list Where FID=100 Order by FID ";
$DATA=$DB->query($SQL); // クエリの実行
$件数 = $DATA->rowcount(); // 結果行数の取得
$ROW = $DATA->fetch(PDO::FETCH_ASSOC); // 先頭行の取得
  • SQL文は単なるサンプル
  • オブジェクト変数のプロパティやメソッドは、VBAのようなドットではなく"->"で結ぶ
  • クエリの結果行数をカウントする場合は rowcount() 関数を使用。該当データがなければ値は 0 になる
  • 1行目の取得だけで良い場合は fetch() 関数を使用
  • Select 文以外のSQLでは3行目以降は不要

結果による条件分岐

[PHP][JS]
if($件数 == 0){ exit; }
  • データが存在しなかった場合の処理※実際にはメッセージ表示等の注意喚起が必要だがここでは省略
  • if 文の条件判定部分は必ず ( ) で囲む事
  • 実行部分は中カッコで囲むがこの例のように単純な1コマンドだけの場合は省略可
  • 値の比較は等号(イコール)記号を二重にしないと動作しない※等号記号1個でもエラーは発生しないので注意が必要
  • スクリプトを中断して以降のスクリプトを実行させない場合は exit; とする
  • 変数名は必ず $ で始まる語句とする[PHPのみ]
  • スクリプトコードの末尾には必ずセミコロンが必要

データ(カラム値)の取得

[PHP]
$ROW["カラム名"]  // ex:$ROW["タイトル"]

複数カラム値の連結

[PHP]
Print "タイトル =".$ROW["FID"].":".$ROW["タイトル"];
  • 出力結果は タイトル =1:ACADEMY DINOSAUR
  • 値の連結にはドットを使う

ループ処理

[PHP]
Foreach ($DATA as $ROW){
Print文による出力など
:
:
}

ユーザー定義関数の作成

[PHP]ではすべて function であり、Access VBAのような Subプロシージャは存在しない[JS]
function 削除実行($RECID){
global $DB;
$SQL="Delete from テーブル名 Where RECID =".$RECID;
$DB->query($SQL);
}
  • function 関数名(引数) とし、{ } (中カッコ)内に処理を書く{JS}
  • 呼び出し側の変数を参照する場合は関数側で global としなければ未定義エラーとなる
  • Where 条件のカラム名と変数名は単なるサンプル

関数の利用方法

[PHP][JS]
関数名($引数名);
ex.
削除実行(155);   // または
$REC=155;
削除実行($REC); // とする
  • 関数本体にも引数にも文字列型や数値型といった型指定はない
  • 処理内容によっては引数なしも可
  • 関数内で既定値を定義しておけば、呼び出し側での引数省略が可能
    function TEST($A=50){
    Print $A;
    }
    TEST();
    ブラウザに読み込むと 50 と表示される。
    JavaScript では変数名と出力コマンドが異なるので注意
    <script>
    function TEST2(A=550){
    document.write(A);
    }
    TEST2();
    </script>

    外部ファイルによるデータベース処理

    [PHP]
    • 本記事冒頭のDB接続部分を専用のPHPファイルに記述しておけば、include 文で外部参照とするだけで接続が完了する
    • 呼び出し側のコード
    • include("DB_LIST_SHOUHIN.php");
    • include文はDB接続を使用するスクリプトコードよりも前になければならない
    • include を実行すると、そのファイルに記述されているすべてのスクリプトを読み込んで実行するため、文字出力するようなコードをユーザー定義関数以外の場所に書いてはならない
    • ユーザー定義関数も、同一ページ内で記述したのとまったく同様に利用可能となる
    • よほどの小規模アプリでなければ、当然この形態が基本となる
    • 複数のデータベースを使い分ける場合は接続処理も関数化する必要があるだろう

    PHPからJavaScript 関数への引き数渡しにおける注意点

    [PHP]
    $ROW関数による文字列変数渡しを行うには この記事 を参照。
アクセス数
カレンダー
08 | 2018/09 | 10
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
最新記事
カテゴリ
PHP (5)
最新コメント
月別アーカイブ
全記事表示リンク

全ての記事を表示する

リンク
検索フォーム
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。