俺の開発大作戦

Linux, Mac, Windows10 で 迷走する1開発を進めていく備忘録5

JQuery の ajax で POST を非同期で送る

web ページからサーバにリクエスト情報を送る際に HTTP GET / POSTメソッドを使う機会は非常に多いが、通常この処理を行うと、サーバサイドで情報を受け取ってレスポンスを返すためのページを読み込むことを余儀なくされる。

一方、ページのリロードを伴わずに非同期でリクエストだけ送りたい場面も生じるが、この場合は、JQuery の ajaxメソッドで を使用すれば割と容易に実装ができてしまう。というわけで、さっそく手順を備忘録として記したい。

1. jQuery を読み込む

まずは基本中の基本から・・・。実装したいページ内で、<script> タグを使いオプションの src 属性で読みこませる JQuery の URI を指定する。

URI は予め本家から入手して自サーバ内に設置しておいた場所を指定する方法や、google のCDN(content delivery network : 配信用に最適化されたネットワーク)など外部にホストされている JQuery のアドレスを指定する方法がある。

'保管した場所から読み込み
<script src="/保管場所/jquery-ヴァージョン.min.js"></script>

'google の CDN から読み込み
<script src="//ajax.googleapis.com/ajax/libs/jquery/ヴァージョン/jquery.min.js"></script>" 

ヴァージョンは1.x系、2.x系、3.x系があり、それぞれサポートするブラウザの範囲が異なる。2.x系以降はIE9以降しかサポートしていないため、サービス対象にIE8以下が含まれている場合には、1.x系を選択する。

なお、CDN からの読み込みを選んだ場合、サービス障害等で読み込むことができない不足の事態に備え、代わりに自サーバに配置した jQuery を読み込むように以下のように記述しておくと良い。

<script src="//ajax.googleapis.com/ajax/libs/jquery/ヴァージョン/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/保管場所/jquery-ヴァージョン.min.js"><\/script>');</script>

また、読み込む場所は、ページの読み込みを優先したい場合は、冒頭の<head>~</head>タグ内ではなく、<body>〜</body>タグの最後に記述するのが今流だ。

2. POST フォーム の通常 submit を無効化

続いて form タグで普通にPOST のフォームを作り、その後通常の同期通信型 submit が行えないようにする。submit 無効化の方法については、javascript のsubmit イベントで、'return false'を使ったり、'preventDefault()'を使う方法があるが、当方環境では、これらの方法をとると、連続してsubmit した場合に2回目で無効化が解除されてしまっていて通常の submit による リロードが発生してしまう事態に何度か直面したため、別の方法をとることにしている。例えば、form タグの action属性 に 'javascript:void(0);' を指定して、戻り値をundefined(未定義)として submit を無効化する方法など。以下はその例。

<form action="javascript:void(0);">
 ・
 ・
 ・
</form>

あるいは submit ボタンの代わりに、aタグによる擬似ボタンを作るなど。但しこの場合も、'href' に 'javascript:void(0);' を指定してaタグ本来の動きを止める必要がある。

3. Jquery で onClick イベントを作成

通常の submit を無効化したら、いよいよ JQuery の ajaxメソッドで非同期通信の処理を onClick イベントで書いていく。テンプレート的な書き方は以下のとおり。

<form id="test" action="javascript:void(0);">
 ・
 ・
 ・
<input type="submit" />
</form>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
  $('input#test').click(function () {

    // 一括してフォームデータを取得
    var formData = $('#test').serialize();

    console.log(formData);
      $.ajax({
          url: "test.php",  //POST送信を行うファイル名を指定
          type: "POST",
          data: formData  //POST送信するデータを指定({ 'hoge': 'hoge' }のように連想配列で直接書いてもOK)
      });
  });
});
</script>

これでページのリロードを挟まずにPOST送信が非同期で行える。

4. POST 成功した後に、POSTした内容でページの一部を更新

3. で使用したajaxに「done」メソッドを付けると、POST送信が成功した場合に新たな処理を実行できる。また、「done」メソッドには、指定した引数にPOSTから渡されたデータを格納できる。

この「success」オプション内で、 '$(object).text()' や '$(object).text()', '$(object).load()' などの非同期型の JQueryメソッドを記述することで、POST した内容に応じながら一部ページの更新をリロードなしに実行できる。

以下は、$(object).text() を使用した例。

<form id="test" action="javascript:void(0);">
 ・
 ・
 ・
<input id="dummy" type="text" name="dummy" /> 
<input id="test" type="submit" />
</form>

<div id="sample">何か記入してください</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
  $('input#test').click(function () {

    // 一括してフォームデータを取得
    var formData = $('#test').serialize();

    console.log(formData);
      $.ajax({
          url: "test.php",  //POST送信を行うファイル名を指定
          type: "POST",
          data: formData  //POST送信するデータを指定({ 'hoge': 'hoge' }のように連想配列で直接書いてもOK)
      }).done(function(data) {
          $('div#sample').text(data2);
      });
  });
});
</script>

