4
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【PDO】PHPでデータベースに接続する方法【INSERT編】

Last updated at Posted at 2020-02-09

この記事では、《PHPでデータベースに接続する方法》について、
業務を通して学習した内容をまとめています。

  • PDOって何なの?
  • PHPでデータベースにどうやって接続するの?
  • データベースに登録したユーザーを検索する機能を実装したい

こういった疑問に答えます。

※本記事は、自分で学習したことのまとめ用として書いています。
尚、PHPの解説で誤った点があれば、スローして頂ければ喜んでキャッチしますのでお願い致します。

#PDOの基礎
school-2.jpg

現在、PHPでデータベースに接続する際は、『PDO』を使う方法が主流です。そこで、PDOの基本的な使い方を解説していきます。

###概要:PDOとは?
PDO』とは『PHP Data Objects』の略で、ざっくり言うと…

PHPからデータベースへいい感じにアクセスしてくれるもの

です。

通常データベースサーバーへのアクセスは、以下のようなデータベース固有のドライバが使用されます。

  • MySQL
  • PostgreSQL
  • SQLite
  • Oracle
  • MS SQL Server etc…

ですが・・・

PDOを使用することにより、接続するデータベースにかかわらず、同じ操作でデータにアクセスすることが可能になります。

##PDOを使ってPHPでデータベースに接続する方法【ユーザー検索】

startup-1.jpg

PDOを使ってデータベースに接続しユーザー検索するのは、下記の手順で行います。

  1.  PDOクラスをインスタンス化
  2.  プリペアドステートメントを準備する
  3.  値をバインドする
  4.  プリペアドステートメントを実行する
  5.  SELECTの結果を取得する

それでは、ひとつずつ見ていきましょう。

###Step①:PDOクラスをインスタンス化

PDOクラスをインスタンス化して、データベースに接続します。

$pdo = new PDO(
    'DSN',
    'ユーザーネーム',
    'パスワード',
    'オプション'
);

上記の通り、インスタンス化するときに引数に必要な情報を記述することで、データベースに接続できます。

※データベースに接続する際は、例外処理を記述する必要がありますが、現時点ではデータベースへ接続する箇所だけ見ていきます。

また、コンストラクタには、以下のような引数を指定します。

  • DSN (Data Source Name) ※必須
  • ユーザー名
  • パスワード
  • オプション

それぞれ簡単に解説していきます。

####DSN (Data Source Name) ※必須

データベースに接続するために必要な情報です。
以下に各データベース製品に応じたDSNの書き方が掲載されています.

