proff56/pdb

为PHP定制的PDO类

v1.0.8 2021-11-11 22:43 UTC

This package is not auto-updated.

Last update: 2024-09-23 22:58:30 UTC


README

PHP的PDO查询构建器

安装

🛠️ 使用composer将包添加到项目中;

composer require proff56/pdb

示例用法

use Mlevent\Pdb;

/**
 * MYSQL
 */
$db = new Pdb([
    'database' => 'ecommerce',
    'username' => 'root',
    'password' => 'test'
]);

/**
 * SQLITE
 */
$db = new Pdb([
    'driver'   => 'sqlite',
    'database' => 'ecommerce.sqlite'
]);

不使用Composer

创建一个新的目录,将src目录下的所有文件复制进去,并通过require将其包含在页面中启动类。

require '{pdb_dosyalarinin_bulundugu_dizin}/autoload.php';

use Mlevent\Pdb;

$db = new Pdb([
    'database' => 'ecommerce',
    'username' => 'root',
    'password' => 'test'
]);

配置

默认配置设置

[
    'host'      => 'localhost',
    'driver'    => 'mysql',
    'database'  => '',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'debug'     => false,
    'cacheTime' => 60,
    'cachePath' => __DIR__ . '/Cache'
]

当前可用的驱动程序列表

  • Mysql
  • Sqlite (测试阶段)

Fetch

可用的方法:get()first()value()pluck()find()

Get

此方法默认返回一个stdClass对象。如果您想以Array格式访问结果,请查看toArray()方法。

$products = $db->get('products');

foreach ($products as $product) {
    echo $product->name;
}
  • get()
  • get('products')

您可以使用链式方法创建SQL查询,并运行这些方法来执行查询。

$query = $db->select('id, name, code, price, stock')
            ->table('products')
            ->between('price', 900, 1500)
            ->grouped( function($q) {
                $q->like(['code', 'name'], '%iphone%')
                  ->orWhere('featured', 1);
            })
            ->in('categoryId', [1, 2, 3, 4, 5, 6])
            ->order('price')
            ->get();

上述链式查询的输出如下

SELECT
  id, name, code, price, stock
FROM
  products
WHERE
  price BETWEEN ? AND ?
  AND ((name LIKE ? OR code LIKE ?) OR featured=?)
  AND categoryId IN(?,?,?,?,?,?)
ORDER BY
  price DESC

toArray()

用于以Array格式访问结果。

$products = $db->table('products')
               ->toArray()
               ->get();

foreach ($products as $product) {
    echo $product['name'];
}

toJson()

用于以Json格式访问结果。

$products = $db->table('products')
               ->toJson()
               ->get();

First

如果您需要从表中获取单行,则可以使用first()方法。此方法默认返回一个stdClass对象。

$user = $db->table('users')
           ->first();

echo $user->email;

Value

如果您不需要一行中的所有内容,则可以使用value方法从记录中提取单个值。

$email = $db->table('users')
            ->where('name', 'Walter')
            ->value('email');

echo $email;

Pluck

如果您需要包含单个列值的数组,则可以使用pluck()方法。

$pluck = $db->table('products')
            ->pluck('name');
Array
(
    [0] => Apple Iphone X 128 GB
    [1] => Apple Iphone X 256 GB
    [2] => Apple Iphone X 512 GB
)

通过向pluck()方法发送第二个参数,您可以指定用作数组键的列

$pluck = $db->table('products')
            ->pluck('name', 'code');
Array
(
    [APPLEX128] => Apple Iphone X 128 GB
    [APPLEX256] => Apple Iphone X 256 GB
    [APPLEX512] => Apple Iphone X 512 GB
)

Find

返回与主键匹配的记录。

$user = $db->table('users')
           ->find(15);

echo $user->name;
SELECT * FROM users WHERE id=?
  • find(15)
  • find(15, 'products')

Total

用于获取总行数。

