PHPで問い合わせフォームシステムを作成する ~ 問い合わせフォームで入力内容をメールで送信(BOT対策用画像認証付)

PHPで問い合わせフォームシステムを作成する ~ 問い合わせフォームで入力内容をメールで送信(BOT対策用画像認証付)

PHPでBOT対策用の画像認証付の「お問い合わせフォーム」(お問い合わせ内容を管理者へメールで送信する)システムを作成します。
データベースに登録したい場合は、ソースコードにあるコメントを参照してください。

実行画面

実行サンプルのサイトを開く

(準備)IPAフォントのダウンロード

BOT対策用画像認証でTrue-Typeフォントが必要なので以下のIPAのサイトからダウンロードします。
https://moji.or.jp/ipafont/ipaex00401/
から「IPAexゴシック(Ver.004.01) ipaexg00401.zip(4.0MB)」をダウンロードしてください。
(「IPAフォントライセンス」の内容に同意してください)

ダウンロードした「ipaexg00401.zip」を解凍します。
必要なファイルは 「ipaexg.ttf」だけで、
以下で作成する「inquiry.php」ファイルと同じフォルダ内に配置する必要があります。

「inquiry.php」のソースコード

以下ソースコードをファイル名「inquiry.php」で文字コード「UTF-8」で保存してください。
<?php
/* 内部文字エンコーディングをUTF-8に設定 */
mb_language("Japanese");
mb_internal_encoding("UTF-8");
session_start();

class TInquiry{
  //↓以下は必ず設定
  const title="お問い合わせフォーム";  //タイトル
  const footer="Copyright 2022 mam";   //フッター文字列
  const adminMailTo="hoge@hoge.jp"; //問い合わせ内容がこのアドレスに飛ぶ。複数の場合はカンマ(,)区切り
  const adminMailFrom="from@hoge.jp";  //Fromメールアドレス
  const privacy_policy_url="/privacy/";//個人情報取得なのでプライバシーポリシーのURLを設定する
  //↑設定ここまで

