PDOってよくわからず使ってない？

## はじめに

PDOについて理解せず使っていたので今回PDO学びました。
使い方というよりPDOって何なのかを記事にしております。

基本ブラックボックスで使って問題ないものなので初学者は飛ばしてもいいと思います
自分も初学者でインプット目的で書いてるのであしからず。
ただ（細かくを書くことはできないが）参考にしていただけたら幸いです。

　
※わたくし初学者ですので。
Qiita書き始めの自分の記事が見てもらえるとは思わずビビっております。笑

## そもそもPDOって何？
PDOは、PHP Data Objects の略で、
`「PHPでDBに接続するためのオブジェクト指向プログラム」`

※自分の解釈なので間違っているや、こういう解釈の方がいいなどあればご教授くださいまし。

脆弱性や柔軟性、拡張性がよいのでよく使われる。

脆弱性・・・SQLインジェクションをプリペアドステートメントを使うことで防ぐことができる。
柔軟性・・・DBが変わっても一部変更すればDBの切り替えに対応できる。
拡張性・・・エラーハンドリングなどのオプションを追加変更が容易

## PDOは、PHPのライブラリ

PDOはPHPのライブラリとして提供されているので
PHPのドキュメントに書かれている。
[PDOについてのドキュメント](https://www.php.net/manual/ja/class.pdo.php)
　
先ほども書いたが
PDOはオブジェクト指向で作られているので
オブジェクトを理解していないとブラックボックスで使うことになる。

オブジェクト指向について
[]()
※自分の記事で今日恐縮ですが。


## PDOの中身について
```diff_sql
class PDO {
/* 定数 */
public const int PARAM_NULL;
public const int PARAM_BOOL = 5;
public const int PARAM_INT = 1;
public const int PARAM_STR = 2;
public const int PARAM_LOB = 3;
public const int PARAM_STMT = 4;
public const int PARAM_INPUT_OUTPUT;
public const int PARAM_STR_NATL;
public const int PARAM_STR_CHAR;
public const int PARAM_EVT_ALLOC;
public const int PARAM_EVT_FREE;
public const int PARAM_EVT_EXEC_PRE;
public const int PARAM_EVT_EXEC_POST;
public const int PARAM_EVT_FETCH_PRE;
public const int PARAM_EVT_FETCH_POST;
public const int PARAM_EVT_NORMALIZE;
public const int FETCH_DEFAULT;
public const int FETCH_LAZY;
public const int FETCH_ASSOC;
public const int FETCH_NUM;
public const int FETCH_BOTH;
public const int FETCH_OBJ;
public const int FETCH_BOUND;
public const int FETCH_COLUMN;
public const int FETCH_CLASS;
public const int FETCH_INTO;
public const int FETCH_FUNC;
public const int FETCH_GROUP;
public const int FETCH_UNIQUE;
public const int FETCH_KEY_PAIR;
public const int FETCH_CLASSTYPE;
public const int FETCH_SERIALIZE;
public const int FETCH_PROPS_LATE;
public const int FETCH_NAMED;
public const int ATTR_AUTOCOMMIT;
public const int ATTR_PREFETCH;
public const int ATTR_TIMEOUT;
public const int ATTR_ERRMODE;
public const int ATTR_SERVER_VERSION;
public const int ATTR_CLIENT_VERSION;
public const int ATTR_SERVER_INFO;
public const int ATTR_CONNECTION_STATUS;
public const int ATTR_CASE;
public const int ATTR_CURSOR_NAME;
public const int ATTR_CURSOR;
public const int ATTR_ORACLE_NULLS;
public const int ATTR_PERSISTENT;
public const int ATTR_STATEMENT_CLASS;
public const int ATTR_FETCH_TABLE_NAMES;
public const int ATTR_FETCH_CATALOG_NAMES;
public const int ATTR_DRIVER_NAME;
public const int ATTR_STRINGIFY_FETCHES;
public const int ATTR_MAX_COLUMN_LEN;
public const int ATTR_EMULATE_PREPARES;
public const int ATTR_DEFAULT_FETCH_MODE;
public const int ATTR_DEFAULT_STR_PARAM;
public const int ERRMODE_SILENT;
public const int ERRMODE_WARNING;
public const int ERRMODE_EXCEPTION;
public const int CASE_NATURAL;
public const int CASE_LOWER;
public const int CASE_UPPER;
public const int NULL_NATURAL;
public const int NULL_EMPTY_STRING;
public const int NULL_TO_STRING;
public const string ERR_NONE;
public const int FETCH_ORI_NEXT;
public const int FETCH_ORI_PRIOR;
public const int FETCH_ORI_FIRST;
public const int FETCH_ORI_LAST;
public const int FETCH_ORI_ABS;
public const int FETCH_ORI_REL;
public const int CURSOR_FWDONLY;
public const int CURSOR_SCROLL;

/* メソッド */
public __construct(
    string $dsn,
    ?string $username = null,
    #[\SensitiveParameter] ?string $password = null,
    ?array $options = null
)
public beginTransaction(): bool
public commit(): bool
public errorCode(): ?string
public errorInfo(): array
public exec(string $statement): int|false
public getAttribute(int $attribute): mixed
public static getAvailableDrivers(): array
public inTransaction(): bool
public lastInsertId(?string $name = null): string|false
public prepare(string $query, array $options = []): PDOStatement|false
public query(string $query, ?int $fetchMode = null): PDOStatement|false
public query(string $query, ?int $fetchMode = PDO::FETCH_COLUMN, int $colno): PDOStatement|false
public query(
    string $query,
    ?int $fetchMode = PDO::FETCH_CLASS,
    string $classname,
    array $constructorArgs
): PDOStatement|false
public query(string $query, ?int $fetchMode = PDO::FETCH_INTO, object $object): PDOStatement|false
public quote(string $string, int $type = PDO::PARAM_STR): string|false
public rollBack(): bool
public setAttribute(int $attribute, mixed $value): bool
}
```

※上記のコードはドキュメントからのコピペです。
ドキュメントの下に説明がありますが
上記の説明を見ても使い方がよくわからないと思います。

今回の記事でわかるようになるとは思っておりませんが
軽ーく説明したいと思います。

まずそもそも自分はブラックボックスで使っていたので
こんなコードになっていたのか。。。と中身の理解が今楽しい状態です(笑)

### 定数について
定数とかかれた上部についてこれは設定の変更に使われます。
```diff_php
<?php 
$dsn = “”;
$pdo = new PDO($dsn); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
```

これはよく使われるEXCEPTIONのエラーハンドリングの設定を変更しました。
こんな感じでsetAttribute(何を変えるか？,何に変えるか？)
で好きに変更することが可能です。

### メソッドについて
メソッドについては
まず最初にある__constructが代表的で少し触ったことある人ならわかるはず（インスタンス作成時に処理するメソッド）

なので別のトランザクション、コミット、ロールバックについて話していきます。

```diff_php
<?php 

try {
    // 接続してsqlをセットして$pdoというインスタンスを生成済み

    // プリペアドステートメントの利用
    $ps = $pdo->prepare($sql); 
    // トランザクションを実行　＝　オートコミットOFF
    $pdo->beginTransaction();
    try{
      foreach($array as $value){
       $ps->bindValue(“:id”,$value[“id”],PDO::PARAM_INT);
       $ps->bindValue(“:title”,$value[“title”],PDO::PARAM_INT);
       $ps->execute();
      }

       // commit 実行
       $pdo->commit();
    } catch (PDOException $e) {

        // rollback 処理をキャンセルする
       $pdo->rollback();
       throw $e;
    	 }
      
}catch (PDOException $e){
    echo $e->getMessage();
}

```

トランザクションについて軽く説明。
```
$pdo->beginTransaction();
```
を宣言することでトランザクションが開始される。

次に
```
$pdo->commit();
```
が行われるまで処理が実行されず、待機状態となる。
例えば今回のコードの場合

```diff_php
foreach($array as $value){
       $ps->bindValue(“:id”,$value[“id”],PDO::PARAM_INT);
       $ps->bindValue(“:title”,$value[“title”],PDO::PARAM_INT);
       $ps->execute();
      }

       // commit 実行
       $pdo->commit();
```
このようにforeachでループ処理で展開しながらコードを進めているが
処理は待機している。無事に
```
$pdo->commit();
```
まで進んだ時、待機していた処理を一気に処理が行う。


トランザクションを行ってから
```
$pdo->commit();
```
に到達する前に処理にエラーが起こった場合に
```
$pdo->rollback();
```
を実行させることでトランザクション中に待機させていた処理をすべてキャンセルさせる。


このようにトランザクションの処理もすべてPDOクラスの中にメソッドとして用意されている。

なのでPDOインスタンスを作成して
メソッドにアクセスして使うことができる。


なんかな話がまとまらない。。。
また機会があれば編集しなおします。。。