アラカン"BOKU"のITな日常

文系システムエンジニアの”BOKU”が勉強したこと、経験したこと、日々思うことを書いてます。

PHP+CodeIgniter3+Bootstrap4:フォームバリデーション(テキスト入力値チェック)と変数名の翻訳

CodeIgniter3+Bootstrap4でForm入力を前回に引き続きやります。

f:id:arakan_no_boku:20180926205937p:plain

今回は、前回の画面に以下を追加します。

  • 入力テキストに対するチェックを行う
  • エラーメッセージの変数名を人間用に翻訳する

 

入力画面イメージのサンプルチェック仕様

 

まず、入力画面のイメージです。

f:id:arakan_no_boku:20181001223844j:plain

やることは、シンプルに「ユーザID」と「パスワード」を入力して、それぞれ、以下のルールに一致しているかをチェックします。

  • ユーザID :必須入力 と 文字種(半角英数字のみ)
  • パスワード:必須入力 と 文字種(半角英数字のみ)と 文字数(8~20)

 

入力テキストに対するチェックを行う

 

後ろのコントローラクラスで参照する名前を確認するために、VIEW(入力画面)の入力に使うinputタグだけ抜き出しています。

ユーザID部分が「name="input-id"」で、パスワード部分が「name="input-password"」です。

<input type="text" class="form-control" id="input-id" name="input-id" placeholder="ユーザID(半角)を入力">
<input type="password" class="form-control" id="input-password" name="input-password" placeholder="パスワード">

入力に対してチェック(バリデーション)を行うには、コントローラクラスで「$this->form_validation->set_rules」を使って、チェックルールを指定します。

ひとつの項目に対して、複数のルールを指定する時は「|」でつなぎます。

例えば。

ユーザIDの場合。

必須入力(required) と 文字種正規表現判定(regex_match)の2つを同時にしているするのでこんな感じです。

$this->form_validation->set_rules('input-id', 'ユーザID',
     'required|regex_match[/^[0-9a-zA-Z]+$/]'
);

パスワードの場合。

必須入力(required) と 文字種(alpha_numeric)と 文字数(min_lengthとmax_length)を同時に指定するので、こんな感じ。

$this->form_validation->set_rules('input-password', 'パスワード',
   'required|alpha_numeric|min_length[8]|max_length[20]'
);

まあ、わかりやすくはあります。 

なお。

半角英数字のみのチェックは、「alpha_numeric」という組み込みのものを使う方法と「regex_matchに正規表現(^[0-9a-zA-Z]+$)で指定する」方法の2通り書いてますが、どっちでもチェックは同じです。

あと、ソースを書く時の注意点がひとつ。

複数条件を連結する場合に

'required|alpha_numeric|min_length[8]|max_length[20]'

みたいに「|」と次の単語の間に空間をあけない書き方がいいです。

ソースの視認性を気にして以下のように書いても、動きますが・・。

'required|

alpha_numeric|

min_length[8]|

max_length[20]'

2番目以降のパラメータでエラーになった時に、メッセージが正しく表示されなくなる(適切なメッセージが見つからないとか)場合があります。

CodeIgniterには、上記以外にもいろいろ組み込みチェックが用意されてます。

主なものは、こんな感じです。

URLとかemailとか、正規表現で書くとややこしいものがあるのは有難いです。

regex_matchで正規表現を指定することで拡張もできますしね。

