php 会員登録機能をつくろう
» STARTOUT詳細はこちら

WEBサービスづくり学習「STARTOUT」はじめました!

自分の「WEBサービス」を作りながら「制作技術」を習得しよう!

STARTOUTとは、WEB制作×サービス作りのオンライン実践学習サービスです。ゼロからWEBサービスを作り、収益化しながら技術を習得してみましょう!

 詳しくはこちら
ここでは「WEB制作×事業づくり実践学習サービス STARTOUT」の学習コンテンツの一部を公開しています。もし1,000以上あるすべてのコンテンツを学び尽くしたい場合、ぜひこちらからご登録ください!

会員登録機能をつくろう

php|2018年11月16日

2018年11月16日
  • このエントリーをはてなブックマークに追加

WEBサービスを開発するのであれば「会員登録機能」は、ほぼ必須です。

今回は、シンプルな会員登録機能を作ってみます。
メールアドレスとパスワードを入力して登録するだけです。

会員登録システムには、基本中の基本となる3つの機能があります。
登録機能とログイン、そしてユーザー情報の編集です。
この3つを習得すると、応用で色々作れるようになります。

ぜひ、理解できるまで「繰り返して」みてください。

今回のポイントとなるのは2つ。

入力エラーがないか確認する「バリデーションチェック」。
そして「パスワードの暗号化」です。

セキュリティ上、パスワードは誰にも知られてはいけません。
それが、管理者であってもです。
データベースにも、本物が分からないように暗号化して保存する必要があります。

とは言っても、難しいことではありません。
phpには暗号化の処理も存在しているのです。

今回も、前回までのファイルに機能を加える形で作っていきます。
前回までのファイルを持っている方は、そのままカスタマイズして進めてください。

ミッションの内容

下記のファイルを再現してみてください。
基本的には、前回のファイルのアップデートです。

特に気をつけるポイントは、入力内容のバリデーションチェック。
そして、パスワードの暗号化です。

まず、ソースコードの解説を読み、自分自信で実装してみてください。
どうしても分からない場合は解答ファイルを参考にしましょう。

ソースコードの説明を下記に記載します。
まず一通り目を通して、同時に自分のエディタで試してみてください。

ソースコードの解説

まず、全体のソースコードをみていきましょう。

<?php
     
    //データベース呼び出し
    require_once "functions/db.php";
    //URLパラメータ取得
    $editId = $_GET["edit"];
     
    //URLパラメータからidを受け取り、該当のユーザーを検索
    $userdataEdit = "select * from userdata where id = '".$editId."' order by id DESC"; 
    $userdataEdit = mysqli_query($mysqli,$userdataEdit);
         
    while ($userdataEditArray = mysqli_fetch_assoc($userdataEdit)) {
        $name = $userdataEditArray["name"];
        $age = $userdataEditArray["age"];
        $skill = $userdataEditArray["skill"];
        //新しく会員登録やログインに必要なメールとパスワードが追加。
        $mail = $userdataEditArray["mail"];
        //$hashpassは暗号化されたパスワードという意味。
        $hashpass = $userdataEditArray["password"];
    };
     
    //存在したユーザー数カウント。
    $userCount = $userdataEdit->num_rows;
         
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
         
        //ポストされたデータをキャッチします。
        $name = htmlspecialchars($_POST['name'], ENT_QUOTES);
        $age = htmlspecialchars($_POST['age'], ENT_QUOTES);
        $skill = htmlspecialchars($_POST['skill'], ENT_QUOTES);
         
        //メールアドレスとパスワードをキャッチします。
        $mail = htmlspecialchars($_POST['mail'], ENT_QUOTES);
        $password = htmlspecialchars($_POST['password'], ENT_QUOTES);
         
        //メールアドレスが正しいメールアドレスかどうかを確認する関数です。
        function mailcheck($mail){
            //こちらの記号は正規表現と言います。
            //今回は、メールアドレスの形を表しています。
            //正規表現で$mail内に入っているデータがメールアドレスの形じゃなければfalseを返します。
            if(preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD', $mail)){
                 return 'true';
            }else{
                 return 'false';
            }
        };
             
        //$mailが空じゃなければバリデーションチェック呼び出します。
        //空の場合は$mailresultにfalseを返します。
        if(!empty($mail)){
            $mailresult = mailcheck($mail);
        }else{
            $mailresult = "false";
        };
             
        //パスワード暗号化と空欄チェックを行います。
        if(!empty($password)){
            //パスワードは、管理者にも知られてはいけません。
            //必ず、受けとったパスワードのデータを暗号化します。
            //$passwordに文字列が入っていれば、それが暗暗号化され$hashpassに入ります。
            $hashpass = password_hash($password, PASSWORD_BCRYPT);
        };
             
        //もし暗号化されたパスワードが$hashpassになければ$passresultがfalseに。
        if(empty($hashpass)){
            $passresult = "false";
        };
             
        //すでにユーザーが存在していた場合はアップデート。
        //メールアドレスとパスワードが入力されていた場合に実行。
        if($userCount !== 0&&$mailresult!=="false"&&$passresult!=="false"){         
            $result = mysqli_query($mysqli,"update userdata set name = '".$name."',age = '".$age."',skill = '".$skill."',mail = '".$mail."',password = '".$hashpass."' where id = '".$editId."'");
             echo "アップデート完了";
        }
             
        if($userCount == 0&&$mailresult!=="false"&&$passresult!=="false"){
            //$userCountが0だった場合は新規で登録。
            //メールアドレスとハッシュパスがあれば登録可能。
            $result = mysqli_query($mysqli,"insert into userdata(name,age,skill,mail,password) VALUES('$name','$age','$skill','$mail','$hashpass')");
            echo "新規登録完了";
        };
             
    };
