PHP 的轻量级数据库抽象层

1.1.0 2023-01-18 13:34 UTC

This package is auto-updated.

Last update: 2024-09-23 15:26:01 UTC


README

DB Link 是一个为 PHP 设计的轻量级数据库抽象层,部分灵感来自 Django

请注意,DB Link 不会为您管理数据库结构。如果您更新了一个模型类,则必须相应地更新数据库模式,反之亦然。

配置

对于数据库连接,DB Link 将寻找一个名为 dblink_create_pdo() 的函数,该函数必须由用户定义。该函数必须具有以下签名

function dblink_create_pdo(): PDO

一个基本用法可能如下实现

function dblink_create_pdo(): PDO
{
    $db_host = "127.0.0.1";
    $db_name = "my_database";
    $db_user = "my_user";
    $db_password = "this_is_top_secret";

    return new PDO(
        "mysql:dbname=$db_name;host=$db_host",
        $db_user,
        $db_password
    );
}

确保在调用任何 DB Link 函数之前包含此函数。如果找不到此函数,将抛出 LogicException

创建模型

您可以通过扩展 Model 类来创建您的模型。函数 get_table_name() 应返回相关数据库表的名称,作为字符串。函数 get_attributes() 应返回一个数组,其中键是数据库列名,值是 Field 子类的实例。

use \Getpastthemonkey\DbLink\Model;
use \Getpastthemonkey\DbLink\fields\IntegerField;
use \Getpastthemonkey\DbLink\fields\CharField;

class User extends Model
{
    protected static function get_table_name(): string
    {
        return "users";
    }

    protected static function get_attributes(): array
    {
        return array(
            "id" => new IntegerField(is_primary_key: true),
            "username" => new CharField(),
            "mail" => new CharField(),
            "is_admin" => new IntegerField(min: 0, max: 1, default: 0),
        );
    }
}

目前,仅支持 IntegerFieldCharField 字段类型,但计划在未来的更新中增加更多字段类型,例如 TextFieldDateFieldDateTimeField。在此期间,请使用 CharField 来实现这些目的。

运行查询

以下展示了可用的查询功能示例。

// Example 1: Basic example
// Load all users (using the default ordering of the database)
$users = User::objects();

// Example 2: Filtering
// Only load users that have a Gmail address
use \Getpastthemonkey\DbLink\filters\F_LIKE;
$users = User::objects()->filter(new F_LIKE("mail", "%@gmail.com"));

// Example 3: Exclude
// Load all users that do not have a Gmail address
use \Getpastthemonkey\DbLink\filters\F_LIKE;
$users = User::objects()->exclude(new F_LIKE("mail", "%@gmail.com"));

// Example 4: Ordering
// Load all users sorted by increasing name
$users = User::objects()->order("name");

// Example 5: Reverse ordering
// Load all users sorted by decreasing ID
$users = User::objects()->order("id", false);

// Example 6: Limit
// Only load the first 10 users
$users = User::objects()->limit(10);

// Example 7: Limit and offset
// Load 10 users without loading the first 20 users
$users = User::objects()->limit(10, 20);

所有这些示例都返回一个 Query 对象。函数调用可以是任意链式的。Query 类实现了 Countable 接口,因此可以使用 count() 函数获取返回的行数。Query 类还实现了 Iterator 接口,因此可以通过迭代 Query 实例来获取查询结果。

过滤器列表

以下表格显示了所有可用的过滤器类。它们都在 \Getpastthemonkey\DbLink\filters 命名空间中。

加载单个模型实例

如果筛选单个实例,可以使用 Query 类的 get() 方法。

如果查询没有返回条目,将抛出 ObjectDoesNotExistException。如果查询返回多个条目,将抛出 MultipleObjectsReturnedException

访问模型属性

Model 类实现了 ArrayAccess 接口,并重载了大多数魔术方法。因此,有两种访问模型属性的方法。

访问模型属性的第一种方法是使用 ArrayAccess 接口,它允许数组风格的访问。

$users = User::objects();

foreach ($users as $user) {
    echo "<tr>
        <td>" . $user["id"] . "</td>
        <td>" . $user["username"] . "</td>
        <td>" . $user["mail"] . "</td>
        <td>" . $user["is_admin"] . "</td>
    </tr>";
}

第二种选择是使用重载的魔术方法,通过类成员风格访问属性。请注意,此选项可能会在 IDE 中给出警告,因为属性未在类中定义。

$users = User::objects();

foreach ($users as $user) {
    echo "<tr>
        <td>" . $user->id . "</td>
        <td>" . $user->username . "</td>
        <td>" . $user->mail . "</td>
        <td>" . $user->is_admin . "</td>
    </tr>";
}

更新模型属性

更新模型属性的方法与访问模型属性的方法相同:通过 ArrayAccess 接口或重载的魔术方法。

以下是一个使用 ArrayAccess 接口更新属性并将其保存回数据库的示例。内部保存也验证了当前字段值。

use \Getpastthemonkey\DbLink\exceptions\ValidationException;

$user = User::objects()->current();
$user["is_admin"] = 1;

try {
    $user->save();
} catch (ValidationException $e) {
    // The instance did not pass the validation checks
    // Use $e->children to get an array of validation exceptions with more details about the failed checks
}

要在不保存实例的情况下检查其实例是否有效,请调用 validate() 而不是 save()。如果实例无效,将抛出 ValidationException 异常。如果它有效,则不会发生任何事。

创建新实例

通过调用 Model 子类的构造函数,创建一个新的模型实例。所有字段都持有定义的默认值。如果一个字段没有默认值,它将是 NULL。请注意,新实例仅存在于 PHP 运行时中,但它并未保存到数据库中。要将实例添加到数据库中,必须调用 save()

以下是如何创建新的 User 并将其保存到数据库的示例。

use \Getpastthemonkey\DbLink\exceptions\ValidationException;

$user = new User();
$user["id"] = 123;
$user["username"] = "my_username";
$user["mail"] = "me@example.com";

try {
    $user->save();
} catch (ValidationException $e) {
    // The instance did not pass the validation checks
    // Use $e->children to get an array of validation exceptions with more details about the failed checks
}

删除实例

可以通过调用 delete() 函数来删除单个模型实例。请注意,数据库条目将被删除,但模型实例仍然存在于代码中。

以下是删除 ID 为 123 的用户的示例。

use \Getpastthemonkey\DbLink\filters\F_EQ;

$user = User::objects()->filter(new F_EQ("id", 123))->get();
$user->delete();

通过在 Query 实例上调用 delete() 支持批量删除。查询返回的所有条目都将被删除。

以下是删除所有非管理员的用户的示例。

use \Getpastthemonkey\DbLink\filters\F_EQ;

User::objects()->filter(new F_EQ("is_admin", 0))->delete();

故障排除

由于 DB Link 是一个新的项目,目前还没有关于常见问题或问题的完整指南。如果您有任何问题或问题,请毫不犹豫地打开 GitHub 问题