質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.95%

会員登録フォームの制作においてページ遷移の判定がうまくできない

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,906

score 403

下記コードは制作中のものの一部ですが、会員登録フォームを制作しています。
2つの入力フィールドに入力したアドレスが異なっていた場合
・配列に何かしらの文字(ここではerror)を代入
・それと同時にエラー文を作っておく

異なっていた場合はEmail::equal()でエラー文を表示させる

異なっていなければ
sessionにPOST内容を記録させて
header('Location: register1.php');で
次のページに遷移する。

<?php
class Email{
    function equal(){
        $email1 = filter_input(INPUT_POST, 'email1');
        $email2 = filter_input(INPUT_POST, 'email2');
        if(isset($email1,$email2)){
            if($email1 !== $email2 ){
                $error['mailequal'] = "error";
                $errorms = '<div class="r_em">' . "メールアドレスが一致しません" . '</div>' ;
                return $errorms;
            }
        }
    }
}

if(!empty($_POST)){
    if($error['mailequal'] !== "error"){
        $_SESSION['join'] = $_POST;
        header('Location: register1.php');
        exit();
    }
}
?>


<tr>
    <td>E-mail</td>
    <td colspan="2"><input type="email" name="email1" maxlength="50" size="46" placeholder="info@example.com" ></td>
</tr>
<tr>
    <td>E-mail (確認用)</td>
    <td colspan="2"><input type="email" name="email2" maxlength="50" size="46" placeholder="info@example.com" ></td>
    <td><?php echo Email::equal(); ?></td>
</tr>

なのですが、ページ遷移のところでてこずっています。
異ならないアドレスで試してもページ遷移してしまうのですが、どうしたら良いでしょうか...?

多分、問題は外部からクラスへのアクセス方法になっているとおもいます。
$error['mailequal']をクラス外で使っているので未定義の変数を呼び出していることになって判定がうまくできないのだと思います。(違っていたら申し訳ない)

エラー文の表示では、クラスはインスタン化せずに::で使てますが
クラスのプロパティ(変数?)にアクセスする方法が分かれば...

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

とりあえず元のイメージを維持した形で書きました。
通常なら、Validate クラスでまとめるほうが無難だと思います。

<?php

class Email
{

    /**
     * エラーメッセージ
     * 複数のエラーメッセージを格納できるように配列に
     *
     * @var array
     */
    private $error = array();

    /**
     * メールアドレスの入力チェック
     * @return bool
     */
    public function check()
    {
        if (is_null(filter_input_array(INPUT_POST))) {
            return true;
        }
        $email = filter_input(INPUT_POST, 'email');
        $email_conf = filter_input(INPUT_POST, 'email_conf');

        if ($email !== $email_conf) {
            $this->error[] = 'メールアドレスが一致しません。';
            return false;
        }
        return true;
    }

    /**
     * エラーメッセージを取得する
     * @return array
     */
    public function getErrorMessage()
    {
        return $this->error;
    }

}

$objEmail = new Email();

if (!$objEmail->check()) {
    $errMsg = implode(',', $objEmail->getErrorMessage());
}
?><!DOCTYPE HTML>
<html lang="">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form action="" method="post">
            <table>
                <tr>
                    <td>E-mail</td>
                    <td><input type="post" name="email" /></td>
                </tr>
                <tr>
                    <td>E-mail (確認用)</td>
                    <td><input type="post" name="email_conf" /></td>
                </tr>
                <tr>
                    <td></td>
                    <td><button>送信</button></td>
                </tr>
            </table>
            <?php
            if (isset($errMsg)) {
                printf('<p>%s</p>', $errMsg);
            }
            ?>
        </form>
    </body>
</html>
<?php

function h($str)
{
    return htmlspecialchars($str, ENT_QUOTES, 'utf-8');
}

class Validate
{

    /**
     * エラーメッセージ
     * 複数のエラーメッセージを格納できるように配列に
     *
     * @var array
     */
    private $error = array();

