2013年4月7日日曜日

PHP:ランダムURLを埋め込んだメールを送信する会員登録システム

http://net.tutsplus.com/tutorials/php/create-a-signup-form-with-email-confirmation/を自分用に訳。





ステップ1:テンプレート

サイトのベーシックなレイアウトを入れておいたので、フォームを作ったりかわいく見えるサイトを作るために時間を無駄にすることはない。君がここに来た理由であるコーディングにすぐ取り組める。

 Site Template folderを開き(←ない。有料登録したらDLできるのか?)、ローカルホストかウェブサーバーにコピーする。

index.phpを開いてちょっと見てほしい。入力項目が3つあるシンプルなフォームがあるだろう。これからキャプチャーするフィールドだ。ユーザーネーム、パスワード、eメール。ユーザーがサインアップした時に他の要素をキャプチャーすることもできる。が、今必要なのは3つだ。

ステップ2:MySQLのセットアップ

PHPMyAdminか、MySQLの管理に使っているプログラムを開いて、新しいデータベースを作る。名前は何でも良い。ユーザーの情報confirmの情報を入れておくための列が必要だ。そのためUsersとConfirmの2つのテーブルを作る。

  1. CREATE TABLE `users` (  
  2.   `id` int(11) NOT NULL auto_increment,  
  3.   `username` varchar(50) NOT NULL default '',  
  4.   `passwordvarchar(128) NOT NULL default '',  
  5.   `email` varchar(250) NOT NULL default '',  
  6.   `active` binary(1) NOT NULL default '0',  
  7.   PRIMARY KEY  (`id`)  
  8. ) ENGINE=MyISAM AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;  
最初のテーブルには列を5つ作る。最初はユーザーがサインアップするときに与えるIDだ。これは自動生成するのでユーザーはユニークなIDを持つ。次にユーザーネーム、パスワード、IDだ。 最後の2つはユーザーのステータスをアクティブにするのに使う(←この訳怪しい)。最初はアクティブステータスのデフォルトは0で、ユーザーのアカウントは非アクティブだ。ユーザーがconfirmすればアクティブステータスを1にする。これでアカウントはアクティブになる。

  1. CREATE TABLE `confirm` (  
  2.   `id` int(11) NOT NULL auto_increment,  
  3.   `userid` varchar(128) NOT NULL default '',  
  4.   `keyvarchar(128) NOT NULL default '',  
  5.   `email` varchar(250) default NULL,  
  6.   PRIMARY KEY  (`id`)  
  7. ) ENGINE=MyISAM AUTO_INCREMENT=27 DEFAULT CHARSET=utf8; 
2つ目のテーブルはconfirmテーブルだ。ここにはユーザーのID、eメール、ユーザーアカウントをconfirmするためにランダム生成されたキーを入れる。

ステップ3:MySQLに接続する