$total = $db->table('users')
            ->where('userGroup', 'Admin')
            ->total();
  • total()
  • total('users')

rowCount()

用于获取受影响的行数或读取的行数。

echo $db->rowCount();

lastInsertId()

在插入操作中返回最后插入行的主键。

echo $db->lastInsertId();

原始查询

用于执行原始SQL查询。

原始Fetch

$results = $db->raw('SELECT * FROM products WHERE active = ? AND MONTH(created) = MONTH(NOW())', 1)
              ->get();

原始Exec

$update = $db->raw('UPDATE payments SET active = !active WHERE status = ?', ['paid'])
             ->exec();

分页

应发送每页要列出的记录数作为参数。 pager()方法在原始查询中不工作。

$posts = $db->table('posts')
            ->pager(25)
            ->get();

foreach ($posts as $post) {
    echo $post->title;
}

echo $db->pagerLinks();

pager()函数接受两个参数。第一个参数是每页要列出的记录数,第二个参数是用于传递页面信息的$_GET参数。例如,链接结构为?page=3,则示例用法如下;

$db->pager(25, 'page');

pagerLinks()

用于获取链接输出。

echo $db->pagerLinks();
  • « 1 2 3 4 5 6 ... »

pagerData()

用于获取总结果、页数、limit、offset和活动页等信息。

var_dump($db->pagerData());
Array
(
    [count] => 255
    [limit] => 10
    [offset] => 0
    [total] => 26
    [current] => 1
)

setPagerTemplate()

用于调整链接输出的HTML模板。