  public $prefarr=[
    "選択してください",
    "北海道","青森県","岩手県","宮城県","秋田県","山形県","福島県",
    "茨城県","栃木県","群馬県","埼玉県","千葉県","東京都","神奈川県",
    "新潟県","富山県","石川県","福井県","山梨県","長野県","岐阜県","静岡県","愛知県",
    "三重県","滋賀県","京都府","大阪府","兵庫県","奈良県","和歌山県",
    "鳥取県","島根県","岡山県","広島県","山口県",
    "徳島県","香川県","愛媛県","高知県",
    "福岡県","佐賀県","長崎県","熊本県","大分県","宮崎県","鹿児島県","沖縄県",
  ];
  private $inp=[];//POST値を入れる
  public $err=[]; //エラー値を入れる
  function __construct(){
    //POSTの値
    //  $this->inp["order"] 状態
    //  $this->inp["zip"] 郵便
    //  $this->inp["add0"] 都道府県
    //  $this->inp["add1"]~$this->inp["add3"]   住所
    //  $this->inp["name1"],$this->inp["name2"]  姓名
    //  $this->inp["kana1"],$this->inp["kana2"]   カナ姓名
    //  $this->inp["gender"] 性別
    // $this->inp["tel"],$this->inp["mail"],$this->inp["inquiry"]
    $this->inp["title"]=$this::title;
    $this->inp["footer"]=$this::footer;
    $this->inp["privacy"]=$this::privacy_policy_url;
    $this->inp["pref"]=$this->prefarr;
    //画面遷移の値
    if(isset($_SESSION["comp"]) && $_SESSION["comp"]=="comp"){
        $this->inp["order"]="comp";   //登録完了
    }else if(isset($_POST["order"])){
      if($_POST["order"]=="post"){
        $this->inp["order"]="post";//送信
      }else{
        $this->inp["order"]="input";  //入力画面
      }
    }else{
      $this->inp["order"]="input";    //入力画面
    }

    $this->inp["zip"]=""; $this->inp["add0"]=0;
    $this->inp["add1"]=""; $this->inp["add2"]=""; $this->inp["add3"]="";
    $this->inp["name1"]=""; $this->inp["name2"]="";
    $this->inp["kana1"]=""; $this->inp["kana2"]=""; $this->inp["gender"]=0;
    $this->inp["tel"]=""; $this->inp["mail"]="";
    $this->inp["inquiry"]="";
    $this->inp["auth"]="";
    foreach($this->inp as $key=>$val){
      $this->err[$key]="";
    }

    if($this->inp["order"]=="post"){
      //入力チェック
      if(isset($_POST["zip"])){
        $this->inp["zip"]=$_POST["zip"];
        if(!preg_match('/^[0-9]{7}$/',$this->inp["zip"])){
        $this->err["zip"]="郵便番号は数字7桁で入力してください";
        }
      }else{
        $this->err["zip"]="郵便番号を入力してください";
      }
      if(isset($_POST["add0"])){
        $this->inp["add0"]=intval($_POST["add0"]);
        if($this->inp["add0"]<1 || $this->inp["add0"]>47){
        $this->err["add0"]="都道府県を選択してください";
        }
      }else{
        $this->err["add0"]="都道府県選択が不正です";
      }
      if(isset($_POST["add1"])){
        $this->inp["add1"]=$this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["add1"]));
      }
      if(empty($this->inp["add1"])){
        $this->err["add1"]="入力必須です";
      }else if(mb_strlen($this->inp["add1"])>30){
        $this->err["add1"]="30文字を超えています";
      }
      if(isset($_POST["add2"])){
        $this->inp["add2"]=$this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["add2"]));
      }
      if(empty($this->inp["add2"])){
        $this->err["add2"]="入力必須です";
      }else if(mb_strlen($this->inp["add2"])>30){
        $this->err["add2"]="30文字を超えています";
      }
      if(isset($_POST["add3"])){
        $this->inp["add3"]=$this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["add3"]));
      }
      if(mb_strlen($this->inp["add3"])>30){
        $this->err["add3"]="30文字を超えています";
      }
      if(isset($_POST["name1"])){
        $this->inp["name1"]=$this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["name1"]));
      }
      if(empty($this->inp["name1"])){
        $this->err["name1"]="入力必須です";
      }else if(mb_strlen($this->inp["name1"])>10){
        $this->err["name1"]="10文字を超えています";
      }
      if(isset($_POST["name2"])){
        $this->inp["name2"]=$this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["name2"]));
      }
      if(empty($this->inp["name2"])){
        $this->err["name2"]="入力必須です";
      }else if(mb_strlen($this->inp["name1"])>10){
        $this->err["name2"]="10文字を超えています";
      }
      if(isset($_POST["kana1"])){
        $this->inp["kana1"]=mb_convert_kana($this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["kana1"])),"RNVKC");
      }
      if(empty($this->inp["kana1"])){
        $this->err["kana1"]="入力必須です";
      }else if(mb_strlen($this->inp["kana1"])>12){
        $this->err["kana1"]="12文字を超えています";
      }else if(!preg_match("/^[ァ-ヶー]+$/u",$this->inp["kana1"])){
        $this->err["kana1"]="カタカナ以外の文字が含まれています";
      }
      if(isset($_POST["kana2"])){
        $this->inp["kana2"]=mb_convert_kana($this->mbtrim(mb_ereg_replace("\r\n|\r|\n",'',$_POST["kana2"])),"RNVKC");
      }
      if(empty($this->inp["kana2"])){
        $this->err["kana2"]="入力必須です";
      }else if(mb_strlen($this->inp["kana2"])>12){
        $this->err["kana2"]="12文字を超えています";
      }else if(!preg_match("/^[ァ-ヶー]+$/u",$this->inp["kana2"])){
        $this->err["kana2"]="カタカナ以外の文字が含まれています";
      }
      if(isset($_POST["gender"])){
        $this->inp["gender"]=$_POST["gender"];
      }
      if(empty($this->inp["gender"])){
        $this->err["gender"]="選択してください";
      }else if(!preg_match('/^[1-4]{1}$/',$this->inp["gender"])){
        $this->err["gender"]="選択してください";
      }
      if(isset($_POST["tel"])){
        $this->inp["tel"]=mb_convert_kana($this->mbtrim(mb_ereg_replace("\r\n|\r|\n|\\s",'',$_POST["tel"])),"askh");
      }
      if(empty($this->inp["tel"])){
        $this->err["tel"]="入力必須です";
      }else if(!preg_match('/^[0-9]{10,11}$/',$this->inp["tel"])){
        $this->err["tel"]="ハイフン無し数字で10~11桁で入力してください";
      }
      if(isset($_POST["mail"])){
        $this->inp["mail"]=mb_convert_kana($this->mbtrim(mb_ereg_replace("\r\n|\r|\n|\\s",'',$_POST["mail"])),"askh");
      }
      if(empty($this->inp["mail"])){
        $this->err["mail"]="入力必須です";
      }else if(
        !preg_match(
          '/^[a-zA-Z0-9_+-]+(.[a-zA-Z0-9_+-]+)*@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/',
          $this->inp["mail"]
        )
      ){
        $this->err["mail"]="メールアドレスが不正です";
      }else if(mb_strlen($this->inp["mail"])>50){
        $this->err["mail"]="メールアドレスが長すぎます";
      }
      if(isset($_POST["inquiry"])){
        $this->inp["inquiry"]=$this->mbtrim($_POST["inquiry"]);
      }
      if(empty($this->inp["inquiry"])){
        $this->err["inquiry"]="ご質問を入力してください";
      }else if(mb_strlen($this->inp["inquiry"])>500){
        $this->err["inquiry"]="500文字を超えています";
      }
      if(isset($_POST["auth"])){
        $this->inp["auth"]=$_POST["auth"];
      }
      if(!isset($_SESSION["auth"])){
        $this->err["auth"]="画像認証が不正です";
      }else if(empty($this->inp["auth"])){
        $this->err["auth"]="画像認証を入力してください";
      }else if($this->inp["auth"]!=$_SESSION["auth"]){
        $this->err["auth"]="画像認証が誤っています";
      }
      $errflag=false;
      foreach($this->err as $key=>$val){
        if(!empty($val)){
          $errflag=true;
          break;
        }
      }
      if($errflag){
        $this->inp["order"]="input";
      }
    }
    $this->inp["err"]=$this->err;
    //入力画面の場合
    if($this->inp["order"]==="input"){
      [$auth_char,$auth_img]=getCharImg();
      //POST後URLで入力値とPOST値を比較して認証する
      $_SESSION["auth"]=$auth_char;
      $this->inp["authimg"]=$auth_img;
      showInput($this->inp);
      exit;
    }else if($this->inp["order"]==="post"){
      //メールの送信
      $g="";
      if($this->inp["gender"]==1){$g="男性";}
      else if($this->inp["gender"]==2){$g="女性";}
      else if($this->inp["gender"]==3){$g="その他";}
      else if($this->inp["gender"]==4){$g="回答しない";}
      $body=
        "郵便番号:".$this->inp["zip"]."\r\n".
        "住所:\r\n".
        "  ".$this->prefarr[$this->inp["add0"]]."\r\n".
        "  ".$this->inp["add1"]."\r\n".
        "  ".$this->inp["add2"]."\r\n".
        "  ".$this->inp["add3"]."\r\n".
        "名前:".$this->inp["name1"]." ".$this->inp["name2"]."\r\n".
        "カナ:".$this->inp["kana1"]." ".$this->inp["kana2"]."\r\n".
        "性別:".$g."\r\n".
        "電話番号:".$this->inp["tel"]."\r\n".
        "メール:".$this->inp["mail"]."\r\n".
        "お問い合わせ内容:\r\n".
        str_repeat("-",60)."\r\n".
        $this->mb_wordwrap($this->inp["inquiry"])."\r\n".
        str_repeat("-",60)."\r\n";
      mb_send_mail(
        self::adminMailTo,
        '【お問い合わせ】'.self::title,
        $body,
        "Content-Type: text/plain; charset=UTF-8\r\n".
        "Content-Transfer-Encoding: BASE64\r\n".
        "From:".self::adminMailFrom."\r\n"
      );

      //DB登録したい場合
      /*
        -- 以下のようなテーブル構造でテーブルを作っておく
        CREATE TABLE t_inquiry(
          zip varchar(7) NOT NULL,  -- 郵便番号
          add0 varchar(20),        -- 都道府県
          add1 varchar(160),        -- 住所1
          add2 varchar(160),        -- 住所2
          add3 varchar(160),        -- 住所3
          name1 varchar(60),        -- お名前1
          name2 varchar(60),        -- お名前2
          kana1 varchar(60),        -- お名前カナ1
          kana2 varchar(60),        -- お名前カナ2
          gender varchar(20),       -- 性別
          tel varchar(20),          -- お電話番号
          mail varchar(100),        -- メールアドレス
          inquiry text,             -- 問い合わせ内容
          rdate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,  -- 登録日
          udate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  -- 更新日
          PRIMARY KEY(id)
        ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
      */
      /*
        //以下PHPを実行
        $dns="mysql:dbname=データベース名;host=ホストIP";
        $con=new PDO($dns,"ユーザー名","パスワード");
        $con->query('SET NAMES utf8');
        $sql="insert into t_inquiry(".
          " zip,add0,add1,add2,add3,name1,name2,kana1,kana2,gender,tel,mail,inquiry) ".
          "values(  ?,   ?,   ?,   ?,   ?,    ?,    ?,    ?, ?,     ?,  ?,   ?,       ?)";
        $stmt=$con->prepare($sql);
        $stmt->execute([
          $this->inp["zip"],
          $this->prefarr[$this->inp["add0"]],
          $this->inp["add1"], $this->inp["add2"], $this->inp["add3"],
          $this->inp["name1"],$this->inp["name2"],
          $this->inp["kana1"],$this->inp["kana2"],
          $g,
          $this->inp["tel"], $this->inp["mail"], $this->inp["inquiry"]
        ]);
      */

      //完了画面へ遷移させる
      $_SESSION["comp"]="comp";
      header("location: ./".basename(__FILE__));
      exit;
    }else{
      //完了画面
      $_SESSION=[];
      session_destroy();
      showComplete($this->inp);
      exit;
    }
  }
  private function mbtrim($str) {
    return preg_replace("/(^\s+)|(\s+$)/u", "", $str);
  }
  private function mb_wordwrap($str,$width=30){
    $arr = [];
    $strArr=explode("\r\n",$str);
    for($i=0;$i<count($strArr);$i++){
      $c = mb_strlen($strArr[$i],"UTF-8");
      for ($j=0; $j<$c; $j+=$width) {
        $arr[] = mb_substr($strArr[$i], $j, $width,"UTF-8");
      }
    }
    return implode("\r\n", $arr);
  }
}