inc/php/config.phpを開く。
まずデータベースに接続しないといけない。

  1. mysql_connect('localhost''username''password'or die("I couldn't connect to your database, please make sure your info is correct!"); 
君のセットアップによっては、variablesをいくつか変更しないといけない。

次に どのデータベースを使うかMySQLに教えてやる。

 mysql_select_db('your_database_name'or die("I couldn't find the database table make sure it's spelt right!");
 すべて編集したらindex.phpをサーバーにアップ。

トップに何もエラーが出なければ接続成功。

ステップ4:フォームのSubmit

フォームデータをキャプチャーする。

コードの一部を記載して説明した後、変更を実施して機能を追加しよう。
index.phpのトップに以下の記載がある。
  1. //check if the form has been submitted  
  2. if(isset($_POST['signup'])){  
  3.   
  4. }
ここではフォームがsubmitされたかどうかのステータスをチェックしている。
これがないと、ページがリフレッシュされる度にスクリプトが走ってしまう。

注:使っているアプリケーションやコーディングスタイルによっては、このコードはフォームがsubmitされた時にアクセスされる別なファイルに入っているかもしれない。自分はシンプルにして追いやすくするため全部1ファイルにまとめている。

ステップ5:変数を整理してチェックする

ユーザーの入力内容をチェックしたい。
最初のパートでは$_POST変数をシンプルな変数にしてデータベース格納用に整形している。
  1. $username = mysql_real_escape_string($_POST['username']);  
  2. $password = mysql_real_escape_string($_POST['password']);  
  3. $email = mysql_real_escape_string($_POST['email']);  
mysql_real_escapse_string() では、ユーザーにアポストロフィを使わせないようにしている。
(MySQLインジェクションでデータベースにアクセスさせないため)
ユーザーが入力した情報をデータベースに入れたい時は常に、mysql_real_escape_string()を通すようにしてほしい。MySQLインジェクションについて詳しくはWikipedia参照

変数をきれいにしたら、入力漏れがないかチェックする。
  1. if(empty($username)){ //put code in me please }  
  2. if(empty($password)){ //put code in me please }  
  3. if(empty($email)){ //put code in me please }  
if文を3つ使って各フィールドが空でないかチェックしている。
もしフィールドが空なら、いくつか変数をアサインする。

配列を作って登録プロセスのステータスとユーザーに見せる文言を入れる。
このコードのすぐ上に、配列と変数をいくつか作っておく。

  1. $action = array();  
  2. $action['result'] = null;  
  3.   
  4. $text = array();  
まず、actionという空の配列を作り、結果の値をセットする。
この結果には成功か失敗の値がある。

次に、textという空の配列をもう一つ作る。
ここには、登録の間ユーザーに見せたいテキストがぜんぶ入ることになる。

変数をチェックするこのif文はまだ何のコードも実行しないので、最初のif文にコードを追加する。
このコードをusernameのif文の中に入れる。
  1. $action['result'] = 'error';  
  2. array_push($text,'You forgot your username'); 
usernameが空でsubmitされたら、上のコードが走ってエラーを返す。
そこでarray_push()を使って、text配列に何かテキストを置く。
これは他の2つのif文でも使うので、このコードをそちらにもコピペする。
if文の内容に合わせてテキストを変更する。

注:フォームsubmitで起きる複数のエラーに対応するためarray_push()を使っているが、すべてのif文が実行されるなら、テキストの配列は次のようになる。

  1. Array(  
  2.     [0] => 'You forgot your username',  
  3.     [1] => 'You forgot your password',  
  4.     [2] => 'You forgot your email'  

ステップ6:エラーがなければユーザーを登録

action配列の返り値がエラーになるかどうかチェックしよう。

  1. if($action['result'] != 'error'){  
  2.     //no errors, continue signup  
  3.        $password = md5($password);  
  4. }  
  5.       
  6. $action['text'] = $text
md5() functionにパスワードも通している。
このfunctionはpasswordを次のような32文字の文字列で返す。
a3470ce826283eca7ce3360d0f26b230

パスワードをデータベースに入れる前にハッシングfunctionを通すのはいい取り組みだ。
もしデータベースがハッキングされてもこれによってパスワードを見られることがなくなる。

もしactionの返り値がエラーなら、このコードすべてをスキップしてエラーを表示し、ユーザーに修正してもらう。
最後のコードでtext配列の値をaction配列に入れる。

ステップ7:ユーザーをデータベースに追加する

最後のif文にこのコードを追加する。

  1. ...  
  2. If Statement checking for errors  
  3. ...  
  4.   
  5. //add to the database  
  6. $add = mysql_query("INSERT INTO `users` VALUES(NULL,'$username','$password','$email',0)");  
  7.           
  8. if($add){  
  9.   
  10.     //the user was added to the database      
  11.               
  12. }else{  
  13.           
  14.     $action['result'] = 'error';  
  15.     array_push($text,'User could not be added to the database. Reason: ' . mysql_error());  
  16.     =  
  17. }  
ユーザーの情報をデータベースに入れるためmysql_query() INSERTを使う。
次に、もう一つif文を追加してユーザーがデータベースに追加されたかチェックする。
これは$add変数がtrueかfalseかでチェックできる。
ユーザーが追加されていれば登録を継続し、そうでなければ適当な変数を割り当てて登録を中止する。

MySQLの作業ではmysql_error() functionを使う。
mysql_error() functionはエラーをテキストで吐いてくれるので、クエリーのどこに問題があるかデバッグするのに役立つ。

ステップ8:Confirmが必要

ユーザーがフォームをsubmitして全てチェックを通りデータベースに入ったら、ユーザーがアカウントを使えるようにしないといけない。confirmをセットアップしよう。
  1. ...  
  2. if added check  
  3. ...  
  4.   
  5. //get the new user id  
  6. $userid = mysql_insert_id();  
  7.               
  8. //create a random key  
  9. $key = $username . $email . date('mY');  
  10. $key = md5($key);  
  11.               
  12. //add confirm row  
  13. $confirm = mysql_query("INSERT INTO `confirm` VALUES(NULL,'$userid','$key','$email')");   
  14.               
  15. if($confirm){  
  16.               
  17.     //let's send the email  
  18.   
  19. }else{  
  20.                   
  21.     $action['result'] = 'error'; 
  22.     array_push($text,'Confirm row was not added to the database. Reason: ' . mysql_error());  
  23.                   
簡単に言うと、新しいユーザーIDを変数に割り当て、それを後で使う。
これを実現するのにmysql_insert_id()を使う。
mysql_insert_id()はどんな新しいユーザーIDでも$useridにセットする。
次にユーザー固有のランダムキーを作る。
変数を作ってkeyという名前にする。でusername、email、dateを代入する。
文字列はmattmatt@email.com012009のようになる。
そしてmd5() functionを使ってそのユーザー固有のランダムな文字列にコンバートする。

mysql_query() and INSERTをもう一度使って、新しいユーザーID、kerとemailをデータベースに入れる。

ステップ9:eメールのテンプレートをセッティング

PHPのコーディングから一時離れて新しいファイルを2つ作る。
効率UPのため、このチュートリアルに入れておいた2つのテンプレートを使う。
これから見ていく2ファイルはsignup_template.htmlsignup_template.txtだ。
ユーザーのメールソフトがHTMLメールに対応してない場合にHTMLとTEXTバージョンを切り替えて使う。
signup_template.htmlを開こう。

注: eメールのHTMLをよく研究すること。
このファイルの編集まではやらない。仕組みを説明して、このチュートリアルを終えた後に利用できるようにするところまでだ。
このファイルの最も重要なパートは{USERNAME}やconfirm.php?email={EMAIL}&key={KEY}のようなタグだ。
これからこのテンプレートを使いフォームから得られる変数でこれらのタグを入れ替えるfunctionを書く。

ステップ10:テンプレートの機能

inc/php/functions.phpを開くと、以下のようなコードがある。
  1. function format_email($info$format){  
  2.   
  3.     //set the root  
  4.     $root = $_SERVER['DOCUMENT_ROOT'].'/dev/tutorials/email_signup';  
  5.   
  6.     //grab the template content  
  7.     $template = file_get_contents($root.'/signup_template.'.$format);  
  8.               
  9.     //replace all the tags  
  10.     $template = ereg_replace('{USERNAME}'$info['username'], $template);  
  11.     $template = ereg_replace('{EMAIL}'$info['email'], $template);  
  12.     $template = ereg_replace('{KEY}'$info['key'], $template);  
  13.     $template = ereg_replace('{SITEPATH}','http://site-path.com'$template);  
  14.           
  15.     //return the html of the template  
  16.     return $template;  
  17.   
format_email()はindex.phpでも使われる2つの変数を使う。
最初の変数はフォームの情報の配列で、二つ目の変数はフォーマットだ。 
フォーマットの変数があるので、この配列をHTMLとTXTバージョンのどちらのテンプレートにも再利用できる。

最初にルートを設定する。
これはテンプレートがあるフォルダを指す。

次にテンプレートの中身を利用できるようにして、それを変数に入れる。

これで ereg_replace()を使ってテンプレート内にある{USERNAME}タグをフォームで入力された内容に入れ替えられる。
このテンプレートは基本的にスーパーシンプルなシステムだ。 

最後に全てのhtmlが入っているテンプレート変数に戻る。

説明:要はformat_email()がテンプレートファイルを開き、HTMLを読み込んで変数にアサインする。
これは簡潔な方法で、その後全てのHTMLをfunctionそのものにアサインする。 

ステップ11:メール送信

Swiftを実行してメールを送信するためもう一つfunctionを書く。

  1. function send_email($info){  
  2.           
  3.     //format each email  
  4.     $body = format_email($info,'html');  
  5.     $body_plain_txt = format_email($info,'txt');  
  6.   
  7.     //setup the mailer  
  8.     $transport = Swift_MailTransport::newInstance();  
  9.     $mailer = Swift_Mailer::newInstance($transport);  
  10.     $message = Swift_Message::newInstance();  
  11.     $message ->setSubject('Welcome to Site Name');  
  12.     $message ->setFrom(array('noreply@sitename.com' => 'Site Name'));  
  13.     $message ->setTo(array($info['email'] => $info['username']));  
  14.       
  15.     $message ->setBody($body_plain_txt);  
  16.     $message ->addPart($body'text/html');  
  17.               
  18.     $result = $mailer->send($message);  
  19.       
  20.     return $result;  
  21.       
  22. }  
format_email()のように、 send_email()は情報の配列を変数としてとる。
funcitonの最初のパートでは2つの変数をアサインする。
$body と $body_plain_textだ。

format_email()でテンプレートのHTML値を各変数にアサインする。
 
Swift_MailTransport:newInstance()を使ってswiftインスタンスをセットアップし、Swift_Mailer::newInstance($transport);でメールソフトをセットアップする。
 
Swiftメッセージの新しいインスタンスを作ってこのインスタンスに変数をいくつかアサインする。
メールのsubjectとtoのアドレス、それからsetBody()を使ってテキストバージョンのメールをメーラーインスタンスにアサインアウトする。

HTMLバージョンの追加にはaddPart()を使う。
send() functionはメール送信を司り、そしてresultに戻る。 

これでメールを作って送るfunctionができた。
index.phpに戻ってメインの登録をやっつけよう。

ステップ12:送信した?Confirmする?

最後はconfirm列が作られたかどうかをチェックするif文だ。
eメールを送信して、何も問題ないか確認しよう。
  1. ...  
  2. if confirm  
  3. ...  
  4.   
  5. //include the swift class  
  6. include_once 'inc/php/swift/swift_required.php';  
  7.               
  8. //put info into an array to send to the function  
  9. $info = array(  
  10.     'username' => $username,  
  11.     'email' => $email,  
  12.     'key' => $key  
  13. );  
  14.               
  15. //send the email  
  16. if(send_email($info)){  
  17.                                   
  18.     //email sent  
  19.     $action['result'] = 'success';  
  20.     array_push($text,'Thanks for signing up. Please check your email for confirmation!');  
  21.                   
  22. }else{  
  23.                       
  24.     $action['result'] = 'error';  
  25.     array_push($text,'Could not send confirm email');  
  26.                   
  27. }  
Swiftクラスがなくてはメールを送信できないので、最初にswiftクラスをincludeしている。

新しいfunctionの両方に情報を送らないといけないので、新しい配列を作って変数をアサインする。
if文の追加も必要だが、ユーザーの簡便性のためにエラーをチェックする必要がある。
ユーザーは常に想像できる限りのミスをすると仮定しておかないといけない。

send_email() functionを、$info arrayをパスするのと同じようにもう一つのif文にラップする。

もしメールが送信されたら成功の値をアサインし、ユーザーに登録を感謝する。

エラーが出たらおなじみの値を使う。

登録はほとんど完了だ。
最後に一つだけfunctionを作る必要がある。
エラーや成功の変数をアサインしたが、ユーザーに情報を示すテキストを表示するようにしていない。

functions.phpに次のコードをペーストする。
  1. //cleanup the errors  
  2. function show_errors($action){  
  3.   
  4.     $error = false;  
  5.   
  6.     if(!empty($action['result'])){  
  7.       
  8.         $error = "<ul class="\"alert" $action[result]\"="">"."\n";  
  9.   
  10.         if(is_array($action['text'])){  
  11.       
  12.             //loop out each error  
  13.             foreach($action['text'as $text){  
  14.               
  15.                 $error .= "<li><p>$text</p></li>"."\n";  
  16.               
  17.             }     
  18.           
  19.         }else{  
  20.           
  21.             //single error  
  22.             $error .= "<li><p>$action</p></li>";  
  23.           
  24.         }  
  25.           
  26.         $error .= "</ul>"."\n";  
  27.           
  28.     }  
  29.   
  30.     return $error;  
  31.   
複雑に見えるかもしれないが、実際には成功/エラーを作っているだけだ。

まず配列が空かどうかチェックして、必要がなければコードを実行しない。

次にulタグを作ってresultをクラスにしている。

次の変数が配列か単なる文章かチェックする。
文章ならliにラップする。
配列なら、配列のアイテムを全部ループしてliにラップする。

最後に、ulを閉じて全体の文に戻る。

index.phpに戻ってheader.phpをインクルードしている所のすぐ後にこのコードを正しく入れたら、このセクションをラップアップできる。


ステップ13:ユーザーを登録する


We should have a good grip on how the script is functioning; so for this next script I’m going to give you the entire chunk of code and then go through it with you.

confirm.phpを開きヘッダーとshow_errors() functionの間にこれをペースト

Open up confirm.php and paste this in-between the header include and your show_errors() function.
  1. //setup some variables  
  2. $action = array();  
  3. $action['result'] = null;  
  4.   
  5. //quick/simple validation  
  6. if(empty($_GET['email']) || empty($_GET['key'])){  
  7.     $action['result'] = 'error';  
  8.     $action['text'] = 'We are missing variables. Please double check your email.';            
  9. }  
  10.           
  11. if($action['result'] != 'error'){  
  12.   
  13.     //cleanup the variables  
  14.     $email = mysql_real_escape_string($_GET['email']);  
  15.     $key = mysql_real_escape_string($_GET['key']);  
  16.       
  17.     //check if the key is in the database  
  18.     $check_key = mysql_query("SELECT * FROM `confirm` WHERE `email` = '$email' AND `key` = '$key' LIMIT 1"or die(mysql_error());  
  19.       
  20.     if(mysql_num_rows($check_key) != 0){  
  21.                   
  22.         //get the confirm info  
  23.         $confirm_info = mysql_fetch_assoc($check_key);  
  24.           
  25.         //confirm the email and update the users database  
  26.         $update_users = mysql_query("UPDATE `users` SET `active` = 1 WHERE `id` = '$confirm_info[userid]' LIMIT 1"or die(mysql_error());  
  27.         //delete the confirm row  
  28.         $delete = mysql_query("DELETE FROM `confirm` WHERE `id` = '$confirm_info[id]' LIMIT 1"or die(mysql_error());  
  29.           
  30.         if($update_users){  
  31.                           
  32.             $action['result'] = 'success';  
  33.             $action['text'] = 'User has been confirmed. Thank-You!';  
  34.           
  35.         }else{  
  36.   
  37.             $action['result'] = 'error';  
  38.             $action['text'] = 'The user could not be updated Reason: '.mysql_error();;  
  39.           
  40.         }  
  41.       
  42.     }else{  
  43.       
  44.         $action['result'] = 'error';  
  45.         $action['text'] = 'The key and email is not in our database.';  
  46.       
  47.     }  
  48.   
  49. }  
大部分はなじみがあると思うので、間を飛ばしてkeyがデータベースセクションにあるかどうかチェックする。

またmysql_query()を使い、emailとkeyがユーザーのemailから提供されたkeyに等しい行を取得する。 
mysql_num_rows()で該当する行の数が0より大きいかどうかチェックする。

データベースにemailとkeyがあれば、 mysql_fetch_assoc()でデータベースから全ての情報を取れる。

ユーザーがアカウントをconfirmしたら、データベースを更新してactive rowを1にセットする必要がある。
もう一度mysql_query()を使うが、INSERTの代わりにUPDATEを使ってuserIDが現在のユーザーのIDと同じactive rowを更新する。


すべてをきれいにするため、 mysql_query()とDELETEでconfirmation rowをデータベースから削除する。
これでユーザーはこのページに戻れなくなり、confirmを繰り返すことはできなくなる。
これでデータベースもきれいに保つことができる。

終わりに

このチュートリアルでは多岐にわたるエリアをカバーしてきた。
emailを送信するためにサードパーティのスクリプトをダウンロードしてインクルードしたし、
シンプルなフォームの確認をインプリメントした。
emailを整形するためにスーパーシンプルなテンプレートも作った。

If you’re new to MySQL we’ve touched on the three most common functions in MySQL so you should have no problem completing some more advanced tutorials.

Final Notes



























































0 件のコメント:

コメントを投稿