?>
     
<div style="padding-bottom:15px;">
    <a href="https://base91.net/mission/php/9/">新規追加</a>
</div>
     
<h1>登録フォーム</h1>
<form method="post" action="">        
    <input type="text" name="mail" placeholder="メールアドレス" value="<?php echo $mail; ?>" /><br/>
    <!--もし$mailresultがfalseの場合はエラー表示。-->
    <?php if($mailresult == "false"){echo "メールアドレスにエラーがあります。<br/>";}; ?>
    <input type="password" name="password" placeholder="パスワード" value="" /><br/>
    <!--もし$passresultがfalseの場合はエラー表示。-->
    <?php if($passresult == "false"){echo "パスワードにエラーがあります。<br/>";}; ?>
    <input type="text" name="name" placeholder="お名前" value="<?php echo $name; ?>" /><br/>
    <input type="text" name="age" placeholder="年齢" value="<?php echo $age; ?>" /><br/>
    <input type="text" name="skill" placeholder="スキル" value="<?php echo $skill; ?>" /><br/>
    <?php if($userCount == 0): ?>
    <input type="submit" name="submitBtn" value="登録" />
    <?php else: ?>
    <input type="submit" name="submitBtn" value="更新" />
    <?php endif; ?>
</form>
     
     
<?php
         
    //投稿データ一覧
    $userdata = "select * from userdata order by id DESC"; 
    $userdata = mysqli_query($mysqli,$userdata);
         
    while ($userdataArray = mysqli_fetch_assoc($userdata)) {
        echo $id = $userdataArray["id"];
        echo ",";
        echo $name = $userdataArray["name"];
        echo ",";
        echo $age = $userdataArray["age"];
        echo ",";
        echo $skill = $userdataArray["skill"];
        echo "|";
        echo "<button class='deleteBtn' data-id='".$id."'>削除する</button>";
        echo "|";
        echo "<button class='editBtn' data-id='".$id."'>編集する</button>";
        echo "<br>";
    };
         
?>
<script>
         
    //削除ボタン押された時
    $(".deleteBtn").click(function(){
        var btnid = $(this).data("id");
        deleteData(btnid);
    });
     
    //編集ボタン押された時
    $(".editBtn").click(function(){
        var btnid = $(this).data("id");
        window.location.href = "./?edit="+btnid;
    });
         
    //削除ボタン押された時に呼び出される関数
    function deleteData(btnid){
        $.ajax({
                type: 'POST',
                dataType:'json',
                url:'functions/delete_func.php',
                data:{
                    btnid:btnid,
                },
                success:function(data) {
                    window.location.href = "./";
                },
                error:function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(errorThrown);
                }
        });
    };
         
