mrjgreen/database

PHP表达式的数据库层 - 基于 Illuminate/Database

2.6.0 2022-05-24 07:58 UTC

README

Build Status Coverage Status Latest Stable Version License Total Downloads

数据库组件是一个框架无关的PHP数据库抽象层,提供了一种表达式的查询构建器。它目前支持MySQL、Postgres、SQL Server和SQLite。

特性

  • 简单的CRUD函数
  • 支持Insert Ignore / Replace
  • 支持Insert On Duplicate Key Update
  • 支持直接INSERT INTO ... SELECT * FROM查询
  • 从Traversable/Iterator接口缓冲插入
  • 连接
  • 子查询
  • 嵌套查询
  • 批量插入
  • MySQL SELECT * INTO OUTFILE '...'
  • MySQL LOAD DATA INFILE '...'
  • 懒惰连接
  • PSR兼容日志记录
  • 数据库连接解析器

该组件基于Laravel的Illuminate\Database,语法非常熟悉。核心查询构建器基本兼容。主要更改是对象的组成,以及在ConnectionFactory和ConnectionResolver类中连接的创建和解析。

安装

composer require mrjgreen/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',
    'username'  => 'root',
    'password'  => 'password',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
));

$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',
));

###默认连接选项默认情况下,以下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'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
    ),
    'archive' => array(
        'driver'    => 'mysql',
        'host'      => '1.2.3.456',
        'username'  => 'root',
        'password'  => 'password',
        'charset'   => 'utf8',
        'collation' => 'utf8_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);

####条件

$connection->table('user')
    ->where('username', '=', 'jsmith')
    ->whereNotIn('age', array(10,20,30))
    ->orWhere('type', '=', 'admin')
    ->orWhereNot('name', 'LIKE', '%Smith%')
    ->get();

#####分组条件

$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')`.

####分组、排序和过滤

$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 输出文件

$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'));

支持 insertIgnoreSelectreplaceSelect 方法,适用于 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();