jsl / database
PHP 表达式数据库层 - 基于 Illuminate/Database
Requires
- php: >=5.4.0
- psr/log: ~1.0
This package is auto-updated.
Last update: 2024-09-11 20:28:07 UTC
README
数据库组件是一个与框架无关的 PHP 数据库抽象层,提供了一种表达式的查询构建器。它目前支持 MySQL、Postgres、SQL Server 和 SQLite。
功能
- 简单的 CRUD 功能
- 支持插入忽略/替换
- 支持插入重复键更新
- 支持直接
INSERT INTO ... SELECT * FROM
查询 - 从 Traversable/Iterator 接口缓冲插入
- 连接
- 子查询
- 嵌套查询
- 批量插入
- MySQL
SELECT * INTO OUTFILE '...'
- MySQL
LOAD DATA INFILE '...'
- 延迟连接
- PSR 兼容日志记录
- 数据库连接解析器
该组件基于 Laravel 的 Illuminate\Database,拥有非常熟悉的语法。核心查询构建器基本上是兼容的。主要的改动是对对象组合,以及连接工厂和连接解析器类中连接的创建和解析。
安装
composer require jsl/database
基本示例
首先,创建一个新的 "ConnectionFactory" 实例。
$factory = new \Database\Connectors\ConnectionFactory(); $connection = $factory->make(array( 'driver' => 'mysql', 'host' => 'localhost', 'username' => 'root', 'password' => 'password', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', // Don't connect until we execute our first query 'lazy' => true, // Set PDO attributes after connection 'options' => array( PDO::MYSQL_ATTR_LOCAL_INFILE => true, PDO::ATTR_EMULATE_PREPARES => true, ) )); $connection->query("SELECT id, username FROM customers");
文档
目录
连接
数据库组件支持 MySQL、SQLite、SqlServer 和 PostgreSQL 驱动。您可以在连接期间指定驱动程序,以及创建新连接时的相关配置。您还可以创建多个连接,但一次只能使用一个别名。
$factory = new \Database\Connectors\ConnectionFactory();
MySQL
$connection = $factory->make(array( 'driver' => 'mysql', 'host' => 'localhost', 'database' => 'database', // Optional 'username' => 'root', 'password' => 'password', 'charset' => 'utf8mb4', // Optional: default value if omitted 'collation' => 'utf8mb4_unicode_ci', // Optional: default value if omitted )); $connection->fetchAll("SELECT id, username FROM customers"); $connection->table('customers') ->find(12); $connection->table('customers') ->join('products', 'customer.id', '=', 'customer_id') ->where('favourites', '=', 1) ->get();
SQLite
$connection = $factory->make(array( 'driver' => 'sqlite', 'database' => '/path/to/sqlite.db', 'create' => true, ));
PDO 总是在数据库不存在时创建数据库。由于您不会收到任何提示,这可能会使调试变得非常困难。使用连接选项 create
您可以决定这种行为。将其设置为 true
以允许 PDO 创建数据库。将其设置为 false
(默认值)将在数据库不存在时抛出异常。
默认连接选项
默认情况下,以下 PDO 属性将在连接上设置。您可以在连接配置的 options
数组参数中覆盖这些属性或添加它们。
PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_EMULATE_PREPARES => false,
连接解析器
许多复杂的应用程序可能需要多个数据库连接。您可以在连接解析器内部创建一组命名连接,并在您的应用程序中通过名称引用它们。
$resolver = new Database\ConnectionResolver(array( 'local' => array( 'driver' => 'mysql', 'host' => 'localhost', 'username' => 'root', 'password' => 'password', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', ), 'archive' => array( 'driver' => 'mysql', 'host' => '1.2.3.456', 'username' => 'root', 'password' => 'password', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', ), )); $dbLocal = $resolver->connection('local'); // Use it $dbLocal->table('users')->get(); $dbArchive = $resolver->connection('archive'); // Etc...
如果您请求的连接是您之前在应用程序中使用的,连接解析器将返回相同的连接,而不是创建一个新的连接。
在创建解析器后,您可以设置默认连接,这样您就不必在整个应用程序中指定连接名称。
$resolver->setDefaultConnection('local'); // Returns the `local` connection $resolver->connection();
原始查询
执行查询,带有绑定并返回 PDOStatement 对象
$statement = $connection->query('SELECT * FROM users WHERE name = ?', array('John Smith')); // PDOStatement $statement->rowCount(); $statement->fetchAll();
查询快捷键
$firstRow = $connection->fetch('SELECT * FROM users WHERE name = ?', array('John Smith')); $allRows = $connection->fetchAll('SELECT * FROM users WHERE name = ?', array('John Smith')); $firstColumnFirstRow = $connection->fetchOne('SELECT COUNT(*) FROM users WHERE name = ?', array('John Smith'));
查询构建器
选择
获取 PDOStatement
如果您打算遍历行,则获取 PDOStatement 可能更高效
$rows = $connection->table('users')->query();
获取所有
$rows = $connection->table('users')->get();
获取第一行
$row = $connection->table('users')->first();
按 ID 查找
$row = $connection->table('users')->find(6);
上述查询假设您的表的主键是 'id'
并且您想检索所有列。您可以指定要获取的列和主键
$connection->table('users')->find(3, array('user_id', 'name', 'email'), 'user_id');
选择列
$rows = $connection->table('users')->select('name')->addSelect('age', 'dob')->get();
限制和偏移
$connection->table('users')->offset(100)->limit(10);
Where
$connection->table('user') ->where('username', '=', 'jsmith') ->whereNotIn('age', array(10,20,30)) ->orWhere('type', '=', 'admin') ->orWhereNot('name', 'LIKE', '%Smith%') ->get();
分组 Where
$connection->table('users') ->where('age', '>', 10) ->orWhere(function($subWhere) { $subWhere ->where('animal', '=', 'dog') ->where('age', '>', 1) }); SELECT * FROM `users` WHERE `age` > 10 or (`age` > 1 and `animal` = 'dog')`.
分组 By、排序 By 和 Having
$users = $connection->table('users') ->orderBy('name', 'desc') ->groupBy('count') ->having('count', '>', 100) ->get();
连接
$connection->table('users') ->join('products', 'user_id', '=', 'users.id') ->get(); /* ->leftJoin() ->rightJoin() */
多个连接标准
如果您需要多个标准来连接一个表,则可以将闭包作为第二个参数传递。
->join('products', function($table) { $table->on('users.id', '=', 'products.user_id'); $table->on('products.price', '>', 'users.max_price'); })
子查询
$query = $connection->table('users') ->selectSub(function($subQuery){ $subQuery ->from('customer') ->select('name') ->where('id', '=', $subQuery->raw('users.id')); }, 'tmp');
这将生成如下查询
SELECT (SELECT `name` FROM `customer` WHERE `id` = users.id) as `tmp` FROM `users`
聚合
计数
$count = $connection->table('users')->count();
最小值
$count = $connection->table('users')->min('age');
最大值
$count = $connection->table('users')->max('age');
平均值
$count = $connection->table('users')->avg('age');
总和
$count = $connection->table('users')->sum('age');
MySQL Outfile
$connection ->table('users') ->select('*') ->where('bar', '=', 'baz') ->intoOutfile('filename', function(\Database\Query\OutfileClause $out){ $out ->enclosedBy(".") ->escapedBy("\\") ->linesTerminatedBy("\n\r") ->fieldsTerminatedBy(','); })->query();
插入
$data = array( 'username' = 'jsmith', 'name' = 'John Smith' ); $connection->table('users')->insert($data); // Returns PDOStatement `->insertGetId($data)` method returns the insert id instead of a PDOStatement
插入忽略
忽略具有重复唯一键插入的任何行的错误
$data = array( 'username' = 'jsmith', 'name' = 'John Smith' ); $connection->table('users')->insertIgnore($data);
替换
替换匹配唯一键的现有行
$data = array( 'username' = 'jsmith', 'name' = 'John Smith' ); $connection->table('users')->replace($data);
批量插入
查询构建器将智能处理多个插入行
$data = array( array( 'username' = 'jsmith', 'name' = 'John Smith' ), array( 'username' = 'jbloggs', 'name' = 'Joe Bloggs' ), ); $connection->table('users')->insert($data);
您还可以将批量插入传递给 replace() 和 insertIgnore()
重复键更新
$data = array( 'username' = 'jsmith', 'name' = 'John Smith' ); $now = $connection->raw('NOW()'); $connection->table('users')->insertUpdate( array('username' => 'jsmith', 'active' => $now), // Insert this data array('active' => $now) // Or partially update the row if it exists ); //insertOnDuplicateKeyUpdate() is an alias of insertUpdate
插入选择
$connection->table('users')->insertSelect(function($select){ $select->from('admin') ->select('name', 'email') ->where('status', '=', 1);
}, array('name','email'));
insertIgnoreSelect
和 replaceSelect
方法支持 MySQL 语法驱动程序。
缓冲迭代器插入
如果您有一个大型数据集,可以以所选大小分批插入(支持插入忽略/替换/重复键更新)。
如果您想从一个服务器选择大量数据集并插入到另一个服务器,这将特别有用。
$pdoStatement = $mainServer->table('users')->query(); // Returns a PDOStatement (which implements the `Traversable` interface) // Will be inserted in batches of 1000 as it reads from the rowset iterator. $backupServer->table('users')->buffer(1000)->insertIgnore($pdoStatement);
更新
$data = array( 'username' = 'jsmith123', 'name' = 'John Smith' ); $connection->table('users')->where('id', 123)->update($data);
删除
$connection->table('users')->where('last_active', '>', 12)->delete();
将删除所有 id 大于 5 的行。
原始表达式
使用 $connection->raw()
包装原始查询以绕过查询参数绑定。注意:谨慎使用 - 不会进行清理。
$connection->table('users') ->select($connection->raw('DATE(activity_time) as activity_date')) ->where('user', '=', 123) ->get();
获取 SQL 查询和绑定
$query = $connection->table('users')->find(1)->toSql(); $query->toSql(); // SELECT * FROM users where `id` = ? $query->getBindings(); // array(1)
原始 PDO 实例
$connection->getPdo();
致谢
这是 mrjgreen/database 的一个分支。