PHP 【保存版!!】PHPからMySQLに接続する方法etc【データベース】

  • 6
    いいね
  • 1
    コメント

データベース



PDO説明.png

ユーザー

データベースを作ったら、このデータベースに
アクセスして操作できるユーザーを作る。
MySQLをインストールしてまもないときは、
rootという管理者権限を持つユーザーが既にいる。
rootユーザーは全てのデータベースを操れるので危険。
なので、データベースを作ったら、
このデータベースだけを操作できるユーザーを作り、
PHPでプログラムを書くときでもそのユーザーで
データベースにアクセスする方が、
他のデータベースを不正利用されず安全

SQLから

コマンドプロンプトからMySQLへ接続

方法①
mysql -u root -p  Enter
Password:password
方法② 192.168.1.30にはホスト名を入れる
mysql -h 192.168.1.30 -u ユーザー名 -p

データベースでユーザー一覧を表示する

# mysql -u root -p
Enter password: ********
Welcome to the MySQL monitor.  
mysql> select Host, User FROM mysql.user;
+-----------+------+
| Host      | User |
+-----------+------+
| linux     |      |
| linux     | root |
| localhost |      |
| localhost | pma  |
| localhost | root |
+-----------+------+
5 rows in set (0.02 sec)

ユーザーの作成

mysql> grant all on test.* to 'testuser'@'localhost' identified by 'root';
Query OK, 0 rows affected (0.02 sec)

確認すると...

mysql> SELECT user,host FROM mysql.user;
+----------+-----------+
| user     | host      |
+----------+-----------+
|          | linux     |
| root     | linux     |
|          | localhost |
| pma      | localhost |
| root     | localhost |
| testuser | localhost |
+----------+-----------+

testuserというユーザーがちゃんとありました

作成したユーザーでMySQLにログイン

# mysql -u testuser -p
Enter password: ****
Welcome to the MySQL monitor.

テーブル作成

使用例


mysql> use takahashi1
Database changed
mysql> create table words(id int auto_increment primary key,word varchar(100),se
nse varchar(250),memo varchar(250));
Query OK, 0 rows affected (0.09 sec)

mysql> show fields from words;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| word  | varchar(100) | YES  |     | NULL    |                |
| sense | varchar(250) | YES  |     | NULL    |                |
| memo  | varchar(250) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+

テーブルにデータを追加

201701108.png

201701107.png

mysql> insert into product values(null, 'バターピーナッツ',200);
Query OK, 1 row affected (0.12 sec)

