1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PHP 郵便番号と住所を検索 正規表現

Posted at

#郵便番号か住所で検索

コメント 2020-03-28 222803.png

##内容

郵便番号または都道府県を選択し市町村を入力すると
郵便のデータが検索できます。

10件を超えた場合に”前へ”、”次へ”を押すと各々のページに飛ぶようになっています。

SQL脆弱性があると思いますが、今のところこのまま学習を進めていきます。

// 変数を設定
$post_num ='';//郵便番号
$area ='';//都道府県選択
$city ='';//市町村
$town ='';//県域
$error1 = [];//エラー文
$error2 = [];//エラー文
$user_data = [];
$abc_data = [];
$query = '';
$host = 'localhost';
$username = '';
$passwd = '';
$dbname = '';
$link= mysqli_connect($host, $username, $passwd, $dbname);
$page = 1;
$count = '';//トータル件数
$totalpage = ceil($count/ 10);//切り上げ

##変数が存在するかを確認

//どちらかに値が入っていた場合
if(isset($_GET['post_num']) === true || isset($_GET['area']) === true) {
//変数を代入する
    if(isset($_GET['post_num']) === true) {
        $post_num = $_GET['post_num'];
    }
        if(isset($_GET['area']) === true) {
        $area = $_GET['area'];
    }
        if(isset($_GET['city']) === true) {
        $city = $_GET['city'];
    }
        if(isset($_GET['town']) === true) {
        $town = $_GET['town'];
    }
        if(isset($_GET['page']) === true) {
        $page = $_GET['page'];
    }
if(isset($_GET['post_num']) === true || isset($_GET['area']) === true)

このif文を書かないと空欄の状態でも変数の確認をしてしまうため、
後述のエラー文が出てしまいます

##空白の削除をします

    $post_num = str_replace(array(" "," "),"", $post_num);
    $area = str_replace(array(" "," "),"", $area);
    $town = str_replace(array(" "," "),"", $town);

str_replace(array(半角、全角空白)、空、変数)となっており
変数の中の半角、全角空白を空要素と入れ替えます。つまり、空白があった場合に削除します。

##エラーメッセージ

    if(empty($post_num) === true && 
    ($area === '都道府県を選択' || empty($city) === true)) {
        $error1[] = '郵便番号を入力してください';
    }else if ((preg_match('/^[0-9]{7}$/', $post_num) !== 1) && 
    ($area === '都道府県を選択' || empty($city) === true)) {
        $error1[] = '7桁の数字で入力してください';
    }else {
        print "";
    }

areaとcityの入力がしていない場合でないと条件を付けないと
2つの値が入っているときにもエラー文が出てしまう。

}else if ((preg_match('/^[0-9]{7}$/', $post_num) !== 1) && 
    ($area === '都道府県を選択' || empty($city) === true)) {
        $error1[] = '7桁の数字で入力してください';

preg_match(正規表現、文字列)で文字列が正規表現と一致しているかを
確認する
一致していれば1、していなければ0で、失敗するとfalseを返します。
正規表現は0から9までの値を7桁でとなっている。
なので、post_numが7桁の数字出なかった場合、かつareaまたはcityの
値が空だった場合にエラー文が出るようになる。
  


    if ($area === '都道府県を選択' && 
    (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))) {
        $error2[] = '都道府県を選択してください';
    }
    if(empty($city) === true && 
    (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))){
        $error2[] = '市区町村名をを入力してください';
    }

前述とほぼ同じで、post_numに値が入っている場合にはエラー分が出ないようになっています。

