sql、phpの最低限のセキュリティ対策とjavascriptのよく使うもの

#前置き
- php7.0
- mysql5.6
- html5
- フレームワークなどは使わない感じです
- fooやbarなどは、自分で書き換えてください

#コードメモ


##主にphp,sql（サーバーサイド）関連


###データベース設定

データベース、sqlを使うときは　require_once "db.php"; 　などして、これを含めてください

```db.php
  define("DB_NAME", "foo");
  define("DB_SERV", "bar");
  define("DB_USER", "username");
  define("DB_PASS", "password");
  define("DSN", "mysql:dbname=".DB_NAME.";host=".DB_SERV.";charset=utf8");
try {
  //PDOclass(buildin)のインスタンス作成　プロパティ(属性)は＄pdo
  $pdo = new PDO(DSN,DB_USER,DB_PASS);
  //prepared statement の emulationをfalseにする　つまりsql文がスタティック静的になり定数しか使えない
  $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
  //attrbute(属性) PDOclassのATTR_ERRMODE(method,function)を呼び出し
  $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
  //echo "データベース{$dbName}に接続しました";
  //$pdo = NULL;接続解除は自動で行われるのでしなくていい
} catch (PDOException $e) {
  echo $e->getMessage();
  exit();
}
```

###sqlインジェクション対策
sqlの基本形です
sqlインジェクション対策にbindValueをして、扱いやすい配列の形にしています

urlや検索ワード、get,postでエンドユーザーとやりとりするもの、インサートするものは必ず行うべきものです

```samplesql.php
require_once "db.php"; 　

$sql="SELECT * FROM base_table WHERE base_id = :sid";
$stmt=$pdo->prepare($sql);
$stmt->bindValue(":sid",$sid,PDO::PARAM_INT);
$stmt->execute();
$result=$stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $key => $value) {
  $base_id=$value['base_id'];
}
```


###xss（クロスサイトスクリプティング）対策

htmlタグなどをエスケープして、悪意のあるプログラムをプログラムとして読まないようにする便利関数です
表示するときにこの関数を使ってください

```function.php

function es ($data){
  //配列の時は値を１づつ呼び出して再帰呼び出し:自身を呼び出すこと
  if (is_array($data)){
    return array_map(__METHOD__,$data);
    //__METHOD__は実行中のメソッド:es()を呼び出すマジック定数
  }else{
    return htmlspecialchars($data,ENT_QUOTES,'UTF-8');
  }
}
//使用例
$_POST=es($_POST);
$_GET=es($_GET);
```


###ページネーション

phpかsqlで条件分岐をかいてください


```pn.php

$div_num = 10;　//表示する数

$param_num = htmlspecialchars($p,ENT_QUOTES,'UTF-8');
if(empty($param_num)){
  $start_num = 1;
}else{
  $start_num = ($param_num - 1) * $div_num + 1;
}
$end_num = $div_num + $start_num - 1;
if($all_data >= $div_num){
for($i = 1; $i <= ceil($all_data / $div_num); $i++){
 echo "<a href='atm_search.php?p={$i}'>{$i}</a>";
 }
}

 //PHPで配列のキーを条件分岐
$result=$stm->fetchAll(PDO::FETCH_ASSOC);
for ($i=$start_num-1; $i < $end_num; $i++) {
  $prefectures[$i]=$result[$i]['prefectures'];
}
 //またはSQLで条件分岐
$sql.=" AND store_id >= :start_num AND store_id <= :end_num";
$stmt=$pdo->prepare($sql);
$all_data=$stmt->rowCount();
$stmt->bindValue(':$start_num',$start_num,PDO::PARAM_INT);
$stmt->bindValue(':end_num',$end_num,PDO::PARAM_INT);
$stmt->execute();
```



###スクレイピング

vendorをインストールした後に実装してください
このコードはヤフーの為替を取って来ます
ただ、頻繁にスクレイピングすると迷惑がかかるので、その辺は配慮してください

```vendor.php

require_once __DIR__ . '/vendor/autoload.php';
  use Goutte\Client;
  $cli = new Client();
  $top = $cli->request('GET', 'https://info.finance.yahoo.co.jp/fx/detail/?code=USDJPY=FX');
  $bid=$top->filter('#USDJPY_detail_bid')->text();
  $ask=$top->filter('#USDJPY_detail_ask')->text();
```


###まるめる
このコードは１２０文字よりあとを...とします
実際は日本語などはマルチバイトなので、６０文字くらいになります


```php
$article = mb_strimwidth($value[""], 0, 120 ,"...","utf8");
```


###検索

ユーザーからの検索ワードを受け付けて、指定したデータベース内を探します