    public function required()
    {
        if (is_null(filter_input_array(INPUT_POST))) {
            return $this;
        }
        $email = filter_input(INPUT_POST, 'email');
        $email_conf = filter_input(INPUT_POST, 'email_conf');

        if (empty($email)) {
            $this->error[] = 'E-mail は入力必須です。';
        }
        if (empty($email_conf)) {
            $this->error[] = 'E-mail(確認用) は入力必須です。';
        }
        return $this;
    }

    /**
     * メールアドレスの確認用との一致
     * @return \Validate
     */
    public function isEqual()
    {
        if (is_null(filter_input_array(INPUT_POST))) {
            return $this;
        }
        $email = filter_input(INPUT_POST, 'email');
        $email_conf = filter_input(INPUT_POST, 'email_conf');

        if ($email !== $email_conf) {
            $this->error[] = 'メールアドレスが一致しません。';
        }
        return $this;
    }

    /**
     * 登録済みかどうか
     * @return \Validate
     */
    public function isRegisterd()
    {
        if (is_null(filter_input_array(INPUT_POST))) {
            return $this;
        }

        $email = filter_input(INPUT_POST, 'email');

        // DB への問い合わせ
        //
        // この辺の処理は自分で書いてね
        //
        if (false) {
            $this->error[] = '既に登録済みです。';
        }
        return $this;
    }

    /**
     * バリデート結果
     * @return boolean
     */
    public function check()
    {
        if (count($this->error)) {
            return false;
        }
        return true;
    }

    /**
     * エラーメッセージを取得する
     * @return array
     */
    public function getErrorMessage()
    {
        return $this->error;
    }

}

$objValidate = new Validate();
$objValidate->required()
    ->isEqual()
    ->isRegisterd();
if (!$objValidate->check()) {
    $errMsg = $objValidate->getErrorMessage();
} else {
    // 成功時にページ遷移
    if (!is_null(filter_input_array(INPUT_POST))) {
        header('Location: success.php');
    }
}
?><!DOCTYPE HTML>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form action="" method="post">
            <table>
                <tr>
                    <td>E-mail</td>
                    <td><input type="post" name="email" value="<?php echo h(filter_input(INPUT_POST, 'email')); ?>" /></td>
                </tr>
                <tr>
                    <td>E-mail (確認用)</td>
                    <td><input type="post" name="email_conf" value="<?php echo h(filter_input(INPUT_POST, 'email_conf')); ?>" /></td>
                </tr>
                <tr>
                    <td></td>
                    <td><button>送信</button></td>
                </tr>
            </table>
            <?php
            if (isset($errMsg)) {
                foreach ($errMsg as $msg) {
                    printf('<p>%s</p>', $msg);
                }
            }
            ?>
        </form>
    </body>
</html>

コメントへの回答

① $error[] とすると、function required() { } の中からだけがその変数へアクセスできるため、外からアクセスできません。なので他のメソッドからもアクセスできるクラスのプロパティに値を守らせることが目的です。

②この処理がないと、POSTされていない時も、そのあとの処理が実行されてしまいます。POSTしていない時は処理する必要がないので、処理を止めるために記述しています。

③他のメソッドの結果を利用せず、単独のメソッドだけで処理することが可能なら static で定義すればいいでしょう。 Validate クラスで 提示した例では、3つのチェックを行っています。それぞれ同時にチェックして、一度にエラーメッセージを出力するために、インスタンスを同一のものに保障しなければなりませんので、new して使う方法にしました。
static で実装する方法もありますが、シングルトンパターンの利用してインスタンスの同一性を担保することというアプローチが必要になります。失礼ながら質問者様にはまだ早計かと思い、このパターンでの実装は見送りました。

でも今試しに、private $error = array();を消して試してみたら
'メールアドレスが一致しません。がしっかり表示されています。

確かに省略した場合でも、表示はされますね。

ただし、その場合、$this->error は public となり、private 変数にはなりません。
privateで定義する意味は、あくまで $this->error の値を書き換えることができるのは、そのクラスの中からのみ可能とするためです。そうすることでアプリケーションの保守性やバグの注入を防ぐ意味があります。

