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

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

ただいまの
回答率

88.79%

入力チェックの際の0の処理について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 679

newyee

score 155

お問合せフォームによる入力チェックの処理を考えていたのですが、0の処理がうまくいかず、ご助言頂きたくご質問させて頂きました。
以下は、お問合せ入力画面の「test1.php」です。

<?php
if(!$_POST){
  $name = '';
  $age = '';
  $age_err = '';
}

?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <style>
    .red{
      color:red
    }
  </style>
<script type="text/javascript"> 

function check(){

    if(window.confirm('送信してよろしいですか?')){ // 確認ダイアログを表示

        return true; // 「OK」時は送信を実行

    }
    else{ // 「キャンセル」時の処理


        return false; // 送信を中止

    }

}


</script>
</head>
<body>
  <h1 class="red">お問合せ画面</h1>
  <h2>お問合せ内容を入力してください</h2>
  <form action="test2.php" method="post" onSubmit="return check()">
    <p>(必須)名前<input type="text" name="name" value="<?php if($name){echo $name;}else{echo '';} ?>"></p>
    <span class="red">
      <?php if(!empty($name_err)): ?>
        <?=$name_err?>
      <?php endif;?>    
    </span>

    <p>(必須)年齢<input type="text" name="age" size="2" value="<?php if($age){echo $age;}else{echo '';}?>"></p>
    <span class="red">
    <?php if(!empty($$age_err)): ?>
        <?=$age_err?>
    <?php endif;?>

    </span>
    <p>好きな色
    <input type="checkbox" name="color[]" value="赤"><input type="checkbox" name="color[]" value="緑"><input type="checkbox" name="color[]" value="青"></p>

    <input type="submit" value="送信">

  </form>
</body>
</html>


以下は、入力フォームより送られた値の入力チェックを行う、test2.phpです。

<?php
// $name = '';
// $age = '';
if($_POST){

  $color = '';
  $name = filter_input(INPUT_POST,'name');
  $age = filter_input(INPUT_POST,'age');


  //if(count($_POST['color']) > 1){
  if(!empty($_POST['color'])){
    $color = implode(',',$_POST['color']);

  }  
  //var_dump($color);
  //}
  var_dump($age);

  if(!$name){
    $name_err = '名前を入力してください';
  }

  if(!empty($age)){
    //全角を半角に
    $age = mb_convert_kana($age,"a");
    //半角または全角のハイフンは取り除く
    // $age = mb_ereg_replace("-", "", $age);
    // $age = mb_ereg_replace("ー", "", $age);
    // $age = mb_ereg_replace("-", "", $age);
      //var_dump($age);

      if(!ctype_digit($age)){
        $age_err = '年齢は整数を入力してください';
      }
      echo __LINE__;

  }else{

  $age_err = '年齢を入力してください';

}




//var_dump($err);


  if(!empty($name_err) || !empty($age_err)){
    include 'test1.php';
  }else{ ?>

    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="UTF-8">
      <style>
        .red{
          color:red;
        }
      </style>
    </head>
    <body>
      <h1 class="red">お問合せ完了画面</h1>
      <h2>送信しました</h2>
      <table border="1">
        <tr>
          <td>名前</td>
          <td><?= $name?></td>
        </tr>
        <tr>
          <td>年齢</td>
          <td><?=$age?></td>
        </tr>
        <tr>
          <td>好きな色</td>
          <td>
            <?php
               if($color){
                echo $color;    
              }
             ?>
          </td>
        </tr>
      </table>
    </body>
    </html>

<?php 
  } 
} 

?>


「test1.php」の名前入力欄及び、年齢入力欄に「0」を入力すると、以下の画像のようになります。
イメージ説明

名前の欄には、0と表示されずエラーメッセージが表示され、年齢の欄には、

<p>(必須)年齢<input type="text" name="age" size="2" value="<?php if($age){echo $age;}else{echo '';}?>">歳</p>


ここで入力保持の為、設定した$ageが表示されません。
上記問題を解決するには、どのようにすれば良いでしょうか?
追記です。
「0」のチェックを解決したコードを作り直してみましたので、下記に追加しておきます。
下記は、お問合せ入力画面の「inquiry_form.php」です