$db->setPagerTemplate('<li>
        <a class="{active}" href="{url}">
            {text}
        </a>
    </li>');

缓存

用于将结果存入缓存。对于不经常更改且使用频繁且可能导致性能问题的查询,可以使用。

磁盘缓存

从mysql中读取comments表中的数据并将其写入磁盘。结果在30秒内从磁盘读取。

$results = $db->cache(30)->get('comments');

fromDisk()方法;如果最后查询是从磁盘读取的,则返回true,如果是从mysql读取的,则返回false

Redis缓存

从mysql中读取comments表中的数据并将其写入redis数据库。结果在30秒内通过Redis读取。

$results = $db->redis(30)->get('comments');

fromRedis() 方法;如果查询从Redis读取则为 true,从mysql读取则为 false 返回。

$redisConnect = (function(){
    $redis = new \Redis();
    $redis->connect('127.0.0.1', 6379, 1, NULL, 0, 0, ['auth' => ['default', '']]);
    return $redis;
});

$db->setRedis($redisConnect());

使用 setRedis() 方法可以将Redis类外部导入。

注意:要使用Redis进行缓存,服务器上需要安装Redis。

插入

用于向表中添加新行。使用 insert() 方法可以添加一个或多个记录。

单条记录

$db->table('products')->insert([
    'name'  => 'Apple Iphone X 128 Gb',
    'code'  => 'APPLEX128',
    'price' => '999.9'
]);

多条记录

$db->table('products')->insert([
    ['name' => 'Apple Iphone X 128 Gb', 'code' => 'APPLEX128', 'price' => '999.9'],
    ['name' => 'Apple Iphone X 256 Gb', 'code' => 'APPLEX256', 'price' => '1149.9'],
    ['name' => 'Apple Iphone X 512 Gb', 'code' => 'APPLEX512', 'price' => '1349.9']
]);

要获取最后插入行的主键,可以使用 lastInsertId() 方法,要获取受影响的行数,可以使用 rowCount() 方法。

Upsert

$db->table('products')->upsert([
    'name'  => 'Apple Iphone X 128 Gb',
    'code'  => 'APPLEX128',
    'price' => '999.9'
]);

如果找到匹配的唯一键,则更新现有记录,如果没有则添加新记录。

  • 目前不支持Sqlite。

Insert Ignore

$db->table('products')->insertIgnore([
    'name'  => 'Apple Iphone X 128 Gb',
    'code'  => 'APPLEX128',
    'price' => '999.9'
]);

如果找到匹配的唯一键,则不添加记录,如果没有则添加新记录。

Insert Replace

$db->table('products')->insertReplace([
    'name'  => 'Apple Iphone X 128 Gb',
    'code'  => 'APPLEX128',
    'price' => '999.9'
]);

如果找到匹配的唯一键,则删除现有记录并添加新记录,如果没有则添加新记录。在每次replace操作中,auto_increment指定的主键(通常为ID)的值也会改变。如果想要保留该值,建议使用 upsert() 方法。

更新

用于更新一个或多个记录。

$update = $db->table('products')
             ->where('id', 11255)
             ->update(['active' => 1]);
  • 返回受影响的行数。

触摸

如果 active 字段为 1 则变为 0,如果为 0 则变为 1

$touch = $db->table('products')
            ->touch('active');
  • touch('active', 'products')

增加

hit 字段增加 1 或发送的值。

$increment = $db->table('posts')
                ->where('slug', 'whats-new-in-laravel-8')
                ->increment('hit');
  • increment('hit')
  • increment('hit', 5)

减少

hit 字段减少 1 或发送的值。

$increment = $db->table('posts')
                ->where('slug', 'whats-new-in-laravel-8')
                ->decrement('hit');
  • decrement('hit')
  • decrement('hit', 5)

删除

用于删除一个或多个记录。

$delete = $db->in('id', [321, 412, 324, 142])
             ->delete('products');
  • 返回受影响的行数。

过滤

将发送的数据与表中的列进行比较,并自动清理错误/多余的数据。与 insert()insertIgnore()insertReplace()upsert()update() 方法一起使用。

假设我们有一个名为 users 的表,它由上面的列组成。

$db->table('users')->filter()->insert([
    'username' => 'walterbishop',
    'email'    => 'walter@bishop.com',
    'password' => 'U7!hsjlIus',
    'gender'   => 'Male',
    'fullname' => 'Walter Bishop'
]);
  • 由于 filter() 方法在 users 表中找不到 fullname 列,因此它会自动清理此数据,并确保记录无错误地创建。
$db->table('users')->filter()->insert($_POST);
  • 以下是一个使用 $_POST 发送的表单的示例。

验证

此方法目前仅用于过滤发送的数据,用默认值填充空字段,进行非空和枚举检查。

try{
    $db->table('users')->validate()->insert([
        'username' => 'walterbishop',
        'email'    => 'walter@bishop.com',
        'password' => 'U7!hsjlIus',
        'gender'   => 'Elephant'
    ]);
} catch(Exception $e){
    echo $e->getMessage();
}
  • 由于 gender 字段中没有定义枚举值 Elephant,因此会返回错误,并且不会添加记录。

事务

方法:inTransaction()beginTransaction()commit()rollBack()

try {

    $db->beginTransaction();

    $db->table('products')->insert([
        'name'  => 'Apple Iphone X 128 Gb',
        'code'  => 'APPLEX128',
        'price' => '999.9'
    ]);

    $db->table('images')->insert([
        'productId' => $db->lastInsertId(),
        'imageName' => 'foo.jpg'
    ]);

    $db->commit();

} catch(Exception $e) {

    $db->rollBack();
}

选择

$db->select('id, name, code, price')...
  • select('id, name')
  • select(['id', 'name', ...])

如果没有使用该方法,则默认使用 * 选择所有列。

选择函数

方法:count()sum()avg()min()max()

$db->sum('amount')...
  • sum('amount')
  • sum('amount', 'totalAmount')

table()from() 方法具有相同的功能。

$db->table('products')...
  • table('products')
  • table(['products as p', 'images as i'])

连接

方法:leftJoin()rightJoin()innerJoin()leftOuterJoin()rightOuterJoin()fullOuterJoin()

$db->table('products as p')
   ->leftJoin('images as i', 'p.id', 'i.productId')
   ->get();
  • leftJoin('images', 'products.id', 'images.productId')
  • leftJoin('images', 'products.id = images.productId')
  • leftJoin('images ON products.id = images.productId')

joinNode()

要在一个结果中为关联的表创建一个新的子元素,可以使用 joinNode() 方法。

$basketData = $db->table('users AS u')
                 ->select('u.*')
                 ->leftJoin('cart AS c', 'c.userId', 'u.id')
                 ->joinNode('cartData', ['name' => 'c.productName', 'quantity' => 'c.quantity'])
                 ->group('u.id')
                 ->first();
stdClass Object
(
    [id] => 159
    [fullName] => John Doe
    [email] => john@doe.com
    [cartData] => Array
        (
            [0] => stdClass Object
                (
                    [name] => Apple Iphone X 128 GB
                    [quantity] => 1
                )

            [1] => stdClass Object
                (
                    [name] => Apple Iphone X 256 GB
                    [quantity] => 1
                )

        )
)

Where

方法:where()orWhere()notWhere()orNotWhere()

$db->where('id', 32886)...
  • where('active', 1)
  • where('stock >= ? AND active = ?', [2, 1])
  • where(['stock > ?', 'active > ?'], [2, 1])
  • where(['stock' => 2, 'active' => 1])
  • where('stock >= 2 AND active = 1 AND MONTH(updated) = MONTH(NOW())')

分组条件

$db->table('products')
   ->like('name', '%iphone%')
   ->grouped(function($q){
        $q->in('brandId', [1, 2, 3])->orIn('categoryId', [1, 2, 3]);
   })->get();
  • SELECT * FROM products WHERE name LIKE ? AND (brandId IN(?,?,?) OR categoryId IN(?,?,?))

介于

方法:between()orBetween()notBetween()orNotBetween()

$db->between('price', 50, 250)...

是空 - 非空

方法:isNull()orIsNull()notNull()orNotNull()

$db->isNull('code')...
  • isNull('slug')
  • isNull(['slug', ...])

在...中 - 不在...中

方法:in()orIn()notIn()orNotIn()

$db->in('id', [33922, 31221, 45344, 35444])...

Find In Set

方法:findInSet()orFindInSet()notFindInSet()orNotFindInSet()

$db->findInSet('categoryId', 139)...

类似 - 不类似

方法:like()orLike()notLike()orNotlike()

$db->like('name', '%Apple%')...
  • like('name')
  • like(['name', ...])

排序

默认选择desc

$db->order('id')...
  • order('id')
  • order('id', 'asc')
  • order('id desc, name asc')
  • order('rand()')

分组

$db->group('id')...
  • group('id')
  • group(['id', 'name'])

Having

$db->having('stock', 5)...
  • having('stock', 5)
  • having('stock > 5')
  • having('stock > ?', 5)

限制 - 偏移

用于限制、偏移和分页操作。

$db->limit(100)...
$db->limit(100, 0)...
$db->limit(100)->offset(0)...

历史记录

queryHistory()

用于访问查询列表。

var_dump($db->queryHistory());
Array
(
    [0] => Array
        (
            [query] => SELECT id, name FROM products WHERE code = ? AND active = ? ORDER BY id desc
            [params] => Array
                (
                    [0] => 34066
                    [1] => 1
                )

            [from] => redis
        )
)

lastQuery()

用于显示最后一条查询。

echo $db->lastQuery();
  • SELECT id, name FROM products WHERE code = ? AND active = ? ORDER BY id desc

lastParams()

用于查看最后一条查询的参数。

var_dump($db->lastParams());
Array
(
    [0] => 34066,
    [1] => 1
)

queryCount()

用于获取总查询数。

echo $db->queryCount();
  • 1

结构

用于结构化查询。

$db->repair('sessions');

方法:truncate()drop()optimize()analyze()check()checksum()repair()

贡献者