mysql> select * from product;
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  1 | 松の実             |   700 |
|  2 | くるみ             |   270 |
|  3 | ひまわりの種       |   210 |
|  4 | アーモンド         |   220 |
|  5 | カシューナッツ     |   250 |
|  6 | ジャイアントコーン |   180 |
|  7 | ピスタチオ         |   310 |
|  8 | マカダミアナッツ   |   600 |
|  9 | かぼちゃの種       |   180 |
| 10 | ピーナッツ         |   150 |
| 11 | クコの実           |   400 |
| 13 | バターピーナッツ   |   200 |
+----+--------------------+-------+
敬語ノートに追加
mysql> insert into honorifics values(null,'無視してください','ご放念ください','
謝礼のほうはご放念ください');
Query OK, 1 row affected (0.03 sec)
敬語学習ノートに追加(例文はnullで)
mysql> insert into honorifics values(null,'~がこのように申しております','~がこ
のように言っています',null);
Query OK, 1 row affected (0.03 sec)

mysql> show fields from honorifics;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| id             | int(11)      | NO   | PRI | NULL    | auto_increment |
| wrongHonorific | varchar(100) | YES  |     | NULL    |                |
| rightHonorific | varchar(100) | YES  |     | NULL    |                |
| example        | varchar(250) | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+

テーブル一覧

使用例

SHOW TABLES FROM データベース名;

testというデータベース名のテーブル一覧を表示...


mysql> show tables from test;
+----------------+
| Tables_in_test |
+----------------+
| week           |
+----------------+

テーブルに登録されたデータ一覧表示

使用例

select * from テーブル名;

mysql> select * from product;
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  1 | 松の実             |   700 |
|  2 | くるみ             |   270 |
|  3 | ひまわりの種       |   210 |
|  4 | アーモンド         |   220 |
|  5 | カシューナッツ     |   250 |
|  6 | ジャイアントコーン |   180 |
|  7 | ピスタチオ         |   310 |
|  8 | マカダミアナッツ   |   600 |
|  9 | かぼちゃの種       |   180 |
| 10 | ピーナッツ         |   150 |
| 11 | クコの実           |   400 |
+----+--------------------+-------+

テーブルのフィールド一覧表示

使用例

mysql> SHOW FIELDS FROM テーブル名;

productというテーブル名のフィールド一覧を表示


mysql> show fields from product;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(200) | NO   |     | NULL    |                |
| price | int(11)      | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
使用例②

mysql> select id from product;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
|  7 |
|  8 |
|  9 |
| 10 |
| 11 |
+----+

テーブルにカラムを追加

201701241.png

テーブルにカラムを追加
mysql> alter table honorific add example varchar(250);
Query OK, 0 rows affected (0.15 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show fields from honorific;
+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| id               | int(11)      | NO   | PRI | NULL    | auto_increment |
| wrongHonorific   | varchar(100) | YES  |     | NULL    |                |
| correctHonorific | varchar(100) | NO   |     | NULL    |                |
| example          | varchar(250) | YES  |     | NULL    |                |
+------------------+--------------+------+-----+---------+----------------+

SQLで商品名で商品を検索

使用例

mysql> select * from テーブル名 where 列名='検索キーワード;

productテーブルのnameという列の中にカシューナッツがあるか検索する


mysql> select * from product where name='カシューナッツ';
+----+----------------+-------+
| id | name           | price |
+----+----------------+-------+
|  5 | カシューナッツ |   250 |
+----+----------------+-------+

SQLで商品を更新するSQL文

カラム.png

zu01.jpg
201701122.png

更新前
mysql> select * from product;
+----+--------------------------------------------------------+-------+
| id | name                                                   | price |
+----+--------------------------------------------------------+-------+
|  1 | 松の実                                                 |   700 |
|  2 | くるみ                                                 |   270 |
|  3 | ひまわりの種                                           |   210 |
name列の値を「高級松の実」にし、同時にpriceを「900」に
mysql> update product set name='高級松の実', price=900 where id=1;
Query OK, 1 row affected (0.09 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from product;
+----+--------------------------------------------------------+-------+
| id | name                                                   | price |
+----+--------------------------------------------------------+-------+
|  1 | 高級松の実                                             |   900 |
|  2 | くるみ                                                 |   270 |
|  3 | ひまわりの種                                           |   210 |
価格だけを「800」に変更する
mysql> update product set price=800 where id=1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from product;
+----+--------------------------------------------------------+-------+
| id | name                                                   | price |
+----+--------------------------------------------------------+-------+
|  1 | 高級松の実                                             |   800 |
|  2 | くるみ                                                 |   270 |
|  3 | ひまわりの種                                           |   210 |

SQLでテーブルのデータを削除

「アーモンド」というnameのデータを削除
mysql> select * from product;
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  1 | 松の実             |   700 |
|  2 | くるみ             |   270 |
|  3 | ひまわりの種       |   210 |
|  4 | アーモンド         |   220 |
|  5 | カシューナッツ     |   250 |
|  6 | ジャイアントコーン |   180 |
|  7 | ピスタチオ         |   310 |
|  8 | マカダミアナッツ   |   600 |
|  9 | かぼちゃの種       |   180 |
| 10 | ピーナッツ         |   150 |
| 11 | クコの実           |   400 |
| 13 | バターピーナッツ   |   200 |
| 14 | ローストピーナッツ |   220 |
| 15 | アーモンド         |   320 |
+----+--------------------+-------+
14 rows in set (0.01 sec)

mysql> delete from product where name='アーモンド';
Query OK, 2 rows affected (0.06 sec)

mysql> select * from product;
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  1 | 松の実             |   700 |
|  2 | くるみ             |   270 |
|  3 | ひまわりの種       |   210 |
|  5 | カシューナッツ     |   250 |
|  6 | ジャイアントコーン |   180 |
|  7 | ピスタチオ         |   310 |
|  8 | マカダミアナッツ   |   600 |
|  9 | かぼちゃの種       |   180 |
| 10 | ピーナッツ         |   150 |
| 11 | クコの実           |   400 |
| 13 | バターピーナッツ   |   200 |
| 14 | ローストピーナッツ |   220 |
+----+--------------------+-------+

delete(全体を削除)
delete from テーブル名
(例)productテーブル全体を削除
delete from product

キーワードを含まない商品名の検索

名前に「ナッツ」を含まない商品を検索
mysql> select * from product where name not like '%ナッツ%';
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  1 | 松の実             |   700 |
|  2 | くるみ             |   270 |
|  3 | ひまわりの種       |   210 |
|  4 | アーモンド         |   220 |
|  6 | ジャイアントコーン |   180 |
|  7 | ピスタチオ         |   310 |
|  9 | かぼちゃの種       |   180 |
| 11 | クコの実           |   400 |
+----+--------------------+-------+

like演算子による部分一致検索(ワイルドカード)

「ピーナッツ」を含まない「ナッツ」の商品検索
mysql> select * from product where name like '%ナッツ%' and name not like 'ピー
ナッツ%';
+----+------------------+-------+
| id | name             | price |
+----+------------------+-------+
|  5 | カシューナッツ   |   250 |
|  8 | マカダミアナッツ |   600 |
+----+------------------+-------+
名前の末尾が「ナッツ」の商品を検索
mysql> select * from product where name like '%ナッツ';
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  5 | カシューナッツ     |   250 |
|  8 | マカダミアナッツ   |   600 |
| 10 | ピーナッツ         |   150 |
| 13 | バターピーナッツ   |   200 |
| 14 | ローストピーナッツ |   220 |
+----+--------------------+-------+

PHPから部分一致で商品を検索する

like演算子
201702061.png

名前に「ナッツ」を含む全ての商品を検索
mysql> select * from product where name like '%ナッツ%';
+----+------------------+-------+
| id | name             | price |
+----+------------------+-------+
|  5 | カシューナッツ   |   250 |
|  8 | マカダミアナッツ |   600 |
| 10 | ピーナッツ       |   150 |
+----+------------------+-------+

201701105.png

search-input2.php
商品名を入力してください。
<form action="search-output2.php" method="post">
<input type="text" name="keyword">
<input type="submit" value="検索">
</form>
search-output.php
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>商品価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'select * from product where name like ?' );
$sql->execute(['%'.$_REQUEST['keyword'].'%'])
;
foreach ( $sql->fetchAll () as $row ) {
    echo '<tr>';
    echo '<td>', $row ['id'], '</td>';
    echo '<td>', $row ['name'], '</td>';
    echo '<td>', $row ['price'], '</td>';
    echo '</tr>';
    echo "\n";
}
?>
</table>

NOT NULL制約の削除

20170131.png

mysql> alter table honorifics modify column example varchar(200);

NULL制約を付ける

201702222.png


mysql> alter table words modify column memo varchar(250) null;

UNIQUE制約を付ける

行ごとに全て異なる値になり、他の行と同じ値を格納することができなくなる。
NULLは格納できる。NULLの値だけは複数のカラムで重複して格納することができる。


mysql>login varchar(100) not null unique,

参考サイト

外部キー制約(foreign key)

20170227.png


mysql> create table purchase(id int not null primary key,customer_id int not nul
l,foreign key(customer_id) references customer(id));

「purchaseテーブルのcustomer_id列には、customerテーブルのid列に存在する値だけが格納できる」

foreign key=外部キー制約

  さまざまな制約
foreign key 外部キー制約を指定した列には、外部のテーブルにある指定した列に含まれる値だけが格納できるようになる
unique 行ごとに全て異なる値になり、他の行と同じ値を格納することができなくなる
primary key 行ごとに異なる値を割り当てる
複合主キー 複数の列を組み合わせて主キーにしたもの

複合主キー

複数項目でワンセットな主キー。
複数の項目で一意に識別できる主キーのこと。

複合主キー.png

参考サイト

varchar

  さまざまな型
char(4) 固定長文字列。char(4)4文字ぴったりしか格納できない
varchar(バイト数) 可変長文字列。varchar(4)最大4バイトの文字列を格納できる

PHPから

PHPからデータベースに接続

■PDO()コンストラクタ
PDO('mysql:host=localhost;dbname=データベース名;charset=utf8','接続するユーザー名','パスワード'

all.php
<?php
$pdo=new PDO('mysql:host=localhost;dbname=shop;charset=utf8',
    'staff', 'password');
?>
connect.phpMySQLのデフォルトポート番号は「3306」です
<?php
try {
    $sql = new PDO ( 'mysql:dbname=takahashi1; host=192.168.1.30;port=3306; charset=utf8', 'takahashi', 'takahashi' );
    print '接続に成功しました。';
} catch ( PDOException $e ) {
    print "接続エラー:{$e->getMessage()}";
}
$sql = null;
?>

DBへ接続するファイルを外部化

selfphpフォルダーの中にあるDbManager.php

DbManager.php
<?php
function getDb() {
    // データベースへの接続を確認
    $pdo = new PDO ( 'mysql:dbname=takahashi1; host=192.168.1.30;port=3306; charset=utf8', 'takahashi', 'takahashi' );
    return $pdo;
}
?>
connection_common.php
<?php
require_once 'selfphp/DbManager.php';
$pdo = getDb();

mysqli()で接続

$db = new mysqli('192.168.1.30','takahashi','takahashi','takahashi1');
// $db = new mysqli( 'localhost', 'staff', 'password', 'shop' );
if ($db->connect_error) {
    echo $db->connect_error;
    exit ();
} else {
    $db->set_charset ( "utf8" );
    echo 'ok';
}

クラスに記述した関数(メソッド)と変数(プロパティ)

  クラス内に記述した変数と関数のみ名称が変わる
プロパティ クラスに属する変数
メソッド クラスに属する関数
  クラス内に記述したときの名称
変数 プロパティ
関数 メソッド
クラスを定義する構文
class クラス名 {
    $プロパティ名

    function メソッド名(引数) {
    }
}

参考元サイト

PDOクラスを使用

PDOクラスを使用するにはPDOのインスタンスを生成する

PDOのインスタンスの生成
$pdo = new PDO(....);

$pdo←名前は自由

コンストラクタ

  • コンストラクタ、_________________________________
    コンストラクタ
    ・コンストラクタとはクラスからオブジェクトがnewによって作成される時に自動的に呼び出されるメソッドです。オブジェクト作成時に初期化処理が必要な場合など、コンストラクタ内に記述しておけば自動的に実行してくれます
    _________________________________________________________

■PDO(....)

$pdo=new PDO('mysql:host=localhost;dbname=shop;charset=utf8',
    'staff', 'password');
?>

コンストラクタ。
コンストラクタの....の部分には
インスタンスの初期化に用いる引数を書く。
データベースに接続するために必要な引数を記述。
PDO(引数)の引数はDSNと呼ばれている。

▪️DSN
どのサーバーにあるどんなデータベースを使うのかを指定した文字列

PHPからSQL文を実行(query)

PHPからSQLのselect文を実行
$pdo->query('select * from product')

query

  PHPからSQL文を実行
SQL文を実行 PDOの変数->query('SQL文')
メソッドを呼び出す 変数->メソッド
queryメソッド(関数) 引数に指定したSQL文をデータベースに対して実行する
->(アロー演算子) メソッドを呼び出す
  • メソッド呼び出し(例)
class CrepeShop {
    public function buy($crepe) {
        $message = '';
        if ($crepe == 'チョコ') {
            $message = $crepe.'は330円です';
        } else if ($crepe == '生クリーム') {
            $message = $crepe.'は270円です';
        } else {
            $message = 'クレープを選択して下さい';
        }
        return $message;
    }
}
$customer = new CrepeShop ();
echo $customer->buy ( '生クリーム' );//生クリームは270円です
echo $customer->buy('チョコ');//チョコは330円です

結果セット

PHPで接続したデータベースから情報一覧を表示

取得したデータを一行ずつ表示する(方法①)
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row2 ) {
    echo '<p>';
    echo $row2 ['id'], ':';
    echo $row2 ['name'], ':';
    echo $row2 ['price'];
    echo '</p>';
}
?>
取得したデータを一行ずつ表示する(方法②)
<?php
$pdo=new PDO('mysql:host=localhost;dbname=shop;charset=utf8',
    'staff', 'password');
foreach ($pdo->query('select * from product') as $row) {
    echo "<p>$row[id]:$row[name]:$row[price]</p>";
}
?>
実行結果
1:松の実:700

2:くるみ:270

3:ひまわりの種:210

4:アーモンド:220

5:カシューナッツ:250

6:ジャイアントコーン:180

7:ピスタチオ:310

8:マカダミアナッツ:600

9:かぼちゃの種:180

10:ピーナッツ:150

11:クコの実:400
取得したデータを一行ずつ処理する
foreach ( $pdo->query ( 'select * from product' ) as $row2 ) {
}

■列のデータを取り出す
配列['列名']

zu01.jpg

(例)id列のデータを表示
echo $row['id'];//1
  • <質問> $pdo->query ( 'select * from product' ) は配列? foreachは確か、 配列とオブジェクトをループして使うための制御構文と学びました。_________________________________
    <解答>
    配列では、無いのですが、 使い易くするために、特別に foreach の反復処理で使える様に作られています。 マニュアルを見ましょう。

http://php.net/manual/ja/pdo.query.php


方法①
foreach ( $pdo->query ( 'select * from product' ) as $row2 ) {
    echo '<p>';
    echo $row2 ['id'], ':';
    echo $row2 ['name'], ':';
    echo $row2 ['price'];
    echo '</p>';
}

何故$row2['id']ではなく$row2[id]?

方法②
foreach ($pdo->query('select * from product') as $row) {
    echo "<p>$row[id]:$row[name]:$row[price]</p>";
}
HTMLの表を使って見やすく表示する
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row ) {
    echo '<tr>';
    echo '<td>', $row ['id'], '</td>';
    echo '<td>', $row ['name'], '</td>';
    echo '<td>', $row ['price'], '</td>';
    echo '</tr>';
    echo "\n";
}
?>
</table>

■実行結果
20170104.png

htmlspecialcharsでより安全に

htmlspecialchars関数でJavascriptのタグを無効化


htmlspecialchars('文字列',エスケープの種類,'文字コード')
エスケープの種類(方法) 概要
ENT_COMPAT ダブルクォートは置き換えるが、シングルクォートは置き換えない
ENT_QUOTES シングルクォートとダブルクォートの両方を置き換える
ENT_NOQUOTES シングルクォートとダブルクォートの両方を置き換えない
all5.php
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
function h($str) {
    return htmlspecialchars ( $str );
}
foreach ( $pdo->query ( 'select * from product' ) as $row ) {
    echo '<tr>';
    echo '<td>' . h ( $row ['id'] ), '</td>';
    echo '<td>', h ( $row ['name'] ), '</td>';
    echo '<td>', h ( $row ['price'] ), '</td>';
    echo '</tr>';
    echo "\n";
}
?>
</table>
例②
<?php
        function h($str) {
            return nl2br ( htmlspecialchars ( $str, ENT_QUOTES, 'UTF-8' ), false );
        }
        ?>
        <p class="textstyle">
            ■お問い合わせ項目:</br><?php if (isset($_SESSION['object'])){ echo '<font color="black">'.implode("</br>", $_SESSION['object']).'</font>';}?></p>
        <p class="textstyle">
            ■お問い合わせ内容:</br><?php if(isset($_SESSION['contactContent'])){echo h($_SESSION['contactContent']).'</font>';}?>
?>
方法①
function h($str) {
    return htmlspecialchars ( $str, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
}
方法②
function e($str, $charset = 'UTF-8') {
    return htmlspecialchars ( $str, ENT_QUOTES | ENT_HTML5, $charset );
}

htmlspecialcharsで対策していないと。。。


MySQLに商品のデータを追加


mysql> insert into product values(null, '',100);
all5.php
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row ) {
    echo '<tr>';
    echo '<td>' . $row ['id'], '</td>';
    echo '<td>' . $row ['name'], '</td>';
    echo '<td>' . $row ['price'], '</td>';
    echo '</tr>';
    echo "\n";
}
?>
</table>

all5.phpを実行
20170110.png

OKボタン押下後↓
201701102.png

htmlspecialchars対策&PHPで入力値を確認してから商品を追加する

insert-input2.php
<p>商品を追加します。</p>
<form action="insert-output2.php" method="post">
商品名<input type="text" name="name">
価格<input type="text" name="price">
<input type="submit" value="追加">
</form>

201701116.png
201701121.png

insert-output2.php方法①
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'insert into product values(null, ?, ?)' );
$err = array ();
if (empty ( $_REQUEST ['name'] )) {
    $err ['name'] = '商品名を入力してください。';
}
if ((preg_match ( '/^[a-zA-Z]+$/', $_REQUEST ['name'] ) || preg_match ( "/^[一-龠]+$/u", $_REQUEST ['name'] )) && ! strlen ( $_REQUEST ['name'] ) == 0) {
    $err ['name'] = '商品名はひらがな又はカタカナで入力してください。';
}
if (empty ( $_REQUEST ['price'] )) {
    $err ['price'] = '価格を入力してください。';
} else if (! preg_match ( '/[0-9]+/', $_REQUEST ['price'] ) && ! strlen ( $_REQUEST ['price'] ) == 0) {
    $err ['price'] = '商品価格は整数で入力してください。';
}
if (count ( $err ) >= 1) {
    if (isset ( $err ['name'] )) {
        echo $err ['name'].'</br>';
    }
    if (isset ( $err ['price'] )) {
        echo $err ['price'];
    }
}else
if ($sql->execute(
    [htmlspecialchars($_REQUEST['name']), $_REQUEST['price']]
))
{
    echo '追加に成功しました。';
} else {
    echo '追加に失敗しました。';
}
?>
<p>
    <button onclick="history.back()">戻る</button>
</p>
insert-output2.php方法②
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'insert into product values(null, ?, ?)' );
$err = array ();
function h($str) {
    return htmlspecialchars ( $str );
}
if (empty ( $_REQUEST ['name'] )) {
    $err ['name'] = '商品名を入力してください。';
}
if ((preg_match ( '/^[a-zA-Z]+$/', $_REQUEST ['name'] ) || preg_match ( "/^[一-龠]+$/u", $_REQUEST ['name'] )) && ! strlen ( $_REQUEST ['name'] ) == 0) {
    $err ['name'] = '商品名はひらがな又はカタカナで入力してください。';
}
if (empty ( $_REQUEST ['price'] )) {
    $err ['price'] = '価格を入力してください。';
} else if (! preg_match ( '/[0-9]+/', $_REQUEST ['price'] ) && ! strlen ( $_REQUEST ['price'] ) == 0) {
    $err ['price'] = '商品価格は整数で入力してください。';
}
if (count ( $err ) >= 1) {
    if (isset ( $err ['name'] )) {
        echo $err ['name'] . '</br>';
    }
    if (isset ( $err ['price'] )) {
        echo $err ['price'];
    }
}else
if ($sql->execute(
    [h($_REQUEST['name']), $_REQUEST['price']]
))