$inq = new TInquiry;
exit;

/*
  ロボット防止の画像認証関数
*/
function getCharImg(){
  //TrueTypeFontファイルのパスを指定する。
  //ipaフォント(https://moji.or.jp/ipafont/ipaex00401/)を
  //ライセンスに準拠してダウンロードして使用しましょう
  define("TrueTypeFontPath",__DIR__."/ipaexg.ttf");
  define("ImageHeight",60);//出力される画像の高さ(px)

  //認証に使用する文字一覧を指定
  //半角数字の場合
  //1,7は回転すると分かりにくいのでコメントアウト
  $carr=[/*"1",*/"2","3","4","5","6",/*"7",*/"8","9","0",];

  $cnum=random_int(6,6);//認証に使用する文字数を指定、とりあえず6桁固定
  $cc='';
  $c=[];
  for($i=0;$i<$cnum;$i++){
      $c[$i]=[];
      $c[$i]['chr']=$carr[random_int(0,count($carr)-1)];
      $cc.=$c[$i]['chr'];
  }

  $lt=floor(ImageHeight*0.1);//総画像幅の計算
  $img=imagecreatetruecolor(100,100);
  $dpi=96;//解像度の設定
  imageresolution($img, $dpi, $dpi);
  $pt= floor(ImageHeight*0.6*72/$dpi);
  $col=imagecolorallocate($img,0,0,0);
  for($i=0;$i<$cnum;$i++){
    //回転角の設定
    $c[$i]['r']=random_int(-45,45);
    $arr=imagettftext(
      $img,$pt,
      $c[$i]['r'],0,0,
      $col,TrueTypeFontPath,$c[$i]['chr']
    );
    $xmin=min($arr[0],$arr[2],$arr[4],$arr[6]);
    $xmax=max($arr[0],$arr[2],$arr[4],$arr[6]);
    $ymin=min($arr[1],$arr[3],$arr[5],$arr[7]);
    $ymax=max($arr[1],$arr[3],$arr[5],$arr[7]);
    $c[$i]['x']=$lt-round($xmin*$dpi/72);
    $char_w=($xmax-$xmin)*$dpi/72;
    $lt=round($c[$i]['x']+$char_w);
    //若干文字をかぶせる
    $lt-=random_int($char_w*0.1,$char_w*0.4);
    $c[$i]['y']=random_int(floor(ImageHeight*0.1),floor(ImageHeight*0.3))-$ymin;
  }
  $lt+=floor(ImageHeight*0.1);//総画像幅の計算
  imagedestroy($img);
  $im=imagecreatetruecolor($lt,ImageHeight);
  imageresolution($im, $dpi, $dpi);

  $tranColor = imagecolorallocate($im, 254, 253, 252);//背景色セット
  imagefill($im, 0, 0, $tranColor);     //背景を塗る
  imagecolortransparent($im,$tranColor);//透明化
  //背景にランダムな四角形を描く
  $rnd=random_int(40,50);
  for($i=0;$i<$rnd;$i++){
    $col=imagecolorallocate($im,random_int(192,255),random_int(192,255),random_int(192,255));
    $x1=random_int(0,$lt);
    $y1=random_int(0,ImageHeight);
    $x2=random_int($x1,$lt);
    $y2=random_int($y1,ImageHeight);
    imagefilledrectangle($im, $x1, $y1, $x2, $y2, $col);
  }
  //変形文字を描画する
  for($i=0;$i<$cnum;$i++){
    $col = imagecolorallocate($im, random_int(0,80), random_int(0,80), random_int(0,80));//色
    imagettftext(
      $im, $pt,
      $c[$i]['r'],$c[$i]['x'],$c[$i]['y'],
      $col, TrueTypeFontPath, $c[$i]['chr']
    );
  }
  //点ノイズの描画
  $rnd=random_int(ImageHeight*6,ImageHeight*8);
  for($i=0;$i<$rnd;$i++){
    $col=imagecolorallocate($im,random_int(0,80),random_int(0,80),random_int(0,80));
    imagesetpixel($im,random_int(0,$lt),random_int(0,ImageHeight),$col);
  }
  //線ノイズの描画
  $rnd=random_int(round(ImageHeight*0.8),round(ImageHeight*0.9));
  for($i=0;$i<$rnd;$i++){
    $col=imagecolorallocate($im,random_int(0,100),random_int(0,100),random_int(0,100));
    imageline($im,random_int(0,$lt),random_int(0,ImageHeight),random_int(0,$lt),random_int(0,ImageHeight),$col);
  }
  //出力のバッファリングからdata URIを取得
  ob_start();
  imagejpeg($im,NULL,30);
  $con = base64_encode(ob_get_contents());
  ob_end_clean();
  imagedestroy($im);
  $src="data:image/jpeg;base64,".$con;

  //正解の文字列と、画像の配列を返す
  return [$cc,$src];
}