<?php
  session_start();

  $err = [];
  if(!empty($_POST)){
    $name = filter_input(INPUT_POST,'name');
    $age = (string)filter_input(INPUT_POST,'age');
    $color = filter_input(INPUT_POST,'color', FILTER_DEFAULT,FILTER_REQUIRE_ARRAY);
    //全角を半角にし、空白を削除
    $name = str_replace([' ',' '], '', mb_convert_kana($name, 'a', 'UTF-8'));
    $age = str_replace([' ',' '], '', mb_convert_kana($age, 'a', 'UTF-8'));
    var_dump($age);
    if(!strlen($name) > 0){

      $name_err = '必須項目です'; 
      echo __LINE__ . PHP_EOL;
    }else{
      echo __LINE__ . PHP_EOL;

    }

    if(empty($name_err)){
      $_SESSION['name'] = $name;
    }

    if(strlen($age) > 0){
      echo __LINE__;

      if(!ctype_digit($age)){
        var_dump($age);

        $age_err = '年齢は整数を入力してください';
        var_dump($age);
        echo __LINE__ . PHP_EOL;
      }else{
        var_dump($age);
        echo __LINE__ . PHP_EOL;
      }
    }else{
      $age_err = '必須項目です';
      echo __LINE__;
    }

    // var_dump($name_err);
    // var_dump($age_err);
    // exit();
    if(empty($age_err)){
      $_SESSION['age'] = $age;
    }

    // var_dump($age);
    // var_dump($age_err);
    // exit();

    if($color){
      $color = implode('、',$color);
      echo __LINE__ . PHP_EOL;
    }else{
      $color = array();
      $color = '';
      //echo __LINE__ . PHP_EOL;
    }

    $_SESSION['color'] = $color;

    if(empty($name_err) && empty($age_err)){
        header('Location:complete.php');
        exit();
        echo 'OK';
        echo __LINE__;
    }
    // var_dump($name_err);
    // var_dump($age_err);
    // exit();


  }

?>



<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>お問合せ</title>
</head>
<body>
  <h1 style="color:red">お問合せ画面</h1>
  <p>お問合せ内容を入力してください。</p>
  <form id="input_form" action="inquiry_form.php" method="post">
    <p>
      (必須)名前<input type="text" name="name" value="<?php echo isset($name) ? $name : ''; ?>">
        <span style="color:red"><?php echo isset($name_err) ? $name_err : ''; ?></span><br>
      (必須)年齢<input type="text" name="age" size="5" value="<?php echo isset($age) ? $age : '';?>">歳
      <span style="color:red"><?php echo isset($age_err) ? $age_err : ''; ?></span><br>

      好きな色&emsp;<input type="checkbox" name="color[]" value="赤">赤
              <input type="checkbox" name="color[]" value="緑">緑
              <input type="checkbox" name="color[]" value="青">青
      </p>
    <input type="submit" value="送信">
  </form>
  <script>
    document.addEventListener('DOMContentLoaded',function(){
      document.getElementById('input_form').addEventListener('submit',function(e){
        if(!window.confirm('ページを送信しても良いですか?')){
          e.preventDefault();
        }
      },false)
    },false);
  </script>
</body>
</html>


下記は、完了画面の「complete.php」です

<?php
session_start();
?>

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title> お問合せ完了</title>
</head>
<body>
  <h1 style="color:red">お問合せ 完了画面</h1>
  <h3>送信しました</h3>
  <table border="1" >
    <tr>
      <td>名前</td>
      <td><?php echo $_SESSION['name']; ?></td>
    </tr>
    <tr>
      <td>年齢</td>
      <td><?php echo $_SESSION['age']; ?>歳</td>
    </tr>
    <tr>
      <td>好きな色</td>
      <td><?php echo $_SESSION['color']; ?></td>
    </tr>
  </table>
</body>
</html>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+2

0はfalseだから、です。
論理型 (boolean) 

 boolean に変換する場合、次の値は FALSE とみなされます。
