[ノート]『初めてのPHP 』を読む(CH07.ユーザとの情報交換)

#7章 ユーザとの情報交換

##7.1サーバ変数
サーバ変数は$_SERVERスーパーグローバル配列により提供


###1.$_SERVER['PHP_SELF'] 
現在のリクエストのURLのパス名の部分
URL->*http://www.example.com/store/catalog.php*
PHP_SELF->*/store/catalog.php*

###2.$_SERVER['REQUEST_METHOD']
Webブラウザが現在のところのページをリクエストするのに使ったらHTTPメソッド

###3.QUERY_STRING
URLの疑問符の後ろに続くURLパラメーターの部分
URL->*http://www.example.com/catalog/store.php?category=kitchen&price=5*
QUERY_STRING->*category=kitchen&price=5*


###4.PATH_INFO
URLのスラッシュの後ろに最後についている追加のパス情報、これはクエリ文字をつかわないでスクリプトに情報を渡す方法
URL->*http://www.example.com/catalog/store.php/browse*
例：*/browse*

###5.SERVER_NAME
PHPエンジンが動作しているWebサイトの名前
例：*www.example.com*

###6.DOCUMENT_ROOT
そのWebサイトで利用できるdocumentを格納するWebサーバコンピュータ上のディレクトリ
例：Webサイト
　　*http://www.example.com*のドキュメントルートが*/usr/local/htdocs*、
　*　http://www.example.com/store/catalog.php*のリクエストは*/usr/local/htdocs/catalog/store.php*に相当

###7.REMOTE_ADDR
Webサーバルにリクエストを行なったユーザーのIPアドレス
例：*175.56.28.3*


##7.2 フォームパラメータへのアクセス

```php
<form method="POST" action="catalog.php">
    <input type="text" name="product_id">
    <select name="category">
        <option value="ovenmitt">Por Holder</option>
        <option value="fryingpan">Frying Pan</option>
        <option value="torch">Kitchen Torch</option>
    </select>
    <input type="submit" name="submit">
</form>
Here are the submitted values:
product_id:<?php print $_POST['product_id']??''?>
<br/>
category:<?php print $_POST['category]??'?>
```
null合体演算子:??
古いバージョンではissetを使う

###複数の値を持つform要素
複数の値を持つことができるフォーム要素には、名前の後に[]を付ける必要だがあります。

```php
<form method="POST" action="eat.php">
    <select name="lunch[]" multiple>
        <option value="pork">BBQ Pork Bun</option>
        <option value="chicken">Chicken Bun</option>
        <option value="lotus">Lotus Seed Bun</option>
        <option value="bean">Bean Paste Bun</option>
        <option value="nest">Bird-Nest Bun</option>
    </select>
    <input type="submit" name="submit">
</form>
Selected buns:<?php
if(isset($_POST['lunch'])){
    foreach ($_POST['lunch'] as $choice){
        print "You want a $choice bun, <br/>";
    }
}
?>
```
##7.3/7.4関数を使ったフォーム処理とデータの検証


```php
<?php

if($_SERVER['REQUEST_METHOD']=='POST'){
   //
   if（validate_form（）){
   process_form();
}else{
    show_form();
}
}

//Do something when the form is submitted フォームのサブミット時に何かを行う

function process_form(){
    print "Hello," .$_POST['my_name'];
}

//Display the form フォームを表示する

function show_form(){
    print<<<_HTML_
<form method="POST" action="$_SERVER[PHP_SELF]">
Your name: <input type="text" name="my_name">
<br/>
<input type="submit" value="Say Hello">
</form>
_HTML_;

}

//Check the form data データの検証
function validate_form(){
    //Is my_name at least 3 characters long?
    if(strlen($_POST['my_name'])<3){
        return false;
    }else{
        return true;
    }
}


```
###7.4.1 必須項目

必須項目が未入力でないかを確認->strlen()

```php

if(strlen($_POST['email'])==0){
    $errors[]="You must enter an email address.";
}
```


###7.4.2 数値要素と文字列要素
サブミットされた値が整数か浮動小数点数かを確認->fileter_input()

```php
//整数入力するの認証
$ok=filter_input(INPUT_POST,'age',FILTER_VALIDATE_INT);
//指定の入力要素が欠けていたらnullを返す
//存在するがフィルタに従うと有効でない場合falseを返す
if(is_null($ok)||($ok===false)){
    $errors[]='Please enter a valid age.';
}
//浮動小数点数入力の認証
$ok=filter_input(INPUT_POST,'price',FILTER_VALIDATE_FLOAT);
if(is_null($ok)||($ok===false)){
    $errors[]='Please enter a valid age.';
}


###ホワイトスペースを取り除く->trim()
if(strlen(trim($_POST['name']))==0){
    $errors[]="Your name is required";
}

###入力データーとエラーの配列の作成

function validate_form(){
    $errors=array();
    $input=array();

    $input['age']=filter_input(INPUT_POST,'age',FILTER_VALIDATE_INT);
    if(is_null($input['age'])||($input['age'])===false){
        $errors[]='Please enter a valid age.';
    }
    $input['price']=filter_input(INPUT_POST,'price',FILTER_VALIDATE_FLOAT);
    if(is_null($input['price'])||($input['price'])===false){
        $errors[]='Please enter a valid price.';
    }

　　　//$_POST['name']が設定されていない場合に備えてnull合体演算子を使う
    $input['name']=trim($_POST['name']??'');
    if(strlen($input['name'])==0){
        $errors[]='Your name is required.';
    }

    return array($errors,$input);
}

```
エラーと変換した入力データの処理