{
    echo '追加に成功しました。';
} else {
    echo '追加に失敗しました。';
}
?>
<p>
    <button onclick="history.back()">戻る</button>
</p>

201701112.png
201701113.png
201701115.png

htmlentities()

この関数はhtmlspecialchars()と同じですが、 HTML エンティティと等価な意味を有する文字をHTMLエンティティに変換します。

商品データを検索するP206

2017011003.png
201702061.png

search-input.php
商品名を入力してください。
<form action="search-output.php" method="post">
<input type="text" name="keyword">
<input type="submit" value="検索">
</form>
search-output.php
<?php require 'header.php'; ?>
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>商品価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
// ?の部分には後から好きな値を設定することが出来る
$sql = $pdo->prepare ( 'select * from product where name=?' );
$sql->execute([$_REQUEST['keyword']])
;
foreach ( $sql->fetchAll () as $row ) {
    echo '<tr>';
    echo '<td>', $row ['id'], '</td>';
    echo '<td>', $row ['name'], '</td>';
    echo '<td>', $row ['price'], '</td>';
    echo '</tr>';
    echo "\n";
}
?>
</table>
<?php require 'footer.php'; ?>

20170105.png

PDOの変数->query('SQL文') 引数に指定したSQL文をデータベースに対して実行する
PDOの変数->prepare('SQL文') SQL文を実行する準備をする
変数->execute([値]) SQL文の実行
foreach(PDOの変数->fetchAll() as 結果を代入する変数) 結果を1行ずつ取得して、変数$rowに代入する

