迷い人

日々勉強。勉強の先に何か見つかるといいなぁ

【PHP】パーフェクトPHPを解説してみる その2

本日はデータベースにアカウント登録する処理について解説したいと思います。

 

前回の記事で、アカウント登録機能の画面表示までを解説したので、その続きになります。

oyaoya1123.hatenablog.com

 

この記事でわかること

  • データベースにアカウント登録するまでの処理の流れ

 

アカウント登録するまでの流れ

アカウント登録画面を表示後、ユーザIDとパスワードを登録して、ホーム画面に遷移するまでの処理について解説していきます。

 

f:id:oyaoya1123:20191008235632p:plain

処理の流れを大まかに以下の通り

  • アカウント登録画面からユーザIDとパスワードを入力して登録ボタンを押下
  • AccountControllerのregisterActionが起動する 

アカウント登録のためのメソッドが呼び出されるまで

 

アカウント登録画面のファイルは以下のようになっています。

 

signup.php
#省略
<form action="<?php echo $base_url; ?>/account/register" method="post"> <input type="hidden" name="_token" value="<?php echo $this->escape($_token); ?>" />
#省略
<?php echo $this->render('account/inputs', array( 'user_name' => $user_name, 'password' => $password, )); ?> <p> <input type="submit" value="登録" /> </p> </form>

 

inputs.php
<tr> <th>ユーザID</th> <td> <input type="text" name="user_name" value="<?php echo $this->escape($user_name); ?>" /> </td> </tr> <tr> <th>パスワード</th> <td> <input type="password" name="password" value="<?php echo $this->escape($password); ?>" /> </td> </tr>

 

formタグの中にinputタグが2つあって、それぞれユーザIDとパスワードに対応しています。

またformタグのactionが「 action="<?php echo $base_url; ?>/account/register 」となっており、base_urlが「 /index_dev.php 」なので送信先URLは

 

/index_dev.php/account/register

 

となります。

 

この送信先URLは以下のコントローラとアクションに対応しています。

 

  • コントローラ → AccountController
  • アクション → registerAction

 

コントローラとアクションを決定し、アクションが実行されるまでの流れは前回解説したアカウント登録画面表示と同じですが、簡単に解説すると以下のようになります。

 

  • コントローラとアクションを特定する・・・resolve()メソッド
  • アクションを実行する・・・runAction()メソッド

 

アカウント登録のためのメソッドregisterActionについて

registerActionメソッドはかなり長い関数になりますが以下のようになっています。

 

AccountController.php

public function registerAction() {
#methodがpostかチェック if (!$this->request->isPost()){ $this->forward404(); }
#csrf対策チェック $token = $this->request->getPost('_token'); if (!$this->checkCsrfToken('account/signup', $token)){ return $this->redirect('/account/signup'); }
#送信されたユーザIDとパスワードを取得 $user_name = $this->request->getPost('user_name'); $password = $this->request->getPost('password');
#送信されたユーザIDとパスワードをチェック $error = array(); if(!strlen($user_name)) { $errors[] = 'ユーザIDを入力してください'; } else if (!preg_match('/^\w{3,20}$/', $user_name)) { $errors[] = 'ユーザIDは半角英数字およびアンダースコアを3〜30文字以内で入力して下さい'; } else if (!$this->db_manager->get('User')->isUniqueUserName($user_name)){ $errors[] = 'ユーザIDはすでに使用されています'; } if (!strlen($password)) { $errors[] = 'パスワードを入力してください'; } else if (4 > strlen($password) || strlen($password) > 30) { $errors[] = 'パスワードは4〜30文字以内で入力してください'; }
#チェックでエラーがなければ
#ユーザIDとパスワードを登録し
#ログイン状態にして
#ホーム画面に遷移する if (count($errors) === 0){ $this->db_manager->get('User')->insert($user_name, $password); $this->session->setAuthenticated(true); $user = $this->db_manager->get('User')->fetchByUserName($user_name); $this->session->set('user', $user); return $this->redirect('/'); }
#エラーがある場合は再びアカウント登録画面に戻る return $this->render(array( 'user_name' => $user_name, 'password' => $password, 'errors' => $errors, '_token' => $this->generateCsrfToken('account/signup'), ), 'signup'); }

 

コードの中にもコメントを書きましたが、コードを大きく分けると以下のようになります。

 

  • methodがpostかチェック
  • csrf対策チェック
  • 送信されたユーザIDとパスワードを取得
  • 送信されたユーザIDとパスワードをチェック
  • チェックでエラーがなければ、ユーザIDとパスワードを登録し、ログイン状態にして、ホーム画面に遷移する
  • エラーがある場合は再びアカウント登録画面に戻る

 

methodがpostかチェック

送信データのmethodがpostかチェックします。今回はformタグでmethod=postと宣言しているのでチェックOKとなります。チェックする関数はRequestクラスで定義されています。

 

csrf対策チェック

簡単に解説すると、悪意あるユーザが本来のアカウント登録以外のページからアクセスしてきた時に、アカウント登録ページに戻します。

今回でいえば「account/signupページ」に対応するトークンと呼ばれる文字列が送られてこない場合、戻ることになります。

 

送信されたユーザIDとパスワードを取得

postで送信されてきたユーザIDとパスワードを取得しています。

 

送信されたユーザIDとパスワードをチェック

桁数やフォーマットをチェックしています。

 

チェックでエラーがなければ、ユーザIDとパスワードを登録し、ログイン状態にして、ホーム画面に遷移する

少し複雑ですが順番に解説していきます。

まず、get('User')でUserRepositroyのインスタンスを作成し、insert()でusersテーブルにユーザIDとパスワードを登録しています。

次にSessionクラスを使って、新規登録したユーザをログイン状態にします。ログインを画面が変わってもその状態を維持する必要があるので、SESSIONの仕組みを利用します。

最後にリダイレクトでホーム画面に遷移します。

 

おつかれさまでした。これでアカウント画面からアカウント登録し、ホーム画面に遷移するまでの解説を終了します。

 

最後に

私はここまで理解するのに約2週間かかりました。1つ1つの処理も、処理と処理の関係性もめちゃくちゃ複雑で、「こんなの本当に理解できるのか?」と不安になりながら勉強していたことを覚えています。

 

今のこの解説を書いて思うことは、まず全体の大きな流れを掴んでから、一つ一つの処理について理解するのがもっとも効率な学習方法だということです。

 

今後はその他の処理も大きな流れを解説して、そのあと各処理を深掘りした解説を書こうと思っています。