</script>

以上が全体のソースコードになります。
まずは、HTMLから見ていきましょう。

<div style="padding-bottom:15px;">
    <a href="https://base91.net/mission/php/9/">新規追加</a>
</div>
     
<h1>登録フォーム</h1>
<form method="post" action="">        
    <input type="text" name="mail" placeholder="メールアドレス" value="<?php echo $mail; ?>" /><br/>
    <!--もし$mailresultがfalseの場合はエラー表示。-->
    <?php if($mailresult == "false"){echo "メールアドレスにエラーがあります。<br/>";}; ?>
    <input type="password" name="password" placeholder="パスワード" value="" /><br/>
    <!--もし$passresultがfalseの場合はエラー表示。-->
    <?php if($passresult == "false"){echo "パスワードにエラーがあります。<br/>";}; ?>
    <input type="text" name="name" placeholder="お名前" value="<?php echo $name; ?>" /><br/>
    <input type="text" name="age" placeholder="年齢" value="<?php echo $age; ?>" /><br/>
    <input type="text" name="skill" placeholder="スキル" value="<?php echo $skill; ?>" /><br/>
    <?php if($userCount == 0): ?>
    <input type="submit" name="submitBtn" value="登録" />
    <?php else: ?>
    <input type="submit" name="submitBtn" value="更新" />
    <?php endif; ?>
</form>

前回と比べて、メールアドレスと、パスワードの入力欄が増えているのがおわかりでしょうか。

また、メールアドレスとパスワードは、入力必須です。
未入力や間違っていればエラーが出るようになっています。
こうした入力内容のエラーチェックをバリデーションチェックと言います。

エラーの出し方については、また後ほどご説明させて頂きます。

次にphpを見ていきましょう。
まずは、最初の設定からです。

//データベース呼び出し
require_once "functions/db.php";
//URLパラメータ取得
$editId = $_GET["edit"];
 
//URLパラメータからidを受け取れとり、該当のユーザーを検索
$userdataEdit = "select * from userdata where id = '".$editId."' order by id DESC"; 
$userdataEdit = mysqli_query($mysqli,$userdataEdit);
     
while ($userdataEditArray = mysqli_fetch_assoc($userdataEdit)) {
    $name = $userdataEditArray["name"];
    $age = $userdataEditArray["age"];
    $skill = $userdataEditArray["skill"];
    //新しく会員登録やログインに必要なメールとパスワードが追加。
    $mail = $userdataEditArray["mail"];
    //$hashpassは暗号化されたパスワードという意味。
    $hashpass = $userdataEditArray["password"];
};
     
//存在したユーザー数カウント。
$userCount = $userdataEdit->num_rows;

URLパラメータを元にデータベースからユーザーデータを呼び出しています。
ユーザーデータの更新に使う時の処理です。
前回からの継続して使う処理ですね。

前回から変わったのは、$mailと$hashpassが加わっているところです。

$mailにメールアドレスを呼び出します。
$hashpassに暗号化済みのパスワードを呼び出します。
今回、会員登録で上記のデータも登録させます。

なお、データベースに登録されているパスワードは、すべて暗号化済みのパスワードです。
暗号化をハッシュ化と呼びます。
暗号化されているので、開発者にもわかりません。

