開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. PHP >
  4. [PHP] シンプルなクエリビルダー Atlas.Queryの使い方

[PHP] シンプルなクエリビルダー Atlas.Queryの使い方

こんにちは、ナカエです。

本日はデータベースフレームワークAtlasの記事の第四弾です。

クエリビルダーのパッケージ、Atlas.Queryの使い方を紹介します。

インストール

Composerを使ってインストールします。

composer require atlas/query

composer.jsonの例

{
    "require": {
        "php": "^7.2",
        "ext-pdo": "*",
        "atlas/query": "^1.2"
    } 
}

インスタンス化

SQL文に対応する、Select, Insert, Update, Deleteクラスが用意されています。

スタティックのnewメソッドにPdoまはたAtlas.PdoのConnectionオブジェクトを与えるのが一つ目の方法です。

<?php

require_once __DIR__ . '/vendor/autoload.php';

use Atlas\Query\Select;
use Atlas\Query\Insert;
use Atlas\Query\Update;
use Atlas\Query\Delete;

$pdo = new PDO('sqlite::memory:');
$select = Select::new($pdo);
$insert = Insert::new($pdo);

$conn = Connection::new('sqlite::memory:');
$update = Update::new($conn);
$delete = Delete::new($conn);

ファクトリクラスを使うのがもう一つの方法です。 この場合でも、PdoまたはConnectionオブジェクトを引数に与える必要があります。

$conn = \Atlas\Pdo\Connection::new('sqlite::memory:');
$queryFactory = new \Atlas\Query\QueryFactory();
$select = $queryFactory->newSelect($conn);
$insert = $queryFactory->newInsert($conn);
$update = $queryFactory->newUpdate($conn);
$delete = $queryFactory->newDelete($conn);

クエリをビルドして実行する

Select, Insert, Update, Deleteそれぞれのクラスに、クエリを構築するためのビルダー系のメソッドと、クエリを実行するための実行用のメソッドが用意されています。一連の処理を通して見ていきましょう

準備

どんなクエリが実行されているかを把握するためにクエリロガーを設定しておくと便利です。 Atlas.PdoのConnectionのロギング機構がそのまま使えます。 今回はコマンドラインからの実行なので、実行されたSQLを装飾して出力するようにします。

// 出力用の補助関数
function info(string $message, string $colorCode = '0;32'): void
{
    echo "\033[{$colorCode}m" . $message . "\033[0m" . PHP_EOL;
}


$conn = Connection::new('sqlite::memory:');
$conn->setQueryLogger(function (array $entry) {
    $keys = array_map(function ($val) {
        return ':' . $val;
    }, array_keys($entry['values']));
    $query = str_replace($keys, array_values($entry['values']), $entry['statement']);

    info($query, '1;33');

});
$conn->logQueries(true);

Atlas.Queryにはテーブルスキーマの操作機能は含まれないので、Atlas.Pdoでテーブルを作成しておきます。

$conn->exec('CREATE TABLE users (id integer primary key, name varchar(255))');

Insert

まずはレコードを挿入します。 Insertオブジェクトには挿入するテーブルを指定するinto()と挿入するカラムと値を指定するcolumn()、columns()などのメソッドがあります。

$records = [
    ['id' => 1, 'name' => 'Taro'],
    ['id' => 2, 'name' => 'Hanako'],
    ['id' => 3, 'name' => 'Jiro'],
];

foreach ($records as $record) {
    // クエリのビルド
    $insert = Insert::new($conn);
    $insert->into('users')->columns($record);

    // クエリの実行
    $insert->perform();
    info('inserted id = ' . $insert->getLastInsertId(), '1;37');
}

クエリの実行はperform()メソッドを呼べばOKです。 実行後にはgetLasInsertID()により、挿入されたレコードのIDを取得できます。

出力

CREATE TABLE users (id integer primary key, name varchar(255))
INSERT INTO users (
    "id",
    "name"
) VALUES (
    1,
    Taro
)
inserted id = 1
INSERT INTO users (
    "id",
    "name"
) VALUES (
    2,
    Hanako
)
inserted id = 2
INSERT INTO users (
    "id",
    "name"
) VALUES (
    3,
    Jiro
)
inserted id = 3

Select

Select文です。usersテーブルから全てのレコードを取得するクエリは例えばこうなります。 取得するカラムをcolumns()で指定し、テーブルはfromで指定します。 元のSQL文を意識したインターフェースになっていますね。

    // ビルド
    $selectAll = Select::new($conn)
        ->columns('id', 'name')
        ->from('users');

    // 実行
    $results = $selectAll->fetchAll();
    var_export($results);

実行結果の取得はAtlas.Pdoのメソッドと同じで、 実行結果を一気に取得するfetch()系のメソッドとGeneraterを使って取得するyield()系のメソッドが使えます。

SELECT
    id,
    name
FROM
    users
array (
  0 => 
  array (
    'id' => '1',
    'name' => 'Taro',
  ),
  1 => 
  array (
    'id' => '2',
    'name' => 'Hanako',
  ),
  2 => 
  array (
    'id' => '3',
    'name' => 'Jiro',
  ),
)

WHERE, LIMIT

WHERE句やLIMIT句なども用意されています。 where()は第一引数に演算子までを記述し、第二引数に比較するパラメータを指定する形になっています。

    // ビルド
    $queryFactory = new QueryFactory();
    $selectTaro = $queryFactory
        ->newSelect($conn)
        ->columns('id', 'name')
        ->from('users')
        ->where('name = ', 'Taro')
        ->limit(1);
    // 実行
    $result = $selectTaro->fetchOne();
    var_export($result);
SELECT
    id,
    name
FROM
    users
WHERE
    name = Taro
LIMIT 1
array (
  'id' => '1',
  'name' => 'Taro',
)

Update

table()によって更新するテーブル名を、columns()によって更新するカラムを指定できます。 where()によって更新先の指定します。

    // ビルド
    $updateTaroName = $queryFactory
        ->newUpdate($conn)
        ->table('users')
        ->columns(['name' => 'Taro2'])
        ->where('name = ', 'Taro');
    // 実行
    $updateTaroName->perform();

    // selectで結果確認
    var_export($selectAll->fetchAll());

実行はInsertと同じくperform()です。

SET
    "name" = Taro2
WHERE
    name = Taro
SELECT
    id,
    name
FROM
    users
array (
  0 => 
  array (
    'id' => '1',
    'name' => 'Taro2',
  ),
  1 => 
  array (
    'id' => '2',
    'name' => 'Hanako',
  ),
  2 => 
  array (
    'id' => '3',
    'name' => 'Jiro',
  ),
)

Delete

DeleteもInsertやUpdateとそう変わりません。 from()がテーブルの指定、where()で削除するレコードを絞り込みます。

    $deleteJiro = $queryFactory
        ->newDelete($conn)
        ->from('users')
        ->where('name =', 'Jiro');
    $deleteJiro->perform();

    // yieldで取得してみる
    $results = $selectAll->yieldAll();
    assert($results instanceof \Generator);
    foreach ($results as $result) {
        var_export($result);
    }
DELETE FROM users
WHERE
    name =Jiro
SELECT
    id,
    name
FROM
    users
array (
  'id' => '1',
  'name' => 'Taro2',
)array (
  'id' => '2',
  'name' => 'Hanako',
)

まとめ

テーブル作成からレコードのCRUDを一通り試してみました。SQL文さえわかっていればすぐに使えるなという印象です。 メソッドの確認のためソースも眺めましたが、Select,Insert,Update,Deleteの各クラスがすっきりしているのもいいですね。

  • posted by ナカエ
  • PHP
TOPに戻る