もし、意図しないバグがあっても、Validate クラスの内部をチェックすれば良いことになるため、プログラムの保守性も上がるはずです。

public にしてしまうと、クラスの外から値を書き換えることが可能になってしまいます。

 ⑤を検証するためのサンプルコード

以下のようなコードを実際に書いて、検証してみましょう。

<?php

class Test
{

    /**
     * private プロパティ
     */
    private $private = 'private';

    /**
     * protected プロパティ
     */
    protected $protected = 'protected';

    /**
     * public プロパティ
     */
    public $public = 'public';

    /**
     * private_method
     */
    private function private_method()
    {
        // この変数にアクセスできるのは、private_method()の中からだけ
        // protected_method, public_method からはアクセスできない
        $private_var = 'private_var';

        // プロパティにアクセス
        $this->private = 'private_method で書き換えました';
        $this->protected = 'private_method で書き換えました';
        $this->public = 'private_method で書き換えました';

        return array(
            'private_var' => $private_var
            , 'private' => $this->private
            , 'protected' => $this->protected
            , 'public' => $this->public
        );
    }

    /**
     * protected_method
     */
    protected function protected_method()
    {
        // プロパティにアクセス
        $this->private = 'protected_method で書き換えました';
        $this->protected = 'protected_method で書き換えました';
        $this->public = 'protected_method で書き換えました';

        return array(
            'private' => $this->private
            , 'protected' => $this->protected
            , 'public' => $this->public
        );
    }

    /**
     * public_method
     */
    public function public_method()
    {
        // プロパティにアクセス
        $this->private = 'public_method で書き換えました';
        $this->protected = 'public_method で書き換えました';
        $this->public = 'public_method で書き換えました';

        return array(
            'private' => $this->private
            , 'protected' => $this->protected
            , 'public' => $this->public
        );
    }

}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/14 03:27

    もういい加減「エラーが出ています」なんていう曖昧な表現はやめませんかね。エラーメッセージをのものを記述してくださいよ。

    キャンセル

  • 2016/06/14 03:29

    すいません!
    何かがおかしかったようで、できました。

    キャンセル

  • 2016/06/14 05:30

    うーん。var_dump() という関数はご存知です?

    キャンセル

0

外してたらごめんなさいですが、呼び出しシーケンスを再考されてはどうでしょうか。

  1. ブラウザからPHPが呼び出される
  2. if(!empty($_POST))が評価される。emptyなので何もしない
  3. htmlが出力される。その際にEmail::equal()が評価され表示される
  4. 一旦プログラム終了。$SESSION以外の変数は消える
  5. ブラウザからformに内容を入れてPHPが呼び出される
  6. if(!empty($_POST))が評価される。!empty($POST)だが$errorは未定義

ということでサーバ側作業とクライアント(ブラウザ側)作業を切り分けて、
シーケンス図のように遷移が解る図を書いてみると良いのではと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

equal()がstatic宣言されていないことが問題なのでは?

class Email{
public static function equal(){

何もreturnしないで抜けるパスがあるので、最後に
return "";
とかを入れた方がいいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/09 12:41

    こっちの方が正解っぽいです。自分曲解してました。

    キャンセル

  • 2016/06/09 23:12

    試しにmethodにstaticを付けてクラス外から$error['mailequal'] にアクセスしようとしているのですができません...

    class Email{
    static function equal(){
    $email1 = filter_input(INPUT_POST, 'email1');
    $email2 = filter_input(INPUT_POST, 'email2');
    if(isset($email1,$email2)){
    if($email1 !== $email2 ){
    $error['mailequal'] = "error";
    $errorms = '<div class="r_em">' . "メールアドレスが一致しません" . '</div>' ;
    return $errorms;
    }
    }
    }
    }

    echo $error['mailequal'] ;

    キャンセル

  • 2016/06/09 23:40

    クラス内のメソッド内の変数にはクラス外からアクセスできません。VBじゃないので。「変数のスコープ」を調べてみてください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.95%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る