sergiosgc/crud-trait

PHP trait,允许在PHP类上实现创建、读取、更新、删除操作

dev-master 2024-09-12 17:16 UTC

This package is auto-updated.

Last update: 2024-09-12 17:16:40 UTC


README

Crud-trait 是一种面向对象关系映射的最小化方法。它基于这样一个预期:任何ORM都是存在漏洞的。如果任何ORM都有漏洞,那么帕累托方法,即基本查询由ORM自动化,而将复杂的SQL访问留给所有其他用例,将导致代码库更简单。

5分钟使用指南

将你的类声明为使用该trait,添加SQL列作为公共PHP字段,并重写getDB方法

class VirtuousGizmo {
    use \sergiosgc\crud\CRUD;
    
    public $id = null;
    public $name = null;
    public $color = null;
    public static function getDB() {
        MyApp::singleton()->getDB(); // Should return a PDO Connection
    }
}

Crud-trait 将假设你的表名为 virtuous_gizmo,拥有键 id 和字段 idnamecolor

现在你可以使用 dbCreate()、dbRead()、dbUdate()、dbDelete() 方法在类/表上操作了

$gizmo = new VirtuousGizmo();
$gizmo->name = 'ZoomZoom';
$gizmo->color = 'blue';
$gizmo->dbCreate(); // $gizmo->id is assigned by dbCreate()
printf('Created gizmo with id %d', $gizmo->id);
$gizmo->color = 'green';
$gizmo->dbUpdate();

$gizmo = VirtuousGizmo::dbRead('color = ?', 'green');
printf('Green gizmo has id %d', $gizmo->id);
$gizmo->dbDelete();

设置读取

你可以使用 dbReadPaged 方法读取一组对象

list($gizmos, $gizmoCount) = VirtuousGizmo::dbReadPaged('name', 'ASC', 'color = ?', 1, 20, 'blue');

这将读取所有颜色为蓝色的gizmos的第1页,按 name 递增排序,每页20个项目。该函数返回一个包含 VirtuousGizmo 的数组和总计数(用于分页UI)。所有在页面大小(本例中为20)之后的参数都传递给查询执行。

就这么多。文档的其余部分将重点介绍如何处理抽象漏洞

  • 以观点导向的方法处理漏洞
  • 将漏洞处理到底层的SQL中

处理抽象漏洞

观点导向的方法重写

Crud-trait 预期底层表与通过启发式定义的定义匹配。如果不匹配,则需要重写一些方法。

表名

默认情况下,表名定义为类名,每个大写字母前都有一个下划线,并转换为小写。例如,将 camelCase 类名转换为 underscore_case。

如果这不可行,则需要重写 dbTableName 静态方法。例如

public static function dbTableName() { return 'virtuousgizmos'; }

字段

默认情况下,表列是所有公共字段,名称与PHP字段相同。如果这不可行,则需要重写 dbFields() 静态方法。例如

public static function dbFields() { return ['id', 'name']; }

键字段

对于键字段的默认假设是,如果存在 id 字段,它是主键,否则没有键。如果这不可行,则需要重写 dbKeys() 静态方法。例如

public static function dbKeyFields() { return ['id', 'name']; }

请注意,如果有多个键,则 dbCreate() 不会在插入后填充对象的字段。

字段(反)序列化

如果字段在存储之前需要序列化,则重写 dbSerializeField() 和 dbUnserializeField。假设我们的示例类有一个 $parts 字段,它是一个部分数组

public static function dbSerializeField($field, $value) {
  switch ($field) {
    case 'parts': return serialize($value);
    default: return $value;
  }
}
public static function dbUnserializeField($field, $value) {
  switch ($field) {
    case 'parts': return unserialize($value);
    default: return $value;
  }
}

可描述的接口

如果你发现自己经常重写这些方法,那么查看 Describable interface 可能是值得的

SQL访问

如果你需要直接执行SQL查询,你可以访问 dbExec()、dbFetchAll() 和 dbFetchAllCallback()。dbExec 和 dbFetchAll 接收一个带有占位符(?)的查询和要放入占位符中的值作为参数。dbExec 执行查询并返回空(错误时抛出异常)。dbFetchAll 执行查询并返回所有行。dbFetchAllCallback 执行查询,使用回调(第二个参数)映射行,并返回结果数组。

dbFetchAllCallback,即允许你使用非基本查询获取一组对象。例如

$gizmos = VirtuousGizmo::dbFetchAllCallback(<<<EOQ
SELECT * FROM alpha_gizmos WHERE color = ?
UNION
SELECT * FROM beta_gizmos WHERE release > ?
EOQ
  , function ($row) { return (new VirtuousGizmo())->dbMap($row); } ,
  'green', 
  1.0);

处理表/类之间的关系

处理关系的功能取决于字段描述,具体请参考可描述接口中的文档