prepareメソッド

PDOの変数->prepare('SQL文') SQL文を実行する準備をする

20170106.png
prepareメソッド
PDOStatement::execute() メソッドによって実行される SQL文を準備する。
SQL文は、文が実行されるときに実際の値に置き換えられる疑問符(?)やパラメーターマーク等を含むことができる。
201701062.png
201601063.png
201701064.png

prepareメソッドの引数には、SQL文を文字列で指定する。
SQL文のなかに「?」を含めることができ、
「?」の部分には後から好きな値を設定することが出来る。

select文で取得したテーブルのなかからwhere句で指定した条件に一致する行を取得する
select * from product where name=?
$pdo->prepare('select * from product where name=?')

executeメソッド

変数->execute([値]) prepareメソッドに引数として渡したSQL文を実行する

201701065.png

$sql->execute([$_REQUEST['keyword']]);

executeメソッドの引数には、
SQL文のなかの「?」部分に設定する値を配列にして渡す。
配列にするのは、1つのSQL文内に複数箇所の?を配置することができるから。
201701201.png
201701202.png

  • 複数の?がある場合_______________________________ 2017011010.png

変数->execute([値])

・複数の?がある場合は、外側を[]で囲み、
複数の値を「,」で区切って
[値, 値, ...]のように並べる。
?が1個だけの場合には[値]のように外側を[]で囲むだけ。