boolean の FALSE
integer の 0 (ゼロ)
float の 0.0 (ゼロ)
空の文字列、 および文字列の "0"
要素の数がゼロである 配列
特別な値 NULL (値がセットされていない変数を含む)
空のタグから作成された SimpleXML オブジェクト

三項演算子を使わないのでしたら1行に詰め込むのではなく丁寧に書いたほうが良いです。

それにfilter_input()使うのなら$_POSTで確認する必要もない。
なぜなら送信されてなかったらnullだから。
分岐によって別の画面をincludeするのであればなおさら$_POSTは不要です。

colorだけ$_POSTから取り出すのも意味がないです。filter_input()でnullかどうかを確認してimplode()すれば良い話で。

分岐でようやくセットされる変数の初期化処理がコメントアウトされているのも謎ですね。

echo書いたり<?=とshort tag使っていたり、コーディングに統一性がないのもよろしくない。

入力値の出力にHTMLエスケープが施されてないですね。


入力画面includeを生かして適当に組みなおしたコード
適当に役割分担。Validationのところとか入力フォーム表示とかClassでやったほうがそれっぽい感じになるので望ましい。(今回の内容だけでもオレオレフレームワーク一歩手前)

返り値の型宣言とか使ってるのでPHP7以上でのみ動作可能

helper.php

<?php
//二重定義阻止
if(!function_exists('h')){
    function h($str)
    {
        return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
    }

}
if(!function_exists('ak')){
    function ak($key,array $array):bool
    {
        return array_key_exists($key,$array);
    }
}
if(!function_exists('iar')){
    function iar($key,array $array):bool
    {
        return in_array($key,$array);
    }
}

input_config.php

<?php
return [
    'name'=>[
        'label'=>'名前',
        'type'=>'text',
        'required'=>true,
        'validation'=>'required'
    ],
    'age'=>[
        'label'=>'年齢',
        'type'=>'text',
        'required'=>true,
        'validation'=>'required|number'
    ],
    'color'=>[
        'label'=>'好きな色',
        'type'=>'checkbox',
        'select'=>['赤','緑','青']
    ],
];

validation.php

<?php
function validation():array
{
    $input_config = require_once 'input_config.php';

    $err = [];
    foreach($input_config as $input_name=>$setting){
        if(ak('validation',$setting)){
            $vali = explode('|',$setting['validation']);
            foreach($vali as $checktype){
                $check_name = $checktype.'Check';
                $res = false;
                if(function_exists($check_name)){
                    switch($checktype){
                        default:
                            $res = $check_name(filter_input(INPUT_POST, $input_name),$setting['label']);
                    }
                    if($res){
                        $err[$input_name][] = $res;
                    }
                }
            }
        }
    }

    return $err;
}

function requiredCheck(string $value,string $name)
{
    if(trim($value) === ''){
        return $name.'を入力してください';
    }
    return false;
}
function numberCheck(string $value,string $name)
{
    if(!empty($value) && !(ctype_digit($value))){
        return $name.'は整数を入力してください';
    }
    return false;
}

test1.php

