figdice / gazedb
简单PDO包装器,用于敏捷且安全的ORM和直接查询
Requires
- php: >=5.6.0
Requires (Dev)
- symfony/console: 3.0.0
This package is not auto-updated.
Last update: 2024-09-28 18:35:49 UTC
README
简单PDO包装器,用于PHP的敏捷且安全的ORM和直接SQL查询
1. 摘要
当不需要完整的ORM框架时,请使用此库。
gazedb 不提供 的功能
- 全面映射完整数据库模式
- 缓存层
- 声明式关系语法
- 集合的懒加载
如果您不知道如何编写干净的、高效的SQL查询,或者如果您不了解索引如何帮助您的架构,或者如果您计划每周末更换底层数据库管理系统供应商,您应该使用其他库(如Doctrine)。您可能需要学习新的查询语言(Hibernate QL、Doctrine QL等)以及框架特定的基于注释的复杂语法来声明表之间的关系。
gazedb 提供 的功能
- 简单的 PDO 包装器
- 基于规范性常量的表和列名称的表示法
- 简单的单对象CRUD操作辅助函数
- 简单的语法,以可重用的方式帮助您创建自己的真实SQL查询
在大多数情况下,您的gazedb模型对象不知道它们之间如何关联。数据库的智能仍然掌握在您的手中(索引、最佳连接方式、何时以及如何检索等)。
2. 模型对象
为每个表创建一个类,作为ModelObject
的子类。
class Employee extends ModelObject
子类 必须 实现以下方法
tableName
mapFields
ModelObject子类 可能 实现以下方法
mapPK
mapAutoIncrement
2.1. 表名称
/** * Must override. Returns the name of the table. * @return string */ protected static function tableName() { return 'employees'; }
您永远不会直接使用tableName()
。此方法用于祖先的table()
静态方法。
Employee::table()
返回为Employee
类配置的数据库表名称。
用法
$query = "select * from ".Employee::table()." limit 10"
2.2. 列
为您的表字段声明类常量。
class Employee extends ModelObject { public const ID = 'employee_id'; public const LASTNAME = 'lastname'; public const SALARY = 'salary'; public const DEPARTMENT = 'dept_id';
这些const
不是由库显式使用的;相反,它们是可重用性辅助工具,以便您可以在代码和查询中编写非硬编码的DB标识符。
您必须通过mapFields
方法告诉gazedb哪些列是数据交换的一部分
/** * Must override. Returns the associative array of the columns mapping * (column name => default value) * @return array */ public static function mapFields() { return [ self::ID => null, self::LASTNAME => '', self::SALARY => 0, self::DEPARTMENT => null ]; }
并且您必须编写列的mutators
public function getLastname() { return $this->column(self::LASTNAME); } /** * @return Employee */ public function setLastname($value) { return $this->assign(self::LASTNAME, $value); }
通过提示返回类型为同一类来使您的设置器链式化
2.3. 主键
您可以通过覆盖方法来指定主键(包括多列主键)
/** * Should override, if the table has a PK (single- or multiple-field). * Returns an array of field names. * @return array */ public function mapPK()
您永远不需要显式调用此方法。一个典型的mapPK
实现示例是
public function mapPK() { return [ self::ID ]; }
2.4. 自增
如果您的表有一个数据库在插入时自动分配的自增列,则提供mapAutoIncrement
的实现。
/** * The name of the auto-increment column. * @return string */ public function mapAutoIncrement() { return self::ID; }
3. 构建您的查询
您通过利用const
名称的优势,在代码中编写典型查询。
$query = " select Employee.".Employee::ID.", Employee.".Employee::LASTNAME.", Dept.".Department::FLOOR." from ".Employee::table()." Employee inner join ".Department::table()." Dept on Dept.".Department::ID." = Employee.".Employee::DEPARTMENT." where Employee.".Employee::SALARY." > 10000 ";
因此,您以您选择的目标SQL方言(即实际的SQL引擎的特定语法和函数)编写真实、有效的SQL。
您可以使用PDO附带的标准参数绑定(:param
语法),并应小心处理SQL注入保护。
使用上述建议编写查询所能获得的唯一好处,是确保表和字段名称的一致性和语法检查。
4. 数据库对象
gazedb 允许您同时连接到多个不同的数据源。它使用可注入的单例模式,具有命名实例。
$db = Database::get(); $archiveDB = Database::get('archive');
您必须在数据库实例上调用 injectDsn($dsnString, $username, $password)
来指定 PDO 连接字符串。
然后,您可以直接使用以下方法操作底层的 PDO 实例:
$db->pdo()
该方法返回您的普通且熟悉的 PDO 对象,供您执行
$recordset = $db->pdo()->query($query);
4.1. CRUD 操作
除了直接在 $database->pdo() 实例上执行底层的 PDO 操作外,gazedb 还为那些映射主键的模型对象提供了简单的 CRUD 自动映射方法。
4.1.1. 加载
// "new" does not create anything in DB $employee = new Employee(); // Specify the key value for the employee you wish to load: $employee->setId(12); // Fetch the record and auto-set all the mapped columns (see mapFields() method) $database->load($employee); echo $employee->getLastname();
如果指定主键的记录找不到,Database::load
方法将抛出 ObjectNotFoundException
异常。
4.1.2. 更新
一旦您有一个已填充的对象,您可以使用其 mutators 修改任何字段,并使用 update
方法将其保存回数据库。
$employee->setFloor(8); $database->update($employee);
update
方法产生一个查询,仅更改您明确修改的值,其他所有字段保持不变。
注意:gazedb 在将对象存储回数据库之前不会检查对象的状态。如果记录被另一个进程或连接更改,您的 udpate 语句仍将被执行,而您可能并不知道。
同样,update
不会在数据库中更改自您上次调用 load
以来更改的字段重新获取对象字段。
4.1.3. 插入
$employee = new Employee(); $employee ->setLastname('Smith') ->setFloor(10) ->setSalary(60000); $database->insert($employee); echo $employee->getId();
insert
方法会触发一个插入查询,如果您的模型对象中指定了自增字段,则可选地将自增值分配给映射的自增字段。
insert
调用后,您的对象被认为是“干净的”,您可以在仅对修改的值执行 update
操作之前,通过 mutators 再次修改其值。