ルール Parameter 説明
required No 空き要素の場合はFALSE  
matches Yes formの要素が一致しない時はFALSE matches[form_item]
regex_match Yes 正規表現で指定したパターンに一致しない場合はFALSE regex_match[/regex/]
min_length Yes 指定する文字数より少ない場合はFALSE。 min_length[3]
max_length Yes 指定する文字数を超えた場合はFALSE。 max_length[12]
exact_length Yes 指定する文字数と一致しない場合はFALSE exact_length[8]
greater_than Yes 指定した値よりも(数字的に)等しいもしくは小さいか、数字でない時にFALSE 。 greater_than[8]
greater_than_equal_to Yes 指定した値よりも(数字的に)小さいか、数字でない時にFALSE 。 greater_than_equal_to[8]
less_than Yes 指定した値よりも(数字的に)等しいもしくは大きいか、数字でない時にFALSE 。 less_than[8]
less_than_equal_to Yes 指定した値よりも(数字的に)大きいか、数字でない時にFALSE 。 less_than_equal_to[8]
alpha No アルファベット以外の文字を含む場合、FALSE。 alpha
alpha_numeric No アルファベット・数字以外の文字を含む場合、FALSE。 alpha_numeric
alpha_numeric_spaces No アルファベット・数字・空白(半角)以外の文字を含む場合、FALSE。 alpha_numeric_spaces
alpha_dash No アルファベット、下線、dashesの以外の時にFALSE。 数字を含む場合はFALSE。 alpha_dash
numeric No 数字以外の文字を含む場合FALSE。 numeric
integer No 整数以外の数字・文字列の場合はFALSE。 integer
decimal No 小数点を含む数字以外の場合は、FALSE。 decimal
is_natural No 自然数以外の場合は、FALSE。 0, 1, 2, 3, etc. is_natural
is_natural_no_zero No 0を除く自然数の場合以外の場合は、FALSE。 is_natural_no_zero
valid_url No URL以外の値の場合は、FALSE。 valid_url
valid_email No email以外の値の場合は、FALSE。 valid_email
valid_emails No コンマを挟んだ複数のemail以外の値の場合は、FALSE。 valid_emails
valid_ip No IPアドレス以外の場合は、FALSE。 ‘ipv4’ or ‘ipv6’ の形式をサポートしています。 valid_ip
valid_base64 No Base64の形式以外の場合は、FALSE。 valid_base64

 

エラーメッセージの変数名を人間用に翻訳する

 

今回は、各項目ごとにエラーメッセージを表示するようにしてみます。

f:id:arakan_no_boku:20181002213445j:plain

エラーメッセージを上記のように表示する場合のPHPソースは。

<div class="form-group row my-4">
	<label for="inputId" class="col-sm-2 col-form-label">ユーザID</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="input-id" name="input-id" placeholder="ユーザID(半角)を入力">
    </div>
    <div class="col-sm-2"></div>
    <div class="col-sm-10 text-danger">
    	<?php echo form_error('input-id'); ?>
    </div>
  </div>
  <div class="form-group row  my-4">
    <label for="inputPassword" class="col-sm-2 col-form-label">パスワード</label>
    <div class="col-sm-10">
    	<input type="password" class="form-control" id="input-password" name="input-password" placeholder="パスワード">
    	<small id="passwordHelpBlock" class="form-text text-muted">パスワードは、文字と数字で8~20文字です。空白、記号、特殊文字、絵文字を含むことはできません。</small>
    </div>
    <div class="col-sm-2"></div>
    <div class="col-sm-10 text-danger">
    	<?php echo form_error('input-password'); ?>
    </div>
</div>

エラーメッセージを項目ごとに表示する時は「 form_error('input-password')」のように、form_errorを使います。

各チェックに対応するエラーメッセージは言語ファイル「form_validation_lang.php」(application/languageの下)にあります。

例えば、min_lengthなら今のようにメッセージが用意されてます。

$lang['form_validation_min_length'] = '{field}欄は{param}文字以上、でなければいけません';

まず、 {param}には「min_length[5]」の場合だと「5」がはいります。

あと、 {field} タグには、set_rulesの第二パラメータの指定した名称がはいります。

下記例だと「ユーザID」がはいります。

$this->form_validation->set_rules('input-id', 'ユーザID',
     'required|regex_match[/^[0-9a-zA-Z]+$/]'
);

でも 、上記みたいにダイレクトに日本語を書いていると、ちょっとベタすぎます。

やっぱり、他のメッセージ同様に言語ファイルで多言語対応はしておきます。

まず、言語ファイルを用意します。

日本語の場合なら、application/language/japaneseの下に適当な名前で言語ファイルを作ります。

今回は「my_lang.php」という名前にします。

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

$lang['input-id'] = "ユーザID";
$lang['input-password'] = "パスワード";
?>

この言語ファイルを用意したら、 コントローラクラスを以下のように変更します。

$this->lang->load('my_lang');

$this->form_validation->set_rules('input-id', 'lang:input-id',
     'required|regex_match[/^[0-9a-zA-Z]+$/]'
);
        