```search.php

$search_word = htmlspecialchars($_GET["search_word"],ENT_QUOTES,'UTF-8');
$page_str = "「{$search_word}」での検索結果";
$keywords_str = "検索結果";
$description_str = "「{$search_word}」での検索結果です。";
if(empty($search_word)) {
  header("Location: {$site_url}");
  exit();
}else{
  $not_words = array(",", "、", "　", "。", ".");
  $clean_search = str_replace($not_words, '/', $search_word);
  $search_words = explode('/',$clean_search);
}
echo "「{$search_word}」での検索結果";
$sql .= " OR concat(trade_name,repayment_method,description_str) LIKE ':search_words'";
$stmt->bindValue(':search_words',"%{$search_words[$i]}%",PDO::PARAM_STR);
```


###phpのエラー表示をする


```php
ini_set('display_errors',1);
error_reporting(E_ALL);
```

##主にjavascriptとhtml(フロントサイド)関連
###ajaxと連動プルダウン

これは、北海道と青森県のどちらかを選択すると、その県にある一部の市のプルダウンが現れます


```html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" >
$(function(){
  $('input[type="number"]').change(function(){
    var data = (
      $('input').serialize());
    $.ajax({
      type: "POST",
      url:  "指定しないなら自身にかえって来ます",
      data: data
    }).done(function(data){
        $("#answer").html(data);
    }).fail(function(data){
        $("#answer").text("fail");
    });
  });
});
</script>
<script type="text/javascript">
$(document).ready(function(){
    var pd2 = $("#ma_code option").clone();
    $("#sv_code").change(function () {
        var lv1Val = $("#sv_code").val();
        $("#ma_code").removeAttr("disabled");
        $("#ma_code option").remove();
        $(pd2).appendTo("#ma_code");
        $("#ma_code option[class != "+lv1Val+"]").remove();
        $("#ma_code").prepend('<option value="no_area" selected>選択して下さい</option>');
        $("#sa_code").attr("disabled", "disabled");
        $("#sa_code option").remove();
        $("#sa_code").prepend('<option value="no_area" selected>選択して下さい</option>');
    });
});
</script>
</head>
<body>
  <select id="sv_code" >
    <option value="no_area">選択して下さい</option>
    <option value="1">北海道</option>
    <option value="2">青森県</option>
  </select>

  <select id="ma_code">
    <option value="no_area">選択して下さい</option>
    <option value="函館市" class="1">函館市</option>
    <option value="旭川市" class="1">旭川市</option>
    <option value="弘前市" class="2">弘前市</option>
    <option value="青森市" class="2">青森市</option>
  </select>
</body>
</html>
```

##便利なツール 

babel-preseset  
　 //phpからjavascriptを生成してくれる

http://caniuse.com/
　　//使いたいhtmlの属性などが、どのブラウザで対応しているか調べられる

##メモ

###php関連メモ

PHP_EOL
 //いい感じに改行

<pre><?php?></pre>　
　　// ブラウザで見やすく改行

$_ スーパーグローバル関数
$$a //可変変数
$a()//可変関数

(int)$a
 //型指定 (キャスト割り当てる）演算子

instanceof
　　//型演算子　

urlencode()
　　//空白やマルチバイトurlをエンコード　
urldecode()
　　//デコード


$_server['php_self’]で今のurlがパラメータなしで取得できる
header("location:".$url)は以下を読み込まない時exit()を書く 
リダイレクトと言う
絶対パスでないといけないので$url="http://".$_server['http_host'].dirname($_server[‘php_self']);
などとする


phpは変数定数のみ大文字小文字区別する

implode(",",$a); 配列から文字列にできる
checkbox[]を文字列として一つのカラムに挿入するときに便利

str_ireplace()
　　//大文字小文字区別せず検索して置換 引数配列指定可
mb_substr()
　　//マルチバイト文字を抜く
trim()
　　//全角空白とる

関数定義の時、引数の数がわからないなら...が使える
引数は型指定（タイプヒンティング）できる

セッションスタートとデストロイの前に空白改行htmlがあってはダメ　　　'？>'省略で防げる

トランザクションはどちらかのsql1,2,3...が失敗した時終了しrollback()で全てなかったことにする


###sql関連

長いカラム名ならasでエイリアスを指定できる

alter table rename でテーブル名変更できる

外部キーはインデックスをつける
リレーションキーも定義する
リレーションキーなどよく使うカラムはindexをつけると高速化する 


###html5関連
input　type にスライダーがある

required属性でフォーム入力バリデーションができるが、これさえあれば安心ではなく、サーバーサイドでも検証すべき