<?php
require 'helper.php';
$input_config = require 'input_config.php';
if(!isset($err)){
    $err = [];
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>入力</title>
<style>
h1 {
    color: #f00
}
.error {
    color: #f00
}
</style>
<script>
function check(){
    if(!confirm('送信してよろしいですか?')){
        return false;
    }
}
</script>
</head>
<body>
    <h1>お問合せ画面</h1>
    <h2>お問合せ内容を入力してください</h2>
    <form action="test2.php" method="post" onSubmit="return check()">
    <?php
    foreach($input_config as $input_name=>$setting){
        echo '<p>';
        if(ak('required',$setting) && $setting['required']){
            echo '(必須)';
        }
        echo $setting['label'];
        switch($setting['type']){
            case 'text':
                $input_data = filter_input(INPUT_POST,$input_name);
                echo '<input name="'.$input_name.'" value="'.h($input_data).'">';
                break;
            case 'checkbox':
                $input_data = filter_input(INPUT_POST,$input_name, FILTER_DEFAULT, [
                   'flags' => FILTER_REQUIRE_ARRAY
                ]);
                if(ak('select',$setting) && is_array($setting['select'])){
                    if(is_null($input_data)){
                        $input_data = [];
                    }
                    foreach($setting['select'] as $in=>$val){
                        echo '<input type="checkbox" name="'.$input_name.'[]" value="'.$in.'"'.(iar($in,$input_data)?' checked':'').'>'.$val.'&nbsp;';
                    }
                }
                break;
        }
        echo '</p>';
        if(ak($input_name,$err)){
            echo '<span class="error">'.implode('<br />',$err[$input_name]).'</span>';
        }
    }
    ?>
    <input type="submit" value="送信">
    </form>
</body>
</html>
<?php
exit();

test2.php

<?php
if($_SERVER['REQUEST_METHOD'] !== 'POST'){
    require_once 'test1.php';
}
require 'helper.php';
require_once 'validation.php';

$err = validation();

if (count($err) > 0) {
    require_once 'test1.php';
}
$input_config = require 'input_config.php';
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>送信</title>
</head>
<body>
    <h1 class="red">お問合せ完了画面</h1>
    <h2>送信しました</h2>
    <table border="1">

    <?php
    foreach($input_config as $input_name=>$setting){
        echo '<tr>';
        echo '<td>'.$setting['label'].'</td>';
        echo '<td>';
        switch($setting['type']){
            case 'text':
                $input_data = filter_input(INPUT_POST,$input_name);
                echo h($input_data);
                break;
            case 'checkbox':
                $input_data = filter_input(INPUT_POST,$input_name, FILTER_DEFAULT, [
                   'flags' => FILTER_REQUIRE_ARRAY
                ]);
                if(ak('select',$setting) && is_array($setting['select'])){
                    if(is_null($input_data)){
                        $input_data = [];
                    }
                    foreach($setting['select'] as $in=>$val){
                        if(iar($in,$input_data)){
                            echo $val.'&nbsp';
                        }
                    }
                }
                break;
        }
        echo '</td>';
        echo '</tr>';
    }
    ?>
    </table>
</body>
</html>
<?php
exit();

includeでの別画面表示をいかしたためにhelperで二重定義防止をしていますが
ビューファイルはやはり1画面1つにしたほうがいいと思う。

入力チェック後入力画面をそのまま入力値を初期値で表示させるなら入力チェックは自画面で行ったほうが良いと思います。
リダイレクトするとか、リダイレクトが嫌ならJavaScriptでするとか、サーバーサイドでチェックしたいならAjaxでするとか、方法は幾らでもあります。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/10 16:26

    セッションは適切に管理(削除・編集・解放)しないとバグのもとになりますのでご注意を。
    あれも元を辿ればテキストデータなので。

    キャンセル

  • 2019/05/10 16:28

    分かりました。セッションの扱いには、注意したいと思います

    キャンセル

  • 2019/05/10 16:39

    一応、セッションファイルの生成や中の状態など、確認してみると良いかもしれません。
    (というか現在のコードでも「用事が済んだら削除」してなので残りっぱなしになりそうな気がしますが)

    キャンセル

+2

ミニマルなテストコードを書いて試そう。

<?php

$arr = [0, '0', '00'];
foreach ($arr as $val) {
    if ($val) {
        echo 'TRUE' . PHP_EOL;
    }
    else {
        echo 'FALSE' . PHP_EOL;
    }
}


結果
イメージ説明

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/01 12:10

    ご回答ありがとうございます。
    そうですね。今後はできるだけミニマムコードで、検証していこうと思います。

    キャンセル

checkベストアンサー

+1

if(!$name){if($age){echo $age;}else{echo '';}は0をif文で評価するとずっとfalseだからエラーになってしまうのじゃないでしょうか?
strlenメソッドで分岐させるといいと思います!

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/01 12:24

    strlenをまさか使用して、「0」の問題を解決するというのは自分には思いつきませんでしたので、助かりました。

    キャンセル

  • 2019/05/01 12:24

    ありがとうございました。

    キャンセル

  • 2019/05/01 12:35

    それは良かったです!!
    条件分岐をもう少し簡単にできそうなのでいろいろ改善してみると良いかもしれません!

    キャンセル

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

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

関連した質問

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