tomkyle / databases
通过易于使用的连接工厂创建通用数据库API连接。对于多个数据库,服务定位器可以帮助您创建这些工厂。
Requires
- php: >=5.3.0
- pimple/pimple: ~3.0
Requires (Dev)
- satooshi/php-coveralls: dev-master
Suggests
- aura/sql: Aura.SQL – Provides adapters for SQL database access around PDO
README
#数据库工厂与服务定位器
此数据库连接工厂与服务定位器创建到常见数据库API的通用连接,这些API由易于使用的连接工厂提供。当与多个数据库一起工作时,服务定位器可以帮助您创建这些工厂。它支持PDO、mysqli和Aura.SQL v1.3。
##概述 ###单个数据库
- 使用关联数组或StdClass设置 DatabaseConfig
- 使用配置对象创建 DatabaseProvider(依赖注入)
- 为所需的数据库API 获取连接
###多个数据库
- 在二维数组或StdClass中描述数据库连接
- 使用配置对象设置 DatabaseServiceLocator
- 从ServiceLocator获取 DatabaseProvider
- 为所需的数据库API 获取连接
##安装
此库除了Fabien Potencier的Pimple库外没有依赖项。它可以通过Composer安装和自动加载。在安装过程中,Composer会建议安装Aura.SQL v1.3,如果您还没有安装。通过命令行或composer.json
文件安装
#####命令行
composer require tomykle/databases
#####composer.json "require": { "tomkyle/databases": "~1.0" }
##入门:单个数据库
###概述每个DatabaseProvider
都需要一些有关要处理的数据库的信息,这些信息作为实现DatabaseConfigInterface
的参数传递。一个现成的实现是DatabaseConfig
,它可以通过关联数组或StdClass进行配置。
现在您已经准备好了DatabaseConfig
,只需将其传递给新的DatabaseProvider
并获取您喜欢的连接即可。
###示例
<?php use \tomkyle\Databases\DatabaseConfig; use \tomkyle\Databases\DatabaseProvider; // 1a. Describe your database as array: $describe = array( 'host' => "localhost", 'database' => "database1", 'user' => "root", 'pass' => "secret", 'charset' => "utf8" ); // 1b. Describe your database as StdClass: $describe = json_decode('{ "host": "localhost", "database": "database1" # etc. }'); // 2. Setup DatabaseConfig instance: $config = new DatabaseConfig( $describe ); // 3. Create DatabaseProvider instance: $factory = new DatabaseProvider( $config ); // 4. Grab Aura.SQL connection: $aura = $factory->getAuraSql();
###配置选项如果以下字段之一为空或不存在,则DatabaseConfig
将抛出RuntimeException
- host: 主机名
- database: 数据库名称
- user 或 username: 数据库用户
- pass 或 password: 数据库密码
可选字段,具有根据MySQL设置的默认值
- charset: 要使用的字符集,默认为
utf8
- type: 数据库类型,默认为
mysql
- port: 数据库端口,默认为
3306
###获取连接
每个DatabaseProvider
实例都提供了不同类型的Singleton-like数据库连接。您可以通过调用getter方法或将其作为数组键(Pimple的方式)来获取您的连接。
####PDO连接
$pdo = $factory->getPdo(); // or $pdo = $factory['pdo']; echo get_class( $pdo ); // "PDO"
####Aura.SQL连接
aura = $factory->getAuraSql(); // or $aura = $factory['aura.sql']; echo get_class( $aura ); // "Aura\Sql\Connection\Mysql", for example // Common configuration afterwards $aura->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION ); $aura->setAttribute( \PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
####mysqli连接
$mysqli = $factory->getMysqli(); // or $mysqli = $factory['mysqli']; echo get_class( $mysqli ); // "mysqli"
##多个数据库:使用服务定位器
假设您的项目处理几个不同的数据库,凭证等信息在一个JSON配置文件中。首先,使用配置选项(见下文完整列表)描述每个连接
#####示例配置文件
{ "first_db" : { "host": "db_host", "database": "db_name", "user": "db_user", "pass": "db_pass" }, "second_db" : { "host": "other_host", "database": "other_db", "user": "other_user", "pass": "other_pass", "type": "not_mysql", "charset": "utf8" } }
###用法
- 将配置内容解析为
StdClass
对象 - 创建一个新的
DatabaseServiceLocator
实例,
传入你的数据库描述 - 获取你的数据库的
DatabaseProvider
实例 - 让工厂创建通用的连接
<?php use \tomkyle\Databases\DatabaseServiceLocator; $config = json_decode( file_get_contents( 'config.json' )); $databases = new DatabaseServiceLocator( $config ); // 1. Get DatabaseProvider instance, Pimple-style: $first_factory = $databases['first_db']; // 2. Let factory create Aura.SQL connection: $first_aura = $first_factory->getAuraSql();
###获取连接 在DatabaseServiceLocator
中传入的每个数据库都将像数组成员一样可用。返回的数据库将是一个类似Singleton的DatabaseProvider
实例。
$foo_factory = $databases['foo_db']; echo get_class( $foo_factory ); // "DatabaseProvider"
由于服务定位器和工厂都是Pimple扩展,您也可以在一次调用中获取连接
$databases = new DatabaseServiceLocator( $config ); $first_pdo = $databases['first_db']->getPdo(); $first_mysqli = $databases['first_db']->getMysqli(); $first_aura = $databases['first_db']->getAuraSql(); $second_pdo = $databases['second_db']['pdo']; $second_mysqli = $databases['second_db']['mysqli']; $second_aura = $databases['second_db']['aura.sql'];
##最佳实践 如果一个类需要特殊的数据库连接,比如说PDO,可以这样做
- 获取你的连接提供者
- 让它为你创建一个PDO连接
- 注入生成的PDO。
…下一个依赖Aura.SQL的类
- 使用相同的连接提供者实例(记住:Singleton!)
- 让它为你创建一个Aura.SQL连接
- 注入生成的Aura.SQL MySQL连接。
这样,当事情出错时,它们会在你的业务类之外出错(控制反转)。
Paul M. Jones最近在他的新发表的“应用程序层DI容器应该在哪里?”文章中介绍了这个话题。
##问题和答案
###等等,这不是一个反模式吗? 是的,如果你在类中使用DatabaseServiceLocator作为依赖项,在构造函数或Setter方法中注入它,或者对其进行类型提示,或者不这样做。不是,如果你在你的组合根或配置环境中使用它。
###连接配置有多远?除了它们的字符集之外,“工厂外”的连接没有进行特殊配置。所以如果你喜欢更改默认的fetch模式或(想想PDO::setAttribute
),你可能需要自己配置它。记住,每个连接都是通用的!
###关于Aura.SQL v2?目前,DatabaseServiceLocator支持Aura.SQL v1.3。随着Aura v2的即将到来,Aura.SQL被拆分为三个模块Aura.SQL v2 Aura.SQL_Query和Aura.SQL_Schema - 请参阅Paul M. Jones的文章“一瞥Aura v2 -- Aura.Sql和ExtendedPdo”。
我将尽快添加v2支持,一旦v2变得稳定或成为标准,并且我习惯了它。如果你已经习惯了,欢迎你fork自己的DatabaseServiceLocator :-)