ここではkeywordという名前のリクエストパラメータを使う
$_REQUEST['keyword']
[]で囲んで配列にする
$sql->execute([$_REQUEST['keyword']]);
select * from product where name=?
↑のようなSQL文に入力欄に入力した商品名が設定されて、↓のようなSQL文となって実行される。
select * from product where name=`カシューナッツ`

_________________________________________________________
201701066.png

20170223.png
201702231.png

executeはqueryで取得可能

executeメソッドで実行した結果はfetchAllで
取得しなくてもいい場合がある。
結果セットのPDOStatement型データを返すので、
それを一行ずつ$rowに格納してforeach()ループで一行ずつ読み出しているので問題ありません。

一度に結果全行を読み出すのと、
結果一行ずつすべて読むのとどう違うかというと、
全行読み出すとき結果のレコード数が数千数万だったりすると、
結果を溜め込むまで一見処理が止まってしまいます。
(メモリ的リソースもきつくなります。)
一行ずつ読み出すと、順々にHTML出力ができて止まらず出力し続けられます。
(溜め込まないため軽く動かせるはず。)
(executeメソッドで実行した結果はqueryで取得できる)[https://teratail.com/questions/67076]

query 結果一行ずつすべて読む
fetchAll() 結果データを全件まとめて配列で取得

--

exec()メソッド

exec() SQLステートメントを実行し、作用した行数を返す。PDOオブジェクトに対して実行可能な、PHPからSQLを実行するためのメソッド。
execute() PDOStatementのインスタンスに対して実行可能な、prepareメソッドで用意したSQL文を実行するメソッド。

exec()とexecute()の違い

fetchAllメソッド

2017011004.png

foreach(PDOの変数->fetchAll() as 結果を代入する変数) SQL文をexecuteメソッドで実行した結果を取得する
fetch() 1件データを取得
fetchAll() 結果データを全件まとめて配列で取得

PHPから商品データを追加する

201701109.png

テーブルの最後に「ローストピーナッツ」が追加されている
mysql> select * from product;
+----+--------------------+-------+
| id | name               | price |
+----+--------------------+-------+
|  1 | 松の実             |   700 |
|  2 | くるみ             |   270 |
|  3 | ひまわりの種       |   210 |
|  4 | アーモンド         |   220 |
|  5 | カシューナッツ     |   250 |
|  6 | ジャイアントコーン |   180 |
|  7 | ピスタチオ         |   310 |
|  8 | マカダミアナッツ   |   600 |
|  9 | かぼちゃの種       |   180 |
| 10 | ピーナッツ         |   150 |
| 11 | クコの実           |   400 |
| 13 | バターピーナッツ   |   200 |
| 14 | ローストピーナッツ |   220 |
+----+--------------------+-------+
PDOの変数->prepare('SQL文') SQL文を実行する準備をする
変数->execute([値]) SQL文の実行
foreach(PDOの変数->fetchAll() as 結果を代入する変数) 結果を1行ずつ取得して、変数$rowに代入する
insert-input.php
<p>商品を追加します。</p>
<form action="insert-output.php" method="post">
商品名<input type="text" name="name">
価格<input type="text" name="price">
<input type="submit" value="追加">
</form>
insert-output.php方法①
<?php
$pdo=new PDO('mysql:host=localhost;dbname=shop;charset=utf8',
    'staff', 'password');
$sql=$pdo->prepare('insert into product values(null, ?, ?)');
if ($sql->execute([$_REQUEST['name'], $_REQUEST['price']])) {
    echo '追加に成功しました。';
} else {
    echo '追加に失敗しました。';
}
?>
insert-output.php方法②
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'insert into product values(null, ?, ?)' );
if ($sql->execute ( array (
        $_REQUEST ['name'],
        $_REQUEST ['price']
) )) {
    echo '追加に成功しました。';
} else {
    echo '追加に失敗しました。';
}
?>