[≫ PHP Manual – PDOクラスのデータベース別DSN一覧]
(https://www.php.net/manual/ja/pdo.drivers.php)

例えば、MySQLの場合は以下のように記述します。

pdo = new PDO(
    'mysql:host=サーバー名;dbname=DB名;charset=文字エンコード',
    'ユーザー名',
    'パスワード',
    'オプション'
);

● mysql:host
ホスト名またはIPアドレスを指定します。

● dbname
データベース名を指定します。基本的には必須ですが、データベースを後で USE test のようにSQL文で選択する場合は、省略することができます。

● charset
文字セットを指定します。SET NAMES とするのは避けて、ここで指定するべきです。UTF-8ではなくutf8であることに注意してください。ハイフンは入りません。

####ユーザー名
ユーザー名を指定します。ルート権限を使う場合は、デフォルトで root です。

####パスワード
パスワードを指定します。ルート権限を使う場合は、デフォルトで空白にします。

####オプション
接続時のオプションを連想配列で渡します。
オプションについては、次で詳しく解説します。

###インスタンス化するときにオプションを設定する方法

データベースに接続するコードを思い出してください。

pdo = new PDO(
    'mysql:host=サーバー名;dbname=DB名;charset=文字エンコード',
    'ユーザー名',
    'パスワード',
    'オプション'
);

上記のように、PDOクラスをインスタンス化する際にオプションを記述することが可能です。

オプションは連想配列で指定し、下記のような記述になります。

pdo = new PDO(
    'mysql:host=サーバー名;dbname=DB名;charset=文字エンコード',
    'ユーザー名',
    'パスワード',
    [
        PDO::ATTR_ERRMODE = PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE = PDO::FETCH_ASSOC
    ]
);

また、よく使われるオプションについては、以下の通りです。

  1.  PDO::ATTR_ERRMODE
  2.  PDO::ATTR_DEFAULT_FETCH_MODE

ひとつずつ簡単に解説していきます。

####オプション①:PDO::ATTR_ERRMODE

SQLでエラーが起こった際の処理について設定します。
尚、デフォルトでは “PDO::ERRMODE_SILENT” と設定されています。

  • PDO::ERRMODE_EXCEPTION

    設定すると、例外(PDOException)を投げてくれます。基本的にこれを選択しておきます。
  • PDO::ERRMODE_WARNING

    設定すると、E_WARNINGメッセージを出力します。
    この設定が返すのはE_WARNINGなので、スクリプトは停止されません。
  • PDO::ERRMODE_SILENT

    デフォルトのエラー設定。エラー内容は保持しているが、エラーメッセージは出力しません。

####オプション②:PDO::ATTR_DEFAULT_FETCH_MODE

fetchメソッドや、fetchAllメソッドで引数が省略された場合のフェッチスタイル(配列のパターン)を設定します。
尚、デフォルトでは “PDO::FETCH_BOTH” と設定されています。

  • PDO::FETCH_ASSOC

    カラム名をキーとする連想配列を返します。基本的にこれを選択しておきます。
  • PDO::FETCH_BOTH

    カラム名と、0から始まるカラム番号をキーとする配列を返します。
  • PDO::FETCH_NUM

    0から始まるカラム番号をキーとする配列を返します。
  • PDO::FETCH_OBJ

    カラム名と同名のプロパティを有するオブジェクトを返します。

###Step②:プリペアドステートメントを準備する
executeメソッドによって実行されるプリペアドステートメントを準備します。

  • プレースホルダ

    ユーザが入力した内容を後から挿入するために、予め確保した場所のこと。
  • プリペアドステートメント

    SQL文で値がいつでも変更できるように、変更する箇所だけ変数のようにしたSQL文を作る仕組みのことです。
    通常「プリペアドステートメント」は「プレースホルダ」を使うために作られます。

プレースホルダには…

  • 疑問符プレースホルダ
  • 名前付きプレースホルダ

の2種類がありますが、仮にこれらが混ざってしまうと…

SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters

が発生するので、どちらか片方を選択してください。

尚、ここでは『名前付きプレースホルダ』についてのみ解説します。

####名前付きプレースホルダ

  • :を頭につけ、半角英数字とアンダースコアにて構成
  • バインド時の頭の:は省略可能

PDOクラスのprepareメソッドを使い、SQL文を実行する準備を行います。

prepareメソッドは、返り値としてPDOStatementのインスタンスを返します。

仮に、データベースサーバーが文を準備できなかった場合、 prepareメソッドは FALSE を返すか、例外(PDOException)をスローします。(エラー処理の方法に依存します)

下記では、作成されたインスタンスを変数$stmtに代入しています。

$spl = (
    'INSERT INTO
        'テーブル名'(USER_ID, USER_NAME, PASSWORD)
    VALUES
        (:USER_ID, :USER_NAME, :PASSWORD)'
);

$stmt = $pdo->prepare($sql);

###Step③:値をバインドする
値をバインドするには、bindValueメソッドまたはbindParamメソッドを使います。
ここでは、bindValueを使って値をバインドします。

bindValueメソッドを使うときは、下記のように記述します。

bindValue(パラメータ, バインドする値, データ型;

第1引数には、『パラメータ』を指定します。
パラメータは、『名前付きプレースホルダ』の場合は『:パラメータ』となります。

また・・・

『疑問符プレースホルダ』の場合は、『1からはじまる値』になります。

第2引数には、『バインドする値』を指定します。

第3引数には、『データ型』を指定します。
データ型は、定義済み定数を指定します。

ちなみに・・・

主な定義済み定数は、下記の通りです。

  • PDO::PARAM_BOOL ⇨ 真偽型
  • PDO::PARAM_NULL ⇨ NULL型
  • PDO::PARAM_INT ⇨ 整数型
  • PDO::PARAM_STR ⇨ 文字列型 (デフォルト設定)

デフォルトでは、 PDO::PARAM_STR が指定されているので、何も指定しないとデフォルト値になります。

『名前付きプレースホルダ』を用いた場合は、下記のように記述します。

// パラメータ
$spl = (
    'SELECT
        USER_ID,
        USER_NAME,
        PASSWORD
    FROM
        テーブル名
    WHERE
        USER_ID = :USER_ID
        AND USER_NAME = :USER_NAME
        AND PASSWORD = :PASSWORD'
);

// プリペアドステートメントを用意
$stmt = $pdo->prepare($sql);

// 値をバインドする
$stmt->bindValue(':USER_ID', $user_id, PDO::PARAMS_STR);
$stmt->bindValue(':USER_NAME', $user_name, PDO::PARAMS_STR);
$stmt->bindValue(':PASSWORD', $password, PDO::PARAMS_STR);

###Step④:プリペアドステートメントを実行する

プリペアドステートメントを実行するには、executeメソッドを使います。

// パラメータ
$spl = (
    'SELECT
        USER_ID,
        USER_NAME,
        PASSWORD
    FROM
        テーブル名
    WHERE
        USER_ID = :USER_ID
        AND USER_NAME = :USER_NAME
        AND PASSWORD = :PASSWORD'
);

// プリペアドステートメントを用意
$stmt = $pdo->prepare($sql);

// 値をバインドする
$stmt->bindValue(':USER_ID', $user_id, PDO::PARAMS_STR);
$stmt->bindValue(':USER_NAME', $user_name, PDO::PARAMS_STR);
$stmt->bindValue(':PASSWORD', $password, PDO::PARAMS_STR);

// 実行
$stmt->execute();

###Step⑤:SELECTの結果を取得する

データを取得するには、下記の2つの方法があります。

  1.  fetchメソッドでデータを取得する
  2.  fetchAllメソッドでデータを取得する

それでは、ひとつずつ見ていきましょう。

####方法①:fetchメソッドでデータを取得する
fetchメソッドは、該当するデータを配列として1行のみ取得します。

また・・・

該当するデータがない場合は常に FALSE を返します。

// プリペアドステートメントを用意
$stmt = $pdo->prepare($sql);

// 値をバインドする
$stmt->bindValue(':USER_ID', $user_id, PDO::PARAMS_STR);
$stmt->bindValue(':USER_NAME', $user_name, PDO::PARAMS_STR);
$stmt->bindValue(':PASSWORD', $password, PDO::PARAMS_STR);

// 実行
$stmt->execute();

// 結果を取得する
$row = $prepare->fetch();

####方法②:fetchAllメソッドでデータを取得する

fetchAllメソッドは、該当する全てのデータを配列として返します。

取得結果がゼロ件だった場合は空の配列を返し、 失敗した場合は FALSE を返します。

// プリペアドステートメントを用意
$stmt = $pdo->prepare($sql);

// 値をバインドする
$stmt->bindValue(':USER_ID', $user_id, PDO::PARAMS_STR);
$stmt->bindValue(':USER_NAME', $user_name, PDO::PARAMS_STR);
$stmt->bindValue(':PASSWORD', $password, PDO::PARAMS_STR);

// 実行
$stmt->execute();

// 結果を取得する
$row = $prepare->fetchAll();

##まとめ:基本コーディング
そして、まとめると、下記が書き方のテンプレになります。

<?php

try {

    // リクエストから得た変数をチェックする等の処理
    $user_id = "ここにユーザーIDが入ります";
    $user_name = "ここにユーザー名が入ります";
    $password = "ここにパスワードが入ります";

    // データベース接続設定
    $pdo = new PDO(
        'mysql:host=サーバー名;dbname=DB名;charset=文字エンコード',
        'ユーザー名',
        'パスワード',
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]
    );

    // パラメータ
    $spl = (
        'SELECT
            USER_ID, USER_NAME, PASSWORD
        FROM
            テーブル名
        WHERE
            USER_ID = :USER_ID
            AND USER_NAME = :USER_NAME
            AND PASSWORD = :PASSWORD'
    );

    // プリペアドステートメントを用意
    $stmt = $pdo->prepare($sql);

    // 値をバインドする
    $stmt->bindValue(':USER_ID', $user_id, PDO::PARAMS_STR);
    $stmt->bindValue(':USER_NAME', $user_name, PDO::PARAMS_STR);
    $stmt->bindValue(':PASSWORD', $password, PDO::PARAMS_STR);

    // 実行
    $stmt->execute();

    // 結果を取得する
    $row = $prepare->fetch();

} catch (PDOException $e) {

    // エラー処理

}
4
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?