##データベースに接続


        if(count($error1) === 0 || count($error2) === 0) {
        if($link) {
            mysqli_set_charset($link, 'utf8');
            if($post_num !== '') {
                $query = "SELECT post_num, area , city, town FROM pt_table 
                WHERE post_num = '$post_num'";

エラー文がないときに接続します。文字化けを防止でutf8で表記します。
post_numが空ではない場合にsql文を代入します。


WHERE post_num = '$post_num'";

データベースにある郵便番号の値とpost_numが同じ場合になるのが条件。

            } else {
                $limit = 10*$page-10;
                $query = "SELECT post_num, area , city, town FROM pt_table 
                WHERE (area = '$area') AND (city = '$city') LIMIT ".$limit.",10";
 

pageは1番最初のページ数を表しています。 LIMITは開始位置、終わりの位置までを指定。
つまり、10件ごとにページに表示します。

変数limitは0、10、20、30と増えていきます。

                $query = "SELECT post_num, area , city, town FROM pt_table 
                WHERE (area = '$area') AND (city = '$city') LIMIT ".$limit.",10";

データベースのarea,cityの値がそれぞれ一致している場合という条件。
変数limitを”$limit”と書いた場合には文字列となってしまいます。カンマで囲うと数字として扱えます。

##総件数を出すために文字列を取得

                $abc = "SELECT post_num, area , city, town FROM pt_table 
                WHERE (area = '$area') AND (city = '$city')";
                $result = mysqli_query($link, $abc);
                while($row = mysqli_fetch_array($result)) {
                    $abc_data[] = $row;
                }
            } 

まず、変数queryでデータを取得しようとすると最大10件しか取得できません。理由はLIMITを使って10件ずつ取得するプログラムになっているからです。なので、別の実行データを
1行ずつ取得し、文字列にしていきます。

##実行したデータを取得

$result = mysqli_query($link, $query);
          while($row = mysqli_fetch_array($result)) {
          $user_data[] = $row;
          }      

10件ずつ取得するデータを1行ずつ取得し文字列にします。

##メモリを開放しデータベースから閉じる

            mysqli_free_result($result);
            mysqli_close($link);
            
        }else {
            echo 'DB接続失敗';
        }
        
    }

}

##総件数


$count = count($abc_data);

##ページング

    <?php if ($page > 1) { ?>   
      <a href="?page=<?php echo ($page - 1); ?>&area=<?php print $area; ?>
      &city=<?php print $city; ?>">前のページへ</a>
    <?php } ?>
    <?php if ($page < $totalpage) { ?>
      <a href="?page=<?php echo ($page + 1); ?>&area=<?php print $area; ?>
      &city=<?php print $city; ?>">次のページへ</a>
    <?php } ?>

ファイル名?post_num=&area=県名&city=市名とURLに表示させる事を目的にする。
GETで値を取得したときにはURLが表示され、その先頭は?が付きます。
現在のページが1よりも大きいは(page-1)つまり前のページにいきます。

トータルページが今のページよりも多い場合には次のページに行きます

##全コード

<?php
// 変数を設定
$post_num ='';
$area ='';
$city ='';
$town ='';
$error1 = [];
$error2 = [];
$user_data = [];
$abc_data = [];
$query = '';
$host = 'localhost';
$username = 'codecamp31549';
$passwd = 'RXFXXBTL';
$dbname = 'codecamp31549';
$link= mysqli_connect($host, $username, $passwd, $dbname);
$page = 1;
$count = '';//トータル件数
$totalpage = ceil($count/ 10);//切り上げ
/*変数が存在する確認*/ 
if(isset($_GET['post_num']) === true || isset($_GET['area']) === true) {
    if(isset($_GET['post_num']) === true) {
        $post_num = $_GET['post_num'];
    }
        if(isset($_GET['area']) === true) {
        $area = $_GET['area'];
    }
        if(isset($_GET['city']) === true) {
        $city = $_GET['city'];
    }
        if(isset($_GET['town']) === true) {
        $town = $_GET['town'];
    }
        if(isset($_GET['page']) === true) {
        $page = $_GET['page'];
    }
    
/*空白削除*/
    $post_num = str_replace(array(" "," "),"", $post_num);
    $area = str_replace(array(" "," "),"", $area);
    $town = str_replace(array(" "," "),"", $town);

/*エラーメッセージ*/
    if(empty($post_num) === true && 
    ($area === '都道府県を選択' || empty($city) === true)) {
        $error1[] = '郵便番号を入力してください';
    }else if ((preg_match('/^[0-9]{7}$/', $post_num) !== 1) && 
    ($area === '都道府県を選択' || empty($city) === true)) {
        $error1[] = '7桁の数字で入力してください';
    }else {
        print "";
    }
    if ($area === '都道府県を選択' && 
    (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))) {
        $error2[] = '都道府県を選択してください';
    }
    if(empty($city) === true && 
    (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))){
        $error2[] = '市区町村名をを入力してください';
    }