type属性をhiddenにする

201701123.png
隠しデータを送信することができる。
ユーザーには見せる必要のない隠し情報をフォーム内に埋め込むことができる。 この情報は、ブラウザ上には表示されない。
hidden

type="hidden"なので画面には表示されない
echo '<input type="hidden" name="id" value="', $row['id'], '">';

201701124.png

PHPから商品データを更新する

update-input.php
<?php require 'header.php';?>
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>商品価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row ) {
    echo '<tr><form action="update-output.php" method="post">';
    // type="hidden"にすることでフォームに商品番号を含めつつも編集できないようにしている
    echo '<input type="hidden" name="id" value="', $row ['id'], '">';
    echo '<td>', $row ['id'], '</td>';
    echo '<td>';
    echo '<input type="text" name="name" value="', $row ['name'], '">';
    echo '</td>';
    echo '<td>';
    echo '<input type="text" name="price" value="', $row ['price'], '">';
    echo '</td>';
    echo '<td><input type="submit" value="更新"></td>';
    echo '</form></tr>';
    echo "\n";
}
?>
</table>
<?php require 'footer.php';?>
update-output.php
<?php require 'header.php';?>
<?php

$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'update product set name=?, price=? where id=?' );
$err = array ();
function h($str) {
    return htmlspecialchars ( $str );
}
if (empty ( $_REQUEST ['name'] )) {
    $err ['name'] = '商品名を入力してください。';
}
if ((preg_match ( '/^[a-zA-Z]+$/', $_REQUEST ['name'] ) || preg_match ( "/^[一-龠]+$/u", $_REQUEST ['name'] ) || preg_match ( '/[0-9]+/', $_REQUEST ['name'] )) && ! strlen ( $_REQUEST ['name'] ) == 0) {
    $err ['name'] = '商品名はひらがな又はカタカナで入力してください。';
}
if (empty ( $_REQUEST ['price'] )) {
    $err ['price'] = '価格を入力してください。';
} else if (! preg_match ( '/[0-9]+/', $_REQUEST ['price'] ) && ! strlen ( $_REQUEST ['price'] ) == 0) {
    $err ['price'] = '商品価格は整数で入力してください。';
}
if (count ( $err ) >= 1) {
    if (isset ( $err ['name'] )) {
        echo $err ['name'] . '</br>';
    }
    if (isset ( $err ['price'] )) {
        echo $err ['price'];
    }
}else
    if($sql -> execute(
        [h($_REQUEST['name']),
        $_REQUEST['price'], $_REQUEST['id']]
))