/*
  完了画面
*/
function showComplete($inp){
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title><?=$inp["title"]?></title>
  <meta name="Description" content="<?=$inp["title"]?>">
  <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
  <style>
    body{font-size:18px;color:#333;margin:0;display:flex;flex-flow:column;min-height:100vh;}
    .title{font-size:28px;font-weight:bold;color:#000;}
    @media screen and (max-width:768px){
      .title{font-size:20px;font-weight:700;}
    }
    .mybtn{
      display:inline-block;
      margin:auto;
      padding:8px 16px 8px 16px;
      color:#333;
      text-shadow:1px 1px 2px #999;
      background:#fff;
      border:0px none #000;
      text-decoration:none;
      box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.4);
      cursor:pointer;
      border-radius:0px 0px 0px 0px;
      vertical-align:middle;
      user-select: none;
      font-size:12px;
    }
    .mybtn:active{
      box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.4) inset;
    }
    .mybtn:hover{background:#eee;}
    .inputform{
      margin:0 auto 20px auto;
      width:100%;
      max-width:769px;
      padding:12px;
      box-sizing:border-box;
    }
    .inputform{max-width:560px;width:100%;flex:1;}
    .inputform>div{
      margin:4px 0 30px 0;
      text-align:left;
    }
    .footer{
      margin:0;
      padding:0;
      background:#222;
      height:50px;
      color:#fff;
      text-align:center;
      line-height:46px;
      font-size:15px;
      position:absolute;
      bottom:0;
      left:0;
      width:100%;
    }
    hr.thin{border:none;border-top:1px solid #ccc;}
    .label{font-weight:bold;}
  </style>
</head>
<body>
  <div class="inputform">
    <h1 class="title"><?=$inp["title"]?></h1>
    <hr class="thin">
    <?php if(!empty($inp["privacy"])){ ?>
      <p style="text-align:center;">
        <a href="<?=$inp["privacy"]?>" target="_blank" rel="noopener" class="mybtn">プライバシーポリシーはこちら</a>
      </p>
    <?php } ?>
    <div>
      <div class="label">送信が完了しました</div>
      お問い合わせ内容を担当へ送信しました。<br>
      回答までしばらくお時間を頂戴する場合があります。<br>
      ご了承ください。<br>
      <br>
      このウィンドウを閉じてください。
    </div>
  </div>
  <div class="footer">
    <?=$inp["footer"]?>
  </div>
</body>
</html>
<?php
}

/*
  入力画面
*/
function showInput($inp){
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title><?=$inp["title"]?></title>
  <meta name="Description" content="<?=$inp["title"]?>">
  <meta name="viewport" content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
  <style>
    body{font-size:18px;color:#333;margin:0;}
    .title{font-size:28px;font-weight:bold;color:#000;}
    @media screen and (max-width:768px){
      .title{font-size:20px;font-weight:700;}
    }
    input[type="text"],input[type="tel"],input[type="email"],select,textarea{
      font-size:16px;
      margin:0;
      padding:8px;
      width:100%;
      max-width:500px;
      background:#fafafa;
      border:1px solid #aaa;
      color:#333;
      box-sizing:border-box;
    }
    .mybtn{
      display:inline-block;
      margin:auto;
      padding:8px 16px 8px 16px;
      color:#333;
      text-shadow:1px 1px 2px #999;
      background:#fff;
      border:0px none #000;
      text-decoration:none;
      box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.4);
      cursor:pointer;
      border-radius:0px 0px 0px 0px;
      vertical-align:middle;
      user-select: none;
      font-size:12px;
    }
    .mybtn:active{
      box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.4) inset;
    }
    .mybtn:hover{background:#eee;}
    .blue{color:blue;font-size:16px;font-weight:bold;}
    .err{color:red;font-size:12px;margin:0;padding:0;}
    .inputform{
      margin:0 auto 20px auto;
      width:100%;
      max-width:769px;
      padding:12px;
      box-sizing:border-box;
    }
    .inputform{max-width:560px;width:100%;}
    .inputform>div{
      margin:4px 0 30px 0;
      text-align:left;
    }
    .footer{
      margin:0;
      padding:0;
      background:#222;
      width:100%;
      height:50px;
      color:#fff;
      text-align:center;
      line-height:46px;
      font-size:15px;
    }
    #fm{text-align:center;}
    hr.thin{border:none;border-top:1px solid #ccc;}
    .label{font-weight:bold;}

    input[type="submit"]{
       background-image: linear-gradient(0deg, #fff, #ccc, #fff);
       font-size:20px;
       border: 1px solid #666;
       color:#000;
       border-radius:4px;
       padding:4px 4px;
    }
    input[type="submit"]:hover {
       background-image: linear-gradient(0deg, #fff, #ccc);
       border: 1px solid #333;
    }
    input[type="submit"]:active {
       background-image: linear-gradient(180deg, #fff, #ccc);
       border: 1px solid #333;
    }
  </style>
  <script>
    window.addEventListener("DOMContentLoaded",function(){
      //ボタン連打対応
      document.getElementById("fm").addEventListener("submit",function(){
        setTimeout(function(){
          document.getElementById("submit").setAttribute("disabled","true");
        },1);
        return true;
      });
    });
  </script>
</head>
<body>
  <form id="fm" action="./<?=basename(__FILE__)?>" method="POST" autocomplete="off">
    <div class="inputform">
      <h1 class="title"><?=$inp["title"]?></h1>
      <hr class="thin">
      <?php if(!empty($inp["privacy"])){ ?>
        <p style="text-align:center;">
          <a href="<?=$inp["privacy"]?>" target="_blank" rel="noopener" class="mybtn">プライバシーポリシーはこちら</a>
        </p>
      <?php } ?>

      <div>
        <div class="label">郵便番号<span class="blue">(必須)</span></div>
        <?php
          if(!empty($inp["err"]["zip"])){
            echo "<div><span class='err'>".htmlspecialchars($inp["err"]["zip"])."</span></div>";
          }
        ?>
        <input type="tel" placeholder="(例)0000000(ハイフン無し)" maxlength="7" id="zip" name="zip"
          value="<?=isset($inp["zip"])?htmlspecialchars($inp["zip"]):""?>"
          autocomplete="off" pattern="^[0-9]{7}$" required title="ハイフン無しで半角数字7桁">
      </div>
      <div>
        <div class="label">住所[都道府県]<span class="blue">(必須)</span></div>
        <?php
          if(!empty($inp["err"]["add0"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["add0"])."</span></div>";
          }
        ?>
        <select id="add0" name="add0" required>
          <?php
            foreach($inp["pref"] as $key=>$val){
              if($key==$inp["add0"]){
                if($key==0){
                  echo "<option value='' disabled selected required>{$val}</option>";
                }else{
                  echo "<option value='{$key}' selected required>{$val}</option>";
                }
              }else{
                if($key==0){
                  echo "<option value='{$key}' disabled required>{$val}</option>";
                }else{
                  echo "<option value='{$key}' required>{$val}</option>";
                }
              }
            }
          ?>
        </select>
      </div>
      <div>
        <div class="label">住所[市区町村]<span class="blue">(必須)30文字迄</span></div>
        <?php
          if(!empty($inp["err"]["add1"])){
            echo "<div><span class='err'>".htmlspecialchars($inp["err"]["add1"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="" maxlength="30" id="add1" name="add1" autocomplete="off"
          value="<?=isset($inp["add1"])?htmlspecialchars($inp["add1"]):""?>" required>
      </div>
      <div>
        <div class="label">住所[番地以降]<span class="blue">(必須)30文字迄</span></div>
        <?php
          if(!empty($inp["err"]["add2"])){
            echo "<div><span class='err'>".htmlspecialchars($inp["err"]["add2"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="" maxlength="30" id="add2" name="add2" autocomplete="off"
          value="<?=isset($inp["add2"])?htmlspecialchars($inp["add2"]):""?>" required>
      </div>
      <div>
        <div class="label">住所[建物名以降]<span class="blue">30文字迄</span></div>
        <?php
          if(!empty($inp["err"]["add3"])){
            echo "<div><span class='err'>".htmlspecialchars($inp["err"]["add3"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="" maxlength="30" id="add3" name="add3" autocomplete="off"
          value="<?=isset($inp["add3"])?htmlspecialchars($inp["add3"]):""?>">
      </div>
      <div>
        <div class="label">お名前[姓]<span class="blue">(必須)10文字迄</span></div>
        <?php
          if(!empty($inp["err"]["name1"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["name1"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="(例)苗字" maxlength="10" id="name1" name="name1" autocomplete="off"
          value="<?=isset($inp["name1"])?htmlentities($inp["name1"]):""?>" required>
      </div>
      <div>
        <div class="label">お名前[名]<span class="blue">(必須)10文字迄</span></div>
        <?php
          if(!empty($inp["err"]["name2"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["name2"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="(例)太郎" maxlength="10" id="name2" name="name2" autocomplete="off"
          value="<?=isset($inp["name2"])?htmlentities($inp["name2"]):""?>" required>
      </div>
      <div>
        <div class="label">お名前[カナ姓]<span class="blue">(必須)12文字迄</span></div>
        <?php
          if(!empty($inp["err"]["kana1"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["kana1"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="(例)ミョウジ" maxlength="12" id="kana1" name="kana1" autocomplete="off"
          value="<?=isset($inp["kana1"])?htmlentities($inp["kana1"]):""?>" required>
      </div>
      <div>
        <div class="label">お名前[カナ名]<span class="blue">(必須)12文字迄</span></div>
        <?php
          if(!empty($inp["err"]["kana2"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["kana2"])."</span></div>";
          }
        ?>
        <input type="text" placeholder="(例)タロウ" maxlength="12" id="kana2" name="kana2" autocomplete="off"
          value="<?=isset($inp["kana2"])?htmlentities($inp["kana2"]):""?>" required>
      </div>
      <div>
        <div class="label">性別<span class="blue">(必須)</span></div>
        <?php
          if(!empty($inp["err"]["gender"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["gender"])."</span></div>";
          }
        ?>
        <label><input type="radio" name="gender" value="1" <?=$inp["gender"]==1?"checked":""?> required>男性</label><br>
        <label><input type="radio" name="gender" value="2" <?=$inp["gender"]==2?"checked":""?>>女性</label><br>
        <label><input type="radio" name="gender" value="3" <?=$inp["gender"]==3?"checked":""?>>その他</label><br>
        <label><input type="radio" name="gender" value="4" <?=$inp["gender"]==4?"checked":""?>>回答しない</label>
      </div>
      <div>
        <div class="label">電話番号<span class="blue">(必須)</span></div>
        <?php
          if(!empty($inp["err"]["tel"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["tel"])."</span></div>";
          }
        ?>
        <input type="tel" placeholder="(例)0300000000(ハイフン無し)" maxlength="11"
          id="tel" name="tel" autocomplete="off"
          value="<?=isset($inp["tel"])?htmlentities($inp["tel"]):""?>"
          pattern="^[0-9]{10,11}$" title="ハイフン無しで半角数字10-11桁" required>
      </div>
      <div>
        <div class="label">メールアドレス<span class="blue">(必須)</span></div>
        <?php
          if(!empty($inp["err"]["mail"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["mail"])."</span></div>";
          }
        ?>
        <input type="email" placeholder="(例)user@yourdomain.jp" maxlength="50" id="mail" name="mail" autocomplete="off"
          value="<?=isset($inp["mail"])?htmlentities($inp["mail"]):""?>" required>
      </div>
      <div>
        <div class="label">ご質問事項<span class="blue">(必須)500文字迄</span></div>
        <?php
          if(!empty($inp["err"]["inquiry"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["inquiry"])."</span></div>";
          }
        ?>
        <textarea maxlength="500" id="inquiry" name="inquiry" autocomplete="off" rows="8" cols="40"
         style="margin:0;padding:4px;"
         placeholder="ご質問事項を&anp;#13;&anp;#10;お書きください" required
        ><?=isset($inp["inquiry"])?htmlentities($inp["inquiry"]):""?></textarea>
      </div>
      <div>
        <div class="label">画像認証<span class="blue">(必須)</span></div>
        <?php
          if(!empty($inp["err"]["auth"])){
            echo "<div><span class='err'>".htmlentities($inp["err"]["auth"])."</span></div>";
          }
        ?>
        <img id="char" src="<?=$inp["authimg"]?>"><br>
        <input type="tel" placeholder="" maxlength="6" id="auth" name="auth"
          autocomplete="off" value="" pattern="^[0-9]+$" title="半角数字6桁" required />
      </div>
      <div style="text-align:center;margin:12px 0 12px 0;">
        <input type="hidden" name="order" value="post">
        <input type="submit" value="送信する" id="submit">
      </div>
    </div>
  </form>
  <div class="footer">
    <?=$inp["footer"]?>
  </div>
</body>
</html>
<?php
}