次は、フォームに内容を入力し、登録ボタンが押された後の機能です。
登録ボタンが押されると、同じページが再読み込みされます。
その際、フォームに入力されたデータも再読み込みされたページに渡されます。
渡されたデータを受け取って、登録していきます。

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
     
    //ポストされたデータを受け取ります。
    $name = htmlspecialchars($_POST['name'], ENT_QUOTES);
    $age = htmlspecialchars($_POST['age'], ENT_QUOTES);
    $skill = htmlspecialchars($_POST['skill'], ENT_QUOTES);
     
    //メールアドレスとパスワードを受け取ります。
    $mail = htmlspecialchars($_POST['mail'], ENT_QUOTES);
    $password = htmlspecialchars($_POST['password'], ENT_QUOTES);
     
    //メールアドレスが正しいメールアドレスかどうかを確認する関数です。
    function mailcheck($mail){
        //下記の記号は正規表現と言います。
        //今回は、文字がメールアドレスの形式になっているかの確認です。
        //正規表現で$mail内に入っているデータがメールアドレスの形じゃなければfalseを返します。
        if(preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD', $mail)){
             return 'true';
        }else{
             return 'false';
        }
    };
             
    //$mailが空じゃないかの確認です。
    //空じゃなければバリデーションチェック呼び出します。
    //空の場合は$mailresultにfalseを返します。
    if(!empty($mail)){
        $mailresult = mailcheck($mail);
    }else{
        $mailresult = "false";
    };
             
    //パスワード暗号化と入力チェックを行います。
    //!empty(空じゃない)場合、if文の中の処理を実行します。
    if(!empty($password)){
        //パスワードは、管理者にも知られてはいけません。
        //必ず、受けとったパスワードのデータを暗号化します。
        //$passwordに文字列が入っていれば、それが暗号化され$hashpassに入ります。
        $hashpass = password_hash($password, PASSWORD_BCRYPT);
    }else{
        $passresult = "false";
    };
             
    //すでにユーザーが存在していた場合は更新処理。
    //メールアドレスとパスワードが入力されていた場合に実行。
    if($userCount !== 0&&$mailresult!=="false"&&$passresult!=="false"){         
        $result = mysqli_query($mysqli,"update userdata set name = '".$name."',age = '".$age."',skill = '".$skill."',mail = '".$mail."',password = '".$hashpass."' where id = '".$editId."'");
         echo "アップデート完了";
    }
             
    if($userCount == 0&&$mailresult!=="false"&&$passresult!=="false"){
        //$userCountが0だった場合は新規で登録。
        //メールアドレスとハッシュパスがあれば登録可能。
        $result = mysqli_query($mysqli,"insert into userdata(name,age,skill,mail,password) VALUES('$name','$age','$skill','$mail','$hashpass')");
        echo "新規登録完了";
    };
             
};

色々、前回から増えているので、順番に見ていきましょう。

まず「ポストされたデータ」を受け取ります。
最初に前回と同じデータをキャッチしています。
続けて「メールアドレスとパスワード」を受け取っています。
入力項目は増えたので、もちろん受け取る項目も増えます。

ここで気をつけて欲しいのが、パスワードの変数が2つあること。
フォームから素のパスワードを受け取る変数。
データベースから暗号化されたパスワードを呼び出して受け取る変数。
それぞれ別になっています。

$hashpassが暗号化されたパスワードを受け取る変数。
$passwordが暗号化されていないパスワードを受け取る変数です。

次に「メールアドレスのバリデーションチェックの関数」を作ります。
バリデーションとは入力エラーがないか確かめるための処理ですね。

例えばフォームはからじゃないか。
メールアドレスであれば、@マークが入っているか。
半角英数字か、形式に沿っているか。
決まりに倣って入力されているかどうかです。

下記のソースコードに注目してください。