蛇足ながら、実際に動かしてみる場合の参考に 'test.php' の例も。

<?php
$dummy = $_POST['dummy'];
if (is_null($dummy)){
  echo "何か記入してください";
}elseif (trim($dummy)==""){
  echo "空白です";
}else {
  echo "あなたは、\"" . $dummy . "\"と書きました";
}
?>

LOCALHOST からクラウドの DB サーバに接続

さくらインターネットなど大手レンタルサーバ事業者は、およそ、ローカルのWeb開発環境から 直接DBサーバに接続できない仕様だ。むろん、安全対策上必要な仕様であるものの、localhost に設置した web サーバ上で web製作を進める場合には、少々不便を感じることがある。

一方、たいていのレンタルサーバ事業者は、ローカルからのssh通信は許可している。つまり、sshポートフォワーディングを利用すれば、localhost のwebサーバと、クラウドの DB サーバで通信が可能になる。

というわけで、さっそく設定を行った備忘録。

1. 鍵認証によるsshアクセスを行う設定

(*すでに設定済、あるいはIDパスワードのみによる認証でよければこの設定は不要。)
まずは、localhost 側で以下のコマンドを実行して鍵を作成。

% ssh-keygen -t rsa

ssh-keygen コマンドの -t オプションで、鍵のタイプを指定。タイプは、「RSA」方式と「DSA」方式のどちらかを選択可能。なお、「OpenSSH」の最新版では、より長い鍵長が選択できる「RSA」がデフォルトになっている模様。念の為、オプションを付けておく。

コマンドを打つと設定するパスワードのフレーズを聞かれるので入力する。(入力せずに Enter で進むとパスワードなしの設定となる。)その後、デフォルトの設定で、次のとおり localhost に鍵が作成される。

公開鍵:~/.ssh/id_rsa.pub
秘密鍵:~/.ssh/id_rsa

続いて、sshアクセスするクラウドサーバにアクセスして、サーバの ~/.ssh/authorized_keys に、公開鍵を登録する。.ssh フォルダやauthorized_keys がなければ作成する。この時、作成と一緒にパーミッションを 設定するのを忘れずに行う。

% ssh ユーザー名@サーバアドレス
% mkdir ~/.ssh
% touch ~/.ssh/authorized_keys
% chmod 700 ~/.ssh
% chmod 600 ~/.ssh/authorized_keys

あとは、authorized_keys に localhost 側に作成した id_rsa.pub の内容を追記すればよい。なお、sshアクセスから作成済の authorized_keys に公開鍵を追記するまでの作業を一貫して行いたい場合は、次のとおり。

% cat ~/.ssh/id_rsa.pub | ssh ユーザー名@サーバアドレス 'cat >> .ssh/authorized_keys'

2. ssh によるポートフォワーディング実行

本題のポートフォワーディングを以下のコマンドにて実行する。

% ssh -f -N -L 3307:リモート(クラウド上)のDBサーバアドレス:3306 ユーザー名@サーバアドレス;

-f オプションは ssh をバックグランドで接続するよう指示するもの。また、-N オプションはリモートコマンドを実行しないようにする。これらのオプションはポート転送のみをおこないたい接続の場合につけておくと便利。

-L オプションでは、ローカル側ソケットを指定する。ここで指定した localhost 上のTCP ポートまたはUnixソケットを、続いて指定するリモートホスト上のポートにフォワーディングできる。使用する場合は、'ローカル側ソケット:リモート側DBサーバアドレス:リモート側DBサーバ使用ポート'のように続けて指定する。

上の例では、ローカル側の3307ポートをリモート側DBサーバの3306ポートに転送している。これで、'localhost:3307'のようなアドレス指定で、ローカルのwebサーバからリモートのDBサーバにアクセスできるようになる。(後日追記:MySQLなどのUnixサーバ上では、ホストネームの localhost には特別な意味を持ち、TCP/IPではなくUnixソケットで接続されることが多く、このような場合にポート番号を指定しても無視されてしまう。このため、hosts などでlocalマシンのアドレス '127.0.0.1' に localhost 以外の適当な名前を登録して、'適当な名前:3307' のように指定して使用する方が無難である。)

なお、バックグランドで実行中のssh接続を止める場合は、次のとおり。

% pgrep -f 'ssh'
プロセス番号
% kill プロセス番号

(*)pgrep コマンドは、シンプルにプロセス番号(pid)のみを返り値とし、また、自身のコマンド分は表示しないなど、grepにオプションを沢山つけてを使う場合と比べて効率的で便利。以下のようにシンプルなワンライナーで kill処理まで指示を書くこともできる。

 % pgrep -f 'ssh' | xargs kill