{
    echo '更新に成功しました。';
}else {
        echo '更新に失敗しました。';
}
?>
<p>
    <button onclick="history.back()">戻る</button>
</p>
<?php require 'footer.php';?>

201701132.png

PHPから商品データを削除する

201701161.png
201701163.png

test16.php
<p>
    <a href="test16-output.php?id=1&name=値">次に</a>
</p>
test16-output.php
<?php
$id = $_GET ['id'];
$name = $_GET ['name'];
echo $id . "<br/>";
echo $name;
?>
実行結果
1

delete-input2.php
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>商品価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row ) {

    echo '<tr>';
    echo '<td>', $row ['id'], '</td>';
    echo '<td>', $row ['name'], '</td>';
    echo '<td>', $row ['price'], '</td>';
    echo '<td>';
    echo '<a href="delete-output2.php?id=', $row ['id'], '">削除</a>';
    echo '</td>';
    echo '</tr>';
    echo "\n";
}
?>
</table>
delete-output2.php
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'delete from product where id=?' );

if ($sql->execute([$_REQUEST['id']]))
{
    echo '削除に成功しました。';
} else {
    echo '削除に失敗しました。';
}
?>
<p>
    <button onclick="history.back()">戻る</button>
</p>

201701172.png

PHPから商品データを削除する②

delete-input.php
<table>
    <tr>
        <th>商品番号</th>
        <th>商品名</th>
        <th>商品価格</th>
    </tr>
<?php
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
foreach ( $pdo->query ( 'select * from product' ) as $row ) {

    echo '<tr>';
    echo '<td>', $row ['id'], '</td>';
    echo '<td>', $row ['name'], '</td>';
    echo '<td>', $row ['price'], '</td>';
    echo '<td>';
    echo '<form action="delete-output.php" method="post"><input type="hidden" name="id" value="'.$row['id'].'"><input type="submit" value="削除"  name="submit"></form>';
    echo '</td>';
    echo '</tr>';
    echo "\n";
}

?>
</table>
delete-output.php
<?php