/*データベースに接続*/ 
    
        if(count($error1) === 0 || count($error2) === 0) {
        if($link) {
            mysqli_set_charset($link, 'utf8');
            if($post_num !== '') {
                $query = "SELECT post_num, area , city, town FROM pt_table 
                WHERE post_num = '$post_num'";
                // var_dump($query);
            } else {
                $limit = 10*$page-10;
                $query = "SELECT post_num, area , city, town FROM pt_table 
                WHERE (area = '$area') AND (city = '$city') LIMIT ".$limit.",10";
                $abc = "SELECT post_num, area , city, town FROM pt_table 
                WHERE (area = '$area') AND (city = '$city')";
                $result = mysqli_query($link, $abc);
                while($row = mysqli_fetch_array($result)) {
                    $abc_data[] = $row;
                }
            } 
            // var_dump($query);
                $result = mysqli_query($link, $query);
                while($row = mysqli_fetch_array($result)) {
                    $user_data[] = $row;
                    
                }
            mysqli_free_result($result);
            mysqli_close($link);
            
        }else {
            echo 'DB接続失敗';
        }
        
    }

}

$count = count($abc_data);



        

?>

<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>郵便</title>
</head>
<body>
    <form action="./17-6.php" method="get">
        <h1>郵便番号検索</h1>
        <h2>郵便番号から検索</h2>
        <?php print "総件数" . htmlspecialchars($count,ENT_QUOTES,'UTF-8') . "件";?>
        <input type="search" name="post_num" value="">
        <input type="submit" value="検索">
        <h2>地名から検索</h2>
        <label>都道府県を選択
            <select name="area">
                <option>都道府県を選択</option>
                <option>北海道</option>
                <option>兵庫県</option>
                <option>新潟県</option>
            </select>
        </label>
        <label>市区町村
            <input type="seach" name="city">
            <input type="submit" value="検索">
        </label>
    </form>
    <p><?php foreach($error1 as $key1 => $string1) {
                print htmlspecialchars($string1,ENT_QUOTES,'UTF-8');
            }
    ?></p>
        <p><?php foreach($error2 as $key2 => $string2) {
                print htmlspecialchars($string2,ENT_QUOTES,'UTF-8');;
            }
    ?></p>
        <?php 
    foreach($user_data as $read) {?>
        <table>
           <style type="text/css">
       table, td, th {
           border: solid black 1px;
       }
       table {
           width: 600px;
       }
       tr td {
           width: 150px;
       }
   </style>
    
            <tr>
                <th>郵便番号</th>
                <th>都道府県</th>
                <th>市町村</th>
                <th>町域</th>
            </tr>
            <tr>
                <td><?php print htmlspecialchars($read['post_num'],ENT_QUOTES,'UTF-8'); ?></td>
                <td><?php print htmlspecialchars($read['area'],ENT_QUOTES,'UTF-8'); ?></td>                
                <td><?php print htmlspecialchars($read['city'],ENT_QUOTES,'UTF-8'); ?></td>            
                <td><?php print htmlspecialchars($read['town'],ENT_QUOTES,'UTF-8'); ?></td>            
            </tr>
        </table>
    <?php } ?>  
<p>
    <!--GETを使用するときは?からスタートする-->
    <?php if ($page > 1) : ?>   
      <a href="?page=<?php echo ($page - 1); ?>&area=<?php print $area; ?>
      &city=<?php print $city; ?>">前のページへ</a>
    <?php endif; ?>
    <?php if ($page < $totalpage) : ?>
      <a href="?page=<?php echo ($page + 1); ?>&area=<?php print $area; ?>
      &city=<?php print $city; ?>">次のページへ</a>
    <?php endif; ?>

  </p>    
 
</body>

</html>   

```php


1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?