bogdanpet / orthite-db
PDO 封装,用于更方便地访问数据库
This package is not auto-updated.
Last update: 2024-09-29 05:27:55 UTC
README
PDO 封装,用于更方便地访问数据库。目前处于原型阶段,仅支持 mysql。有些功能可能也适用于 postgres 或 sqlite,但将稍后添加对这些驱动器的完整支持。
目录
安装
使用命令通过 composer 安装包
composer require bogdanpet/orthite-db
创建连接
使用 dsn、用户名和密码字符串创建连接
创建连接与使用 dsn、用户名和密码字符串创建新的 PDO 连接相同。
$db = new \Orthite\Database\Database($dsn, $user, $password)
回收现有的 PDO 连接
如果已经存在一个 PDO 连接,可以将其传递给 Orthite 的 Database 类构造函数。
$pdo = new \PDO($dsn, $user, $password); . . . $db = new \Orthite\Database\Database($pdo);
使用数组创建连接
可以使用包含连接详细信息的数组创建数据库对象:驱动程序、主机、端口、用户、密码和数据库名称。
$conn = [ 'driver' => 'mysql', 'host' => 'localhost', 'port' => 3306, 'user' => 'root', 'password' => 'secret', 'database' => 'database_name', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci' ]; $db = new \Orthite\Database\Database($conn);
当连接详情存储在某种配置文件中时,这种情况很有用。必需的参数是数据库、用户名和密码。其他参数有默认值
- 驱动程序默认为
mysql
- 主机默认为
localhost
- 端口默认为
3306
- 字符集默认为
utf8
- 校对默认为
utf8_unicode_ci
创建子类并配置连接。
如果整个应用程序中使用了相同的连接,但需要在多个地方设置数据库对象,则创建一个子 Database 类并通过重写连接属性来使连接持久化是很好的。
<?php namespace App; class Database extends \Orthite\Database\Database { protected $connection = [ 'driver' => 'mysql', 'host' => 'localhost', 'port' => 3306, 'user' => 'root', 'password' => 'secret', 'database' => 'database_name' ]; }
或者,连接详情可能应该从某些配置文件(如 dotenv)中返回
<?php namespace App; class Database extends \Orthite\Database\Database { public function __construct() { $this->connection['driver'] = getenv('DB_DRIVER'); $this->connection['host'] = getenv('DB_HOST'); $this->connection['port'] = getenv('DB_PORT'); $this->connection['user'] = getenv('DB_USER'); $this->connection['password'] = getenv('DB_PASSWORD'); $this->connection['database'] = getenv('DB_NAME'); parent::_construct(); } }
然后,只需实例化子类即可。
$db = new App\Database();
CRUD 操作
插入
要向数据库表插入记录,请调用 insert 方法并传递要插入的表名和数据数组。数组键必须与列名匹配。假设我们有一个包含 id、first_name、age、email、created_at、updated_at 列的 users 表,其中 id 是自增主键,updated_at 是可空的。要插入记录
$data = [ 'first_name' => 'Anika', 'age' => 28, 'email' => 'anika@example.com', 'created_at' => date() ]; $db->insert('users', $data);
要一次插入多条记录,请使用 insertMany() 方法并传递数组数组(每个数组代表一条记录)。
$data = [ [ 'first_name' => 'Anika', 'age' => 28, 'email' => 'anika@example.com', 'created_at' => date() ], [ 'first_name' => 'Bob', 'age' => 29, 'email' => 'bob@example.com', 'created_at' => date() ] ]; $db->insertMany('users', $data);
insertMany 方法返回成功插入的记录数。
选择
使用 select() 方法从数据库中获取数据。必需参数是表名。
$users = $db->select('users');
这将将 users 表中的所有列的所有记录获取到关联数组中。要获取仅某些列,请传递列名数组作为第二个参数。
$users = $db->select('users', ['name', 'email']);
这将仅获取名称和电子邮件列。
可选地,作为第三个参数可以传递获取样式。默认值为 FETCH_ASSOC。请参阅 PDO 获取样式
限制结果
在 select 之前使用 limit() 方法来限制获取的记录数。
$users = $db->limit(10)->select('users');
这将返回数据库中的前 10 条记录。limit 方法可以接受第二个参数,该参数定义了一个 'chunk',默认值为 1。因此,要获取第二块(从数据库中的第 11 条到第 20 条记录)的用户,请使用
$users = $db->limit(10, 2)->select('users');
在 select 中连接其他表
在 select 之前可以使用 innerJoin()(或别名 join,即内连接)、leftJoin()、rightJoin()、fullJoin() 连接其他表。
$users = $db->join('cities', 'city_id', 'id')->select('users');
此操作将在条件 users.city_id = cities.id
下将 cities 表与 users 表进行内连接。其他类型的连接操作与此类似。
由于 select() 方法必须在链的最后,因此有些人可能觉得先设置连接表然后是主表的方式不太自然。在这种情况下,可以使用 table() 方法,以下是如何达到相同结果的示例。
$users = $db->table('users')->join('cities', 'city_id', 'id')->select();
分组和排序结果
使用 groupBy() 方法,可以通过字符串传递单个列或通过数组传递多个列来生成 `GROUP BY` 声明。
$users = $db->groupBy('age')->select('users');
这将生成查询 SELECT * FROM users GROUP BY age
与分组类似,也可以使用 orderBy() 方法进行排序。
$users = $db->orderBy(['age', 'first_name'])->select('users');
生成的查询是 SELECT * FROM users ORDER BY age, first_name
。对于排序,可以传递 ASC 或 DESC,并通过竖线 '|' 分隔。
$users = $db->orderBy(['age|ASC', 'first_name|DESC'])->select('users');
生成的查询是 SELECT * FROM users ORDER BY age ASC, first_name DESC
where 条件
在查看更新和删除操作之前,让我们先看看 WHERE 条件。要添加 WHERE 条件,请使用常规的 where() 方法。
$user = $db->where('id', 3)->select('users');
第一个参数是列名,第二个是值。另外,第三个参数是比较器,默认为 '=', 但可以是 '<', '>', '<=' 或 '>='。另外,第四个参数是关键字 'WHERE',但可以更改为 'AND' 或 'OR' 以添加多个条件。
$user = $db->where('id', 3)->where('age', 18, '>=', 'AND')->select('users');
这将生成 WHERE id=3 AND age >= 18
。这是可能的,但与其更改第三和第四个参数,不如推荐并更直观地使用包装方法。
- and() - 使用 'AND' 的 where() 方法
- or() - 使用 'OR' 的 where() 方法
- whereGreaterThan(); andGreaterThan(); orGreaterThan() - 与 '>' 比较器相对应的函数
- whereLessThan(); andLessThan(); orLessThan() - 与 '<' 比较器相对应的函数
- whereGreaterOrEquals(); andGreaterOrEquals(); orGreaterOrEquals() - 与 '>=' 比较器相对应的函数
- whereLessOrEquals(); andLessOrEquals(); orLessOrEquals() - 与 '<=' 比较器相对应的函数
因此,将上述查询写成这样会更容易阅读
$user = $db->where('id', 3)->andGreaterOrEquals('age', 18)->select('users');
为了提高可读性,可以使用动态方法,其中列名在 'where'、'and' 或 'or' 关键字之后立即以驼峰式注入到方法名称中,并且只传递值作为参数。
$user = $db->whereId(3)->andAgeGreaterOrEquals(18)->select('users');
对于像 'first_name' 这样由下划线分隔的单词列名,使用驼峰式 whereFirstName()。
其他比较
Orthite-db 还提供了 whereLike()、andLike() 和 orLike() 方法。例如
$users = $db->whereFirstNameLike('Ani%')->select('users');
将生成 WHERE first_name LIKE 'Ani%'
,这将获取以 'Ani' 开头的用户。
与 LIKE 类似,还有用于 IN 比较的方法:whereIn()、andIn() 和 orIn(),它们接受一个要比较的值数组。
$users = $db->whereIdIn([1, 2, 3])->select('users');
生成 WHERE id IN (1, 2, 3)
并获取 id 为 1、2 和 3 的用户。
最后,对于 'BETWEEN' 比较操作,有 whereBetween()、andBetween() 和 orBetween() 方法,它们接受两个值参数。示例
$users = $db->whereIdBetween(1, 10)->select('users');
这将生成 WHERE id BETWEEN 1 and 10
。
更新
要更新数据库中的记录,请使用 update() 方法,它接受与 insert() 相同的参数:表名和数据。如果您不想更新表中的所有行,请别忘了结合使用 WHERE 条件。
$data = [ 'email' => 'anika@example.com' ]; $db->whereFirstName('Anika')->update('users', $data);
删除
要删除表中的一行或多行,请使用具有表名参数的 delete() 方法,并结合 WHERE 条件。
$db->whereId(8)->delete('users');
执行原始查询
提供的 CRUD 操作方法无法满足更复杂的操作,因此可以编写并执行原始查询。
raw() - 返回 PDO 语句
$stmt = $db->raw('SELECT * FROM users WHERE id < 100');
rawFetch() - 用于 SELECT 查询,它返回获取的数据而不是语句
$users = $db->rawFetch('SELECT * FROM users WHERE id < 100');
安全执行查询
而不是运行带有用户输入数据的原始查询,为了防止 SQL 注入,请运行 execute() 方法,该方法准备语句并使用给定的数据执行它。第一个参数是带有占位符的查询,第二个是数据数组。示例使用位置占位符
$stmt = $db->execute('SELECT * FROM users where id = ? and first_name = ?', [$id, $first_name]);
带有命名占位符的示例
$stmt = $db->execute('SELECT * FROM users where id = :id and first_name = :first_name', [ ':id' => $id, ':first_name' => $first_name ]);
自定义带有数据类型指定的占位符
orthite-db 允许在占位符中指定数据类型,以实现更安全的查询。可能的类型有 s、i、b、l,分别对应于 PDO 参数类型 中的字符串、整数、布尔值和 lobs。自定义位置占位符使用问号和相应的字母 '?i' 表示。命名占位符的格式为 's:first_name'。在同一个查询中不能混合使用命名和位置占位符。示例
$stmt = $db->execute('SELECT * FROM users where id = ?i and first_name = ?s', [ ':id' => $id, ':first_name' => $first_name ]);
$stmt = $db->execute('SELECT * FROM users where id = i:id and first_name = s:first_name', [ ':id' => $id, ':first_name' => $first_name ]);
迁移
Orthite-db 还提供使用 migrate() 方法编写迁移脚本的功能。migrate() 方法的第一个参数是表名,第二个参数是包含列定义的回调函数。回调函数接受 $schema 参数,用于定义列结构。一个简单的迁移脚本应如下所示
use Orthite\Database\Migrations\SchemaInterface; $db->migrate('cities', function (SchemaInterface $schema) { $schema->integer('id')->unsigned()->autoIncrement()->primary(); $schema->string('name', 50); return $schema; }); $db->migrate('users', function (SchemaInterface $schema) { $schema->increments(); // Alias of $schema->integer('id')->unsigned()->autoIncrement()->primary(); $schema->string('username', 40)->unique(); $schema->string('name', 30)->nullable(); $schema->double('score')->default('0.00'); $schema->integer('city_id')->unsigned()->foreign('cities', 'id'); /* * Adds created_at, updated_at and deleted_at columns * Same as: * $this->timestamp('created_at'); * $this->datetime('updated_at')->nullable(); * $this->datetime('deleted_at')->nullable(); */ $schema->timestamps(); return $schema; });
上面的迁移脚本将创建两个表:cities 和 users,其中 users 表的 city_id 外键引用 cities 表的 id。
所以,如上例所示,在 $schema 对象上首先调用一个定义列的方法,并传递列名,然后链式调用可选的约束方法。迁移脚本结束时必须返回 $schema 对象。目前支持的列方法有
- string($column, $length = 255) - VARCHAR 列
- text($column) - TEXT 列
- binary($column) - BLOB 列
- integer($column, $size = 4) - INT 列
- double($column, $size = 4, $decimals = 2) - DOUBLE 列
- decimal($column, $size = 4, $decimals = 2) - DECIMAL 列
- bool($column) - TINYINT(1) 列
- date($column) - DATE 列
- datetime($column) - DATETIME 列
- timestamp($column) - TIMESTAMP 列
- time($column) - TIME 列
- year($column) - YEAR 列
可用的约束方法有
- nullable() - 从列中移除 NOT NULL
- unique() - 添加 UNIQUE 约束
- primary() - 设置为 PRIMARY KEY
- foreign($refTable, $refColumn) - 添加 FOREIGN KEY 约束
- check($condition) - 添加 CHECK 约束
- default($value) - 添加 DEFAULT 值
- index() - 设置为 INDEXED 列
- unsigned() - 将整数设置为 UNSIGNED
- autoIncrement() - 将列设置为 AUTO_INCREMENT
包装方法
- increments($column = 'id') - integer($column)->unsigned()->autoIncrement()->primary();
- timestamps() - 创建三个列:created_at TIMESTAMP、updated_at 可空 DATETIME、deleted_at 可空 DATETIME