```php
if($_SERVER['REQUEST_METHOD']=='POST'){
    //If validate_form() returns errors,pass them to show_form()
    list($form_errors,$input)=validate_form();
    if($form_errors){
        show_form($form_errors);
    }else{
        process_form($input);
    }
}else{
    show_form();
}
```


###7.4.3数値範囲

FILTER_VALIDATE_INTの第4引数としてわたす

```php
$input['age']=filter_input(INPUT_POST,'age',FILTER_VALIDATE_INT,
    array('options'=>array('min_range'=>18,'max_range'=>65)));
if(is_null($input['age'])||($input['age']===false)){
    $errors[]='Please enter a valid age between 18 and 65';
}
//min_range/max_rangeを使わない場合
$input['price']=filter_input(INPUT_POST,'price',FILTER_VALIDATE_FLOAT);
if(is_null($input['price'])||($input['price'])===false||($input['price']<10.00)||($input['price']>50.00)){
   $errors[]='Please enter a valid price between $10 and $50';
}
```


###7.4.4 メールアドレス
FILTER＿VALIDATE_EMAILフィルタで文字列をチェックします

```php
$input['email'] = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if (! $input['email']) {
    $errors[] = 'Please enter a valid email address';
}
```

###7.4.5 selectメニュー

```php
$sweets = array('Sesame Seed Puff','Coconut Milk Gelatin Square', 'Brown Sugar Cake','Sweet Rice and Meat');
function generate_options($options){
    $html='';
    foreach ($options as $option){
        $html.="<option>$option</option>";
    }
    return $html;
}
//show form
function show_form(){
    $sweets=generate_options($GLOBALS['sweets']);
    print<<<_HTML_
    <form method="post" action="$_SERVER[PHP_SELF]">
    Your Order:<selct name="order">$sweets</selct>
    <br/>
    <input type="submit" value="Order">
    </form>
_HTML_;

}

```

```php
//validation有効の選択肢なのかをチェック
$input['order']=$_POST['order'];
if(!in_array($input['order'],$GLOBALS['sweets'])){
    $errors='Please choose a valid order.';
}
```

異なる選択肢と値を持つ<select>メニュー

```php
$sweets = array('puff' => 'Sesame Seed Puff',
    'square' => 'Coconut Milk Gelatin Square',
    'cake' => 'Brown Sugar Cake',
    'ricemeat' => 'Sweet Rice and Meat');
function generate_options_with_value($options){
    $html='';
    foreach ($options as $value=>$option){
        $html.="<option value=\"$value\"></option>\n";
    }
    return $html;
}
function show_form(){
    $sweets=generate_options($GLOBALS['sweets']);
    print<<<_HTML_
    <form method="post" action="$_SERVER[PHP_SELF]">
    Your Order:<selct name="order">$sweets</selct>
    <br/>
    <input type="submit" value="Order">
    </form>
_HTML_;

}
```

###7.4.6 HTML とJavascript

strip_tags()でHTMLタグを取り除く→タグがなくなる

```php
//Remove HTML from comments
$comments=strip_tags($_POST['comments']);
//Now it's OK to print $comments
print $comments;

htmlentitiesでエンコード→＜＞など、HTMLで特別な意味をもつ文字はそれに相当するするエンティティに変更
$comments=htmlentities($_POST['comments']);
//Now its ok to print $comments
print $comments;
```
###7.5デフォルト値の表示

```php
if ($_SERVER['REQUEST_METHOD']=='POST'){
    $defaults=$_POST;
}else{
    $defaults=array('delivery' => 'yes',
        'size' => 'medium',
        'main_dish' => array('taro','tripe'),
        'sweet' => 'cake');
}
```
テキストのデフォルト値の設定

```php
print '<input type="text" name="my_name" value="' .htmlentities($defaults['my_name']).'">';

```

複数行のテキスト領域のデフォルト値の設定

```php
print '<textarea name="comments">';
print htmlentities($defaults['comments']);
print '</testarea>';
```

selectメニューのデフォルト値の設定

```php
$sweets=array('puff' => 'Sesame Seed Puff',
    'square' => 'Coconut Milk Gelatin Square',
    'cake' => 'Brown Sugar Cake',
    'ricemeat' => 'Sweet Rice and Meat');
print '<select name="sweet">';
foreach($sweets as $option =>$label){
    print '<option value="'.$option.'"';
    if($option==$defaults['sweet']){
        print ' selected';
    }
    print ">$option</option>";
}
print '</select>';
```

多値の<select>メニューのデフォルトの設定

```php
$main_dishes = array('cuke' => 'Braised Sea Cucumber', 'stomach' => "Sauteed Pig's Stomach",
    'tripe' => 'Sauteed Tripe with Wine Sauce',
    'taro' => 'Stewed Pork with Taro',
    'giblets' => 'Baked Giblets with Salt',
    'abalone' => 'Abalone with Marrow and Duck Feet');
print '<select name="main_dish[]" multiple>';
$selected_options=array();
foreach($default['main_dish'] as $option){
    $selected_options[$option]=true;
}
foreach($main_dishes as $option=>label){
    print '<option value="'.htmlentites($option).'"';
    if(array_key_exists($option,$selected_options)){
        print 'selected';
    }
    print '>'.htmlentities($label).'</option>';

}
print '</select>';
```

チェックボックスとラジオボタンのデフォルトの設定

```php
print '<input type="checkbox" name="delivery" value="yes"';
if($defaults['delivery']=='yes'){
    print ' checked';
    print '> Delivery?';
}

$checkbox_options=array('small' => 'Small', 'medium' => 'Medium',
        'large' => 'Large');
    foreach ($checkbox_options as $value=>$label){
        print '<input type="radio" name="size" value="'.$value.'"';
        if($defaults['size']==$value){
            print ' checked';
            print ">$label";
        }
    }
```