[翻訳]Web 開発入門:Part 7 データを編集するページを作成する(20110218)
翻訳シリーズ Part 7 です。
今回はデータベースのレコードに対して更新をかける方法を紹介します。
元ネタはこちらです。
Web Development 101- Part 7, Creating an Edit Data Page
なお、このシリーズの翻訳の目次はこちらです。
WebMatrix を使ったWeb開発入門の翻訳始めます!(20110204)
Web 開発入門:Part 7 データを編集するページを作成する
これまで映画の一覧ページを作成して、スタイルを追加し、データベースと連携、そして、データベースに映画を追加する機能を追加しました。次は前回の新規データを追加するフォームと非常に似たフォームを作成します。そこでは既存の映画の一覧の内容を編集できるようにします。
現状のアプリケーションを見てみましょう。
映画の一覧ページの下部に新しい映画を追加する機能を追加しました。マウスオーバーの効果を付けるために、それぞれの映画のアイテムを <a> タグを使用してハイパーリンクにしました。このハイパーリンクを使用して映画の情報を編集できる機能を追加していきたいと思います。それでは始めていきましょう。
編集ページを作成する
まず、WebMatrix を使って “EditMovie.cshtml” という新規の CSHTML ファイルを作成します。このページは選択した映画の情報をあらかじめテキストボックスに表示するようなフォームで、それを元に編集を行ってデータベースの内容を更新する処理をします。
まずは、”EditMovie.cshtml” で初期表示されているコードを削除し、前のパートで作成したものとよく似たフォームを作成します。
<h1>Edit a Movie</h1>
<form action="" method="post">
<p>Name:<input type="text" name="formName" /></p>
<p>Genre:<input type="text" name="formGenre" /></p>
<p>Year:<input type="text" name="formYear" /></p>
<p><input type="submit" value="Edit Movie" /></p>
</form>
編集画面を映画一覧から呼び出す
編集フォームの骨組みは既にできていますが、選択した映画の情報をどのように初期表示すればよいのでしょうか?まずは、どの映画を編集したいのかという事を編集ページに伝えなければいけません。そのためには、”dataMovie.cshtml” にいったん戻ります。
次のようなコードでアイテムを書き出していたのを思い出したでしょうか?
<li><a href="#">@row.Name, @row.Genre, @row.ReleaseYear</a></li>
このハイパーリンクは href 属性の値が “#” になっているので、どこにも遷移しません。このハイパーリンクを “EditMovie.cshtml” に遷移するように次のように変更します。
<li><a href="EditMovie.cshtml ">@row.Name, @row.Genre, @row.ReleaseYear</a></li>
これは一見よさそうですが、その映画を選択してもただ単に “EditMovie.cshtml” を呼び出すだけで、実際にどの映画の情報を編集しようとしているのかわからないままです。しかし、dataMovies.cshtml はどの映画を選択したのかを識別できるので、これを使って編集したい映画の ID を次のようなリンクを使って “EditMovie.cshtml” に渡すことができます。
EditMovie.cshtml?id=<何か>
加えて、データベースから取得したID を抽出する方法 (@row.id) を知っているので、Razor 記法を使って ID を書き出すことができます。<li> タグの中身を次のように書き換えてください。:
<li><a href="EditMovie.cshtml?id=@row.id">@row.Name, @row.Genre, @row.ReleaseYear</a></li>
“dataMovies.cshtml” を実行すると次のように表示されます。:
見た目は全く変わっていないですが、HTML のコードを見てみると違いに気づくかと思います。ここでいう HTML のコードは WebMatrix 上で .cshtml ファイルを見るのではなく、.cshtml に基づいてサーバーで生成され、ブラウザに送信された HTML を指しています。
Internet Explorer 9 では、画面上を右クリックして [ソースを表示] をクリックすると生成された HTML のソースを確認することができます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Favorite Movies</title>
<link rel="stylesheet" type="text/css" href="movies.css" />
</head>
<body>
<header>
<h1>A list of my Favorite Movies</h1>
</header>
<div id="movieslist">
<ol>
<li><a href="EditMovie.cshtml?id=1">It's a wonderful life, Comedy, 1946</a></li>
<li><a href="EditMovie.cshtml?id=2">Lord of the Rings, Drama, 2001</a></li>
<li><a href="EditMovie.cshtml?id=3">The Fourth World, Anime, 2012</a></li>
<li><a href="EditMovie.cshtml?id=4">The Lion King, Family, 1994</a></li>
<li><a href="EditMovie.cshtml?id=5">Forrest Gump, Comedy, 1994</a></li>
<li><a href="EditMovie.cshtml?id=6">The Million Year Journey, Anime, 2014</a></li>
</ol>
<a href="AddMovie.cshtml">Add a new movie</a>
</div>
<footer>
This site was built using Microsoft WebMatrix.
<a href="https://web.ms/webmatrix">Download it now.</a>
</footer>
</body>
</html>
HTML が生成された際に、個々のデータの ID が<a> タグの href 属性に設定された URL に書き出されているのがわかったでしょうか?”EditMovie.cshtml” がロードされた時に、このID を使って編集したい映画のレコードを特定することができるようになりました。
編集ページを完成させる
それでは “EditMovie.cshtml” に戻りましょう。
以前に “@{” で始まるブレースをページの一番最初に記述すると、ページが読み込まれた際にそのコードが実行されるというのを覚えているでしょうか?ここで URL から ID を読み取って映画のタイトルやジャンル、公開日を見つけ出す処理を記述したいと思います。
このように URL にパラメーターを付けた形でページを呼び出した場合、Request オブジェクトからこの値を取り出すことができます。たとえば、EditMovie.cshtml?id=6 というURLで呼び出した場合は下記のような形で値を取り出します。
var id=Request["id"];
このコードは id というローカル変数を作成し、パラメーターから取得した値 (こちらも id という名前です) で初期化しています。WebMatrix では両方の id という変数が異なる物であることを、コードの状況から判断しています。
これで “id” を入手できたので、SQLコマンドの “SELECT” コマンドを利用して取得したい映画のレコードを取得できます。
var id=Request["id"];
var SQLSELECT = "SELECT * FROM Favorites where ID=@0";
var db = Database.Open("Movies");
var Movie = db.QuerySingle(SQLSELECT,id);
var MovieName=Movie.Name;
var MovieGenre=Movie.Genre;
var MovieYear=Movie.ReleaseYear;
データベースに対して ”Favorites テーブルから渡されたID と同じ ID を持つレコードの全項目を渡す” という内容のSQL コマンドを作成し、データベースに対して実行しています。ここでは一つのレコードのみを取得するため、db.QuerySingle というメソッドを使用しています。
SQL コマンドが実行されると、Name、Genre、ReleaseYear が取得されローカル変数に格納されます。
これで実行自体は大丈夫ですが、次はこの変数の扱いを定義しなければなりません。まだフォームの各テキストボックスには何も表示されていないので、ユーザーはデータを編集することができません。どうしたらよいでしょうか?答えは簡単です。このコードが実行されている時点ではまだ HTML のコードは書き出されていません。そのため、フォームの中のテキストボックスにデータベースから取得した値を設定することができるのです。フォームの内部では <input> タグを使用してテキストボックスを表示しています。<input> タグでは “value” という属性を使用して初期値を設定することができます。
これが “EditMovie.cshtml” の初期値を設定した際のコードです。
@{
var id=Request["id"];
var SQLSELECT = "SELECT * FROM Favorites where ID=@0";
var db = Database.Open("Movies");
var Movie = db.QuerySingle(SQLSELECT,id);
var MovieName=Movie.Name;
var MovieGenre=Movie.Genre;
var MovieYear=Movie.ReleaseYear;
}
<h1>Edit a Movie</h1>
<form action="" method="post">
<p>Name:<input type="text" name="formName" value="@MovieName" /></p>
<p>Genre:<input type="text" name="formGenre" value="@MovieGenre" /></p>
<p>Year:<input type="text" name="formYear" value="@MovieYear" /></p>
<p><input type="submit" value="Edit Movie" /></p>
</form>
このページを実行すると映画の情報が初期化された状態で表示されるはずです。ただし、URL のパラメーターをセットするために、”dataMovies.cshtml” を表示してから試してみましょう。
一覧の中から編集したい映画を選びます。上記のスクリーンショットの通りここでは “The Fourth World” をクリックし、「id は 3」という情報を付加して “EditMovie.cshtml” を呼び出します。
次のような画面が表示されます。
ここでテキスト ボックスの中の値を変更して “Edit Movie” ボタンを押しても何も起こりません。前のパートの “Add Movie” のページを思い出してください。ボタンが押されると HTTP POST 形式 (先ほどのハイパーリンクを使ってページを呼び出した場合の HTTP GET とは反対です)でフォームが送信されます。これを処理する必要があります。
以前にもやったとおり、if(IsPost) のコードブロックを使用して同じような処理をします。
if(IsPost){
MovieName=Request["formName"];
MovieGenre=Request["formGenre"];
MovieYear=Request["formYear"];
}
このフォームでは Name、Genre、ReleaseYear のそれぞれの値に対してformName、formGenre、formYear (ここでは値がフォームから取得するという意味で接頭字としてformという文字列を付加しています。) という変数名使用しています。これらは Request オブジェクトを経由して渡されます。もし、ユーザーがフォーム上で値を編集した場合、新しい値が上記の方法で渡され、それを使ってデータベースを更新することができます。
データベースを更新するには SQL コマンドの “UPDATE” コマンドを使用します。
UPDATE table SET column=value, column=value, column=value... WHERE key=value
この場合は既に分かっている ID を元に3つの列の値を更新します。これがその際に使用するコードです。
var SQLUPDATE = "UPDATE Favorites Set Name=@0, Genre=@1, ReleaseYear=@2 WHERE id=@3";
db.Execute(SQLUPDATE, MovieName, MovieGenre, MovieYear,id);
ここでは SQL コマンドがわかりやすく、かつ安全に実行できるように SQL のパラメーター (@0,@1 など。Razor 記法の “@” と間違えないようにしてください) を使用します。@ のついた数字が db.Execute() のコードの中で置き換えられることを思い出してください。つまりこの場合は @0 は MovieName に、@1 は MovieGenre に置き換えられます。
最終的に、映画の情報が更新されれば、更新された内容を確認するために映画の一覧のページに戻るのが良いでしょう。これは映画の情報を追加した場合と同じです。これがそのコードになります。
Response.Redirect("dataMovies.cshtml");
これが最終的な “EditMovie.cshtml” の完全なコードです。
Response.Redirect("dataMovies.cshtml");
これが最終的な "EditMovie.cshtml" の完全なコードです。
@{
var id=Request["id"];
var SQLSELECT = "SELECT * FROM Favorites where ID=@0";
var db = Database.Open("Movies");
var Movie = db.QuerySingle(SQLSELECT,id);
var MovieName=Movie.Name;
var MovieGenre=Movie.Genre;
var MovieYear=Movie.ReleaseYear;
if(IsPost){
MovieName=Request["formName"];
MovieGenre=Request["formGenre"];
MovieYear=Request["formYear"];
var SQLUPDATE = "UPDATE Favorites Set Name=@0, Genre=@1, ReleaseYear=@2 WHERE id=@3";
db.Execute(SQLUPDATE, MovieName, MovieGenre, MovieYear,id);
Response.Redirect("dataMovies.cshtml");
}
}
<h1>Edit a Movie</h1>
<form action="" method="post">
<p>Name:<input type="text" name="formName" value="@MovieName" /></p>
<p>Genre:<input type="text" name="formGenre" value="@MovieGenre" /></p>
<p>Year:<input type="text" name="formYear" value="@MovieYear" /></p>
<p><input type="submit" value="Edit Movie" /></p>
</form>
それでは、これを実行したらどうなるのか試してみましょう。ここでは “dataMovies.cshtml” を実行して、ある映画を選択した所です。先ほどと同じ “The Fourth World” を選択した場合、このような画面が表示されているかと思います。
Year の部分の値を 2012 から 2011に変更して、“Edit Movie” ボタンを押したとします。データベースが更新され、一覧のページにリダイレクトされ、Release Year が 2011 になっているのが確認できるかと思います。
これでデータベースのレコードがうまく書き換わったのが確認できました。
まとめ
データベースのデータを使用する Web サイトを作成するとき、ユーザーにとってデータを表示し、レコードを追加するだけでなく、編集することも重要な要素です。このパートでは WebMatrix を使って簡単にレコードの更新を行うページが作成し、パラメーターを使用して編集対象のデータを初期表示できることを学習しました。また、Razor 記法を使用してデータベースから適切なコードを取得し、HTTP POST で更新されたデータを受け取り、そのデータでデータベースを更新する方法を学びました。そして、処理が完了して、更新の内容をすぐに確認できるように一覧のページへリダイレクトする方法も学びました。次のステップではデータベースからレコードを削除する方法を学びます。