UNIX の忘れがちなシェルコマンド備忘録

便利だが忘れがちなコマンド構文を備忘録として残していく第一弾。

1. 指定する文字列を含む文書を一括検索してフルパスで表示する

% find PATH -type f -print | xargs grep 'hoge' 2> /dev/null

PATH は検索を開始したい場所。hoge は検索したい文字列。

'xargs' コマンドは 'コマンドA | xargs コマンドB' のように2つのコマンドをパイプでつなぐことで前のコマンド(コマンドA)で取得した値(標準出力)を読み込み、それを引数としてコマンドBへ渡して実行させる役割を果たす。組み合わせや引数の組み合わせ次第では、コマンドが許容の長さを超える引数のリストを受け付けない問題を回避できたり、処理を並列化して高速化できる場合がある。

'find' コマンドは-typeオプションで、ファイルタイプを指定して検索できる。値を 'f' にすると通常ファイルを検索し、 'd' はディレクトリを、 'l' はシンボリックリンクを検索する。

また、 'find' コマンドに-printオプションをつけると、フルパスで検索結果を標準出力する。

コマンドに '2> /del/null' を付けると標準エラー出力を/dev/nullに捨てることができる。ブラウザのキャッシュなどが走査対象に含まれていて、'検索対象のファイルやディレクトリが見つからない'等のエラーが頻出する場合は、これらを表示しないようにできる。

2. ディレクトリ内にある全ての文書内の文字列Aを文字列Bに置き換える

% grep -l '文字列A' ./* | xargs sed -i.bak -e 's/文字列A/文字列B/g'

再び'xargs' コマンドを含む構文のコマンドで、「置換・削除」を行うための'sed' コマンドをパイプで繋ぐもの。

'sed' コマンドは-iオプションをつけると、変換処理後にファイルを上書き保存できる。更にこのオプションに文字列を続けると、元ファイルをこの文字列を接尾語としたファイルに別名保存して残しておくことができる。なお、文字列を続ける場合は、-iとの間にスペースを挟んではいけない。

'sed' コマンドの-eオプションをつけると、続けて指定する条件式に従って変換処理を行うことができる。このコマンドには、ほかに-fオプションも用意されていて、変換処理を行うための条件式が記述されたファイルの保存場所をPATH指定して、このファイルの内容に基づいて変換処理を進めることもできる。

'sed -e' で全文を一括置換する場合の構文は、's/文字列A/文字列B/g'。ほかにもsに繋げる構文の組み合わせでケースに応じた色々な置換ができる。

% sed -e "s/文字列A/文字列B/"       # 置換 行で最初に出てきた'文字列A'を'文字列B'に置換
% sed -e "s/^文字列A/文字列B/"      # 行頭(^)の'文字列A'を'文字列B'に置換
% sed -e "s/文字列A\$/文字列B/"     # 行末($)の'文字列A'を'文字列B'に置換($は\でescape)
% sed -e "s/~/文字列B/"          # 行頭に'文字列B'を追加
% sed -e "s/\$/文字列B/"         # 行末に'文字列B'を追加
% sed -e "s/.*/文字列C/"         # すべての行を'文字列C'に置換

* * *

Web制作等で複数ファイルに跨る変数やディレクトリ構造そのものを変える必要がある時に、変更漏れのファイルが無いか気になるところ。むしろ、そのような効率の悪い作業が発生しないように、編集効率の良いファイル構成を組みたいところだけど、作業中は仕様変更が頻繁に起こってそうもいかないことも少なからずある。

そんな時に、未編集ファイルの一括検出や置換が効率良くできるこれらコマンドは、非常に便利で重宝している。

俺: 医療系事業会社のITサービス開発担当者

▼プロフィール畳む

▶プロフィール見る

ネットが産声をあげた前世紀末に元国営の通信会社に新卒入社し、以降およそ10年間勤務して、インターネット系の新規事業立ち上げに複数携わる。

その後、退職して、ITベンチャーのスタートアップ参画を皮切りに、複数のIT企業でプロダクトマネージャーを務めた後、縁あって現在の医療系事業会社へjoin。

元来、エンジニアばかりの環境で過ごしてきたが、いまいるここは一般の非IT系事業会社。

自分以外に実際に手を動かせるスタッフは誰もいない環境やさかい、IT系プロダクトの企画から内製によるシステム開発、ビッグデータ分析や人工知能のビジネス転化への試行錯誤も仕方なく一人でマルチに行い奮闘中。
(そろそろ仲間が欲しい・・・)

E-mail: contact@kobachan.biz

カテゴリー
月別アーカイブ
  • 2018 (4)
  • 2017 (6)