if(preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD', $mail))

preg_matchの次に、謎のソースコードがあるのが分かると思います。
これを正規表現と言いまして、文字列のルールを表すものです。

preg_matchで正規表現で書かれたルールと変数$mailに入っている文字列を比較します。
そして、文字列がメールアドレスのルールに沿っているかどうかを判断します。

if文で、もしルールに沿っていたら、returnでtrueかfalseを返します。

//メールアドレスバリデーションチェックの関数
function mailcheck($mail){
    if(preg_match('/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/iD', $mail)){
        return 'true';
    }else{
        return 'false';
    }
};

なお最初のうちはreturnでtrueかfalseが返される、と言っても「どこに」返されるのか迷う方も多いかと思います。
それは、関数を実行する下記のソースコードを見れば分かります。

if(!empty($mail)){
    $mailresult = mailcheck($mail);
}else{
    $mailresult = "false";
};

メールが空でなければ、上の処理を実行。
空であれば下の処理を実行します。
$mailresult = mailcheck($mail); が関数を呼び出す処理です。

変数が関数と「=」でつながっているのが、おわかりでしょうか。
returnで返されたtrueやfalseは、その文字が$mailresultの中に入るのです。
呼び出す時に$mailresultにreturnで返された答えを受け取れるように書いているんですね。

なお、もし$mailが空であれば、バリデーションをチェックすることなく、直接falseが入ります。
$mailresultにfalseが入っていたら、エラーが表示されるという仕組みです。

さて、次はパスワードの暗号化についてご説明しましょう。

//パスワード暗号化と空欄チェックを行います。
if(!empty($password)){
    //パスワードは、管理者にも知られてはいけません。
    //必ず、受けとったパスワードのデータを暗号化します。
    //$passwordに文字列が入っていれば、それが暗暗号化され$hashpassに入ります。
    $hashpass = password_hash($password, PASSWORD_BCRYPT);
}else{
    $passresult = "false";
};

もし受け取ったパスワードが空であれば、そのまま$passresultにfalseが返されます。
パスワードが存在していたら、パスワードを暗号化し、trueを返します。

暗号化しているのは、下記のソースコードです。

$hashpass = password_hash($password, PASSWORD_BCRYPT);

変数$passwordをpassword_hashで暗号化します。
その後、$hashpassに返します。
暗号化の処理はこれだけです。

では、入力されたデータをデータベースに保存していきましょう。

//すでにユーザーが存在していた場合はアップデート。
//メールアドレスとパスワードが入力されていた場合に実行。
if($userCount !== 0&&$mailresult!=="false"&&$passresult!=="false"){         
    $result = mysqli_query($mysqli,"update userdata set name = '".$name."',age = '".$age."',skill = '".$skill."',mail = '".$mail."',password = '".$hashpass."' where id = '".$editId."'");
     echo "アップデート完了";
}
             
if($userCount == 0&&$mailresult!=="false"&&$passresult!=="false"){
    //$userCountが0だった場合は新規で登録。
    //メールアドレスとハッシュパスがあれば登録可能。
    $result = mysqli_query($mysqli,"insert into userdata(name,age,skill,mail,password) VALUES('$name','$age','$skill','$mail','$hashpass')");
    echo "新規登録完了";
};

基本的には、前のソースコードと同じです。
ただ、条件が少し異なっています。

アップデートする条件は下記の2つ。

  • 該当IDのユーザーが存在する
  • $mailresultと$passwordがfalseじゃない

そして新規登録の条件は下記。

  • 該当IDのユーザーが存在しない
  • $mailresultと$passwordがfalseじゃない

それぞれの条件に沿って、アップデートか新規登録か決められます。
いずれにも当てはまらない、つまりエラーがある場合は何も起きません。

これで、今回の変更は以上です。
あとは前回までのソースコードと変わりません。

次回は、ログイン機能について、進めていきます。

WEBサービスづくり学習「STARTOUT」はじめました!

自分の「WEBサービス」を作りながら「制作技術」を習得しよう!

STARTOUTとは、WEB制作×サービス作りのオンライン実践学習サービスです。ゼロからWEBサービスを作り、収益化しながら技術を習得してみましょう!

 詳細はこちら
  • このエントリーをはてなブックマークに追加

ウエヤマ ショウタ

WEB制作 ✕ 事業づくり学習サービス「STARTOUT」|事業づくり実践学習サービス「WAREHOUSE」|教えない学校、IT留学シェアハウス「WORKROOM」|以上3つ運営してます。近々、上記の成果を束ねて、クリエイターと起業家が生まれ、事業が生み出され続ける町を作る人。ベルリンのホルツマルクトはロールモデル。

ウエヤマ ショウタ

WEB制作 ✕ 事業づくり学習サービス「STARTOUT」|事業づくり実践学習サービス「WAREHOUSE」|教えない学校、IT留学シェアハウス「WORKROOM」|以上3つ運営してます。近々、上記の成果を束ねて、クリエイターと起業家が生まれ、事業が生み出され続ける町を作る人。ベルリンのホルツマルクトはロールモデル。

WEBサービスづくり学習「STARTOUT」はじめました!

自分の「WEBサービス」を作りながら「制作技術」を習得しよう!

STARTOUTとは、WEB制作×サービス作りのオンライン実践学習サービスです。ゼロからWEBサービスを作り、収益化しながら技術を習得してみましょう!

 詳しくはこちら