// var_dump ( $_POST );
// var_dump($_POST['id']);
$pdo = new PDO ( 'mysql:host=localhost;dbname=shop;charset=utf8', 'staff', 'password' );
$sql = $pdo->prepare ( 'delete from product where id=?' );
// is_numeric→変数が数値または数値文字列かどうか調べる
// is_string→文字列型かどうか調べる関数
// 条件?TRUEの場合の返却値:FALSEの場合の返却値;
$id = isset ( $_POST ['id'] ) ? $_POST ['id'] : '';
// $id = isset($_POST['id']) && is_string($_POST['id'])?$_POST['id']:'';
// array→配列を生成する。
if($sql->execute([$id])){
// if ($sql->execute ( array ($id) )) {
    echo '削除に成功しました。';
} else {
    echo '削除に失敗しました。';
}
// var_dump(array ($id));
?>
<p>
    <button onclick="history.back()">戻る</button>
</p>

20170123.png

PHP5.4以前

201701201.png
201701202.png

PHP5.4以降の書き方login-output.php
<?php
session_start();
unset($_SESSION['customer']);
$pdo=new PDO('mysql:host=localhost;dbname=shop;charset=utf8', 
    'staff', 'password');
$sql=$pdo->prepare('select * from customer where login=? and password=?');
$sql->execute([$_REQUEST['login'], $_REQUEST['password']]);
foreach ($sql->fetchAll() as $row) {
    $_SESSION['customer']=[
        'id'=>$row['id'], 'name'=>$row['name'], 
        'address'=>$row['address'], 'login'=>$row['login'], 
        'password'=>$row['password']];
}
if (isset($_SESSION['customer'])) {
    echo 'いらっしゃいませ、', $_SESSION['customer']['name'], 'さん。';
} else {
    echo 'ログイン名またはパスワードが違います。';
}
?>
PHP5.4以前の書き方login-output.php
<?php
session_start ();
unset ( $_SESSION ['customer'] );
$pdo = new PDO ( 'mysql:host=localhost;dbname=takahashi1;charset=utf8', 'takahashi', 'takahashi' );
$sql = $pdo->prepare ( 'select * from customer where login=? and password=?' );
$sql->execute ( array (
        $_REQUEST ['login'],
        $_REQUEST ['password']
) );
foreach ( $sql->fetchAll () as $row ) {
    $_SESSION ['customer'] = array (
            'id' => $row ['id'],
            'name' => $row ['name'],
            'address' => $row ['address'],
            'login' => $row ['login'],
            'password' => $row ['password']
    );
}
if (isset ( $_SESSION ['customer'] )) {
    echo 'いらっしゃいませ、', $_SESSION ['customer'] ['name'], 'さん。';
} else {
    echo 'ログイン名またはパスワードが違います。';
}
?>

PDO(PHP Data Objects)

PDOはクラスの一種。
様々なデータベース(DBMS)を簡単に利用できるようにする、PHPの拡張機能。※拡張→新しい部品などを取り付けて機能を追加する
PDOを使うことで、DBMSの違いを吸収し、
異なるDBMSに対して同じプログラムで
同じ処理をさせることが出来る。
MySQL以外に、Oracle、SQLiteなど様々なデータベース(DBMS)があり、DBMS、それぞれデータベースを使うときのプログラムの書き方が違うから
使うデータベースを変えるとPHPのプログラムを修正する手間がかかる。
これを回避するためにPHPとDBMSの間に抽象化レイヤを挟んでそれぞれさまざまなデータベースの違いを
このレイヤで吸収し、さまざま違うデータベースに同じプログラムで同じ処理をできるようにする
それがPDOの機能。
MySQLへの接続をする関数→mysql_connect関数
PostgreSQLへの接続をする関数→pg_connect関数
システムをMySQLからPostgreSQLに移行するときにプログラムを書き換えないといけない。この手間を防ぐのに抽象化レイヤ(PDO)が使われる。
抽象化レイヤ(PDO)を使えば、どんなデータベースでも
mysql_connect関数で接続できる

PDOクラス
PDO説明

パラメーター

媒介変数、補助変数、母数、引数、設定値などの意味を持つ英単語。
プログラミングでは、関数やメソッドなどが呼び出し元から渡された値を受け取るための変数のことをパラメータという。この意味では仮引数と訳されることもある。

エミュレーション

特定のコンピューターやOS向けに開発されたプログラムを、異なる環境のコンピューターで使うこと。一般的には、OSなどが異なる環境では、プログラムを共用できない。プログラムを異なる環境で動かしたいときは、プログラムの一部やすべてを書き換えてつくり直す必要があり、これを移植という。エミュレーションでは、基本的にはプログラムを書き換えずに、エミュレーターというソフトウェアを介して、疑似的に別のコンピューターの環境を作り出すことで、プログラムを動作させる

エミュレーター

機械を真似る機械。
ある機械部品やソフトウェアを動作させるのに、オリジナルのシステムを用意するのが難しい場合に、オリジナルと全く同じ動作をするより簡便なシステムを用意することがある。この装置をエミュレータと言う。

bindParam

指定された変数名にパラメーターをバインド(関連付ける)する