$this->form_validation->set_rules('input-password', 'lang:input-password',
     'required|alpha_numeric|min_length[8]|max_length[20]'
);

補足すると。

my_lang.phpをロードして使えるようにするのは、こんな感じ。

$this->lang->load('my_lang');

ロードした辞書ファイルから名称を持ってくるには、第二パラメータで「lang:」を使います。

例えば、「input-id」で言語ファイルから登録したメッセージを引く時は

lang:input-id

てな感じです。

これで、多言語対応もできました。

とりあえず、今回はこんなとこで。

 

最後に全体のソースです

 

まず、コントローラクラスから。

<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Demos extends CI_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->helper('url');
        $this->load->helper('html');
    }

    public function inpv()
    {
        $this->load->helper('form');
        $this->load->library('form_validation');

        $this->lang->load('my_lang');

        $this->form_validation->set_rules('input-id', 'lang:input-id',
            'required|regex_match[/^[0-9a-zA-Z]+$/]'
        );

        $this->form_validation->set_rules('input-password', 'lang:input-password',
            'required|alpha_numeric|min_length[8]|max_length[20]'
        );

        $data['title'] = "formサンプル";
        $data['id'] = $this->input->post('input-id');
        $data['pass'] = $this->input->post('input-password');

        if ($this->form_validation->run() === FALSE) {
            if (! file_exists(APPPATH . 'views/demos/inpvbody.php')) {
                show_404();
            }
            $data['msg'] = "とりあえずIDとパスワードを入力するサンプル";
            $this->load->view('templates/header', $data);
            $this->load->view('demos/inpvbody.php', $data);
            $this->load->view('templates/footer', $data);
        } else {
            if (! file_exists(APPPATH . 'views/demos/success_vbody.php')) {
                show_404();
            }
            $data['msg'] = "入力を正常に受け取りました";
            $this->load->view('templates/header', $data);
            $this->load->view('demos/success_vbody.php', $data);
            $this->load->view('templates/footer', $data);
        }
    }
}

?>

入力画面のVIEW「inpvbody.php」です。

<div class="row">
  	<div class="col text-center">
  		<h3><?php echo $msg; ?></h3>
  	</div>
</div>

<?php echo form_open('Demos/inpv'); ?>
<div class="form-group row my-4">
	<label for="inputId" class="col-sm-2 col-form-label">ユーザID</label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="input-id" name="input-id" placeholder="ユーザID(半角)を入力">
    </div>
    <div class="col-sm-2"></div>
    <div class="col-sm-10 text-danger">
    	<?php echo form_error('input-id'); ?>
    </div>
  </div>
  <div class="form-group row  my-4">
    <label for="inputPassword" class="col-sm-2 col-form-label">パスワード</label>
    <div class="col-sm-10">
    	<input type="password" class="form-control" id="input-password" name="input-password" placeholder="パスワード">
    	<small id="passwordHelpBlock" class="form-text text-muted">パスワードは、文字と数字で8~20文字です。空白、記号、特殊文字、絵文字を含むことはできません。</small>
    </div>
    <div class="col-sm-2"></div>
    <div class="col-sm-10 text-danger">
    	<?php echo form_error('input-password'); ?>
    </div>
  </div>
  <div class="form-group row  my-4">
    <div class="offset-sm-2 col-sm-10">
      <button type="submit" class="btn btn-primary">実行する</button>
    </div>
  </div>
</form>    

入力OKの結果のVIEW「success_vbody.php」です。

<div class="row">
  <div class="col text-center my-4">
  	<h2><?php echo $msg; ?></h2>
  </div>
</div>
<div class="row">
  <div class="col text-center my-2">
    <h2>入力されたIDは「<?php echo $id; ?>」です。 </h2>
  </div>
</div>
<div class="row">
  <div class="col text-center my-2">
    <h2>入力されたパスワードは「<?php echo $pass; ?>」です。 </h2>
  </div>
</div>
<div class="row">
  <div class="col my-2 text-center">
  	<?php echo img('images/sample02.jpg'); ?>
  </div>
</div>   

なお、例によって、ヘダーとフッターの部分は以下の記事で書いたテンプレートの使いまわしです。

arakan-pgm-ai.hatenablog.com

ではでは。