thoom/dbm

该软件包已被废弃,不再维护。未建议替代软件包。

PHP 5.3 类,通过实体管理器关系扩展 doctrine DBAL,并为 Silex 提供钩子

dev-master 2013-02-02 05:30 UTC

This package is not auto-updated.

Last update: 2023-11-11 09:02:59 UTC


README

摘要

注意:这些类仍在开发中,经常变化。请谨慎使用,并自行承担风险!

这是一个数据库类集合,用于使用 Silex 框架构建简单网站。数据库类建立在 Silex 包含的 Doctrine DBAL 支持之上。

Thoom\Provider\DbServiceProvider

DbServiceProvider 实现了 Silex\ServiceProviderInterface。此提供程序还注册了 Silex\Provider\DoctrineServiceProvider,因此不需要单独注册。此外,此提供程序将 Thoom\Db\ManagerFactory 对象添加到 DI 容器中。这使得能够访问管理器,而无需将每个管理器添加到 Silex 应用程序中。

在注册数组中需要传递的一个额外参数

  • dbm.options:此数组集合目前只包含一个键:format。这是您的管理器的完全限定名,采用 printf 格式。例如,如果您有名为 My\Db\UserManagerMy\Db\AppManager 的管理器,则格式将为 My\Db\%sManager

注册提供程序

$app->register(new Thoom\Provider\DbServiceProvider(),
    array(
        'db.options' => array(
            'host' => 'localhost',
            'dbname' => 'mydb',
            'user' => 'user',
            'password' => 'pass',
        ),
        'dbm.options' => array(
            'format' => 'My\Db\%sManager'
        )
    ));

Thoom\Db

Db 类使用实体管理器关系,其中抽象实体代表数据库行。管理器是其与数据库的连接,并提供 CRUD 方法来与之交互。

显然,有许多面向对象的数据库实现。Doctrine ORM 是一个明显的替代品,因为 Thoom\Db 也利用 Doctrine 的 DBAL 与数据库接口。这个框架不是为了作为功能齐全的替代品,而是一个不同的实体管理方式的轻量级替代品。

实体

实体不仅仅是数据存储。其逻辑的广度仅涉及如何将其数据隔离到三个不同的数组:值、已修改和容器。

每个数组都有其独特的目的

  • values:此数组中的数据受到极度的保护,仅在实体创建或在 resetData 方法中填充。值应表示当前的数据库值。此数组是唯一存储在序列化中的数组!

  • modified:每次使用 ArrayAccess 或 __set 方法提交数据时,都会填充此数组。其值用于在数据库中插入/更新记录。

  • container:任何传递给实体但键不在值数组中的值将放置在容器数组中。容器的作用是为附加额外的数据提供一个空间,而不会污染表数据。

用法

以最简单的方式创建实体很容易

namespace My\DbNamespace;

use Thoom\Db\EntityAbstract;

class User extends EntityAbstract{}

有几种方法可以访问实体中的数据。这里有一些选项

  • 作为对象

    $entity->foo = 'bar';
    echo $entity->foo; //prints "bar"
    
  • 作为数组

    $entity['foo'] = 'bar';
    echo $entity['foo']; //prints "bar"
    

实体默认将数据保存到修改数组中,如果键存在于值数组中,否则将其保存到容器数组中。可以通过创建名为要覆盖的键的 get/set 方法非常容易地覆盖此行为。

例如,如果我们想确保在将其保存到修改数组之前,键 foo 被转换为小写,则在我们的实体类中添加一个 setFoo 方法

class BazEntity extends Thoom\Db\EntityAbstract
{
    protected function setFoo($value)
    {
       $this->modified['foo'] = strtolower($value);
    }
}

现在如果我们执行与之前相同的调用

$entity['foo'] = 'BaR';
echo $entity['foo'] // prints "bar" not "BaR"!

显然,您需要小心使用此功能,因为您的输入可能不会与输出匹配!

使用此功能,您还可以引入一些模拟属性。例如,假设您的数据库将用户名存储为firstName和lastName。您不想每次都要连接这些值。相反,创建一个模拟属性!

class UserEntity extends Thoom\Db\EntityAbstract
{
    protected function getFullName()
    {
       return $this['firstName'] . ' ' . $this['lastName'];
    }
}

现在就像使用任何其他属性一样使用它(比如说这个用户的名字是Bruce,姓氏是Banner

$user = $userManager->read($primaryKey);
echo $user->fullName; //prints "Bruce Banner"

注意,如果您尝试设置全名,除非您也创建了一个setFullName方法,否则它最终会在容器数组中存储该值

protected function setFullName($value)
{
    $names = explode(' ', $value);

    $this->modified['firstName'] = $names[0];
    $this->modified['lastName'] = $names[1];
}

哇!

经理

经理是实体与数据库的接口。经理的行为类似于实体工厂,它创建新实体并注入任何依赖项。它包含它所代表的表的所有数据,包括表的名称、具有默认值和类型的列、主键的字段名称等。

经理使用依赖注入来接收其数据库连接。

用法

创建新的经理时,应该定义一些属性。以下是一个示例

namespace My\DbNamespace;

use Thoom\Db\ManagerAbstract;

class UserManager extends ManagerAbstract
{
    protected $entity = 'My\DbNamespace\User';

    protected $columns = array(
        'uid',
        'firstName',
        'lastName',
        'username',
        'password',
        'modified'
    );

    protected $primaryKey = 'uid';

    protected $table = 'users';
}

让我们回顾一下这些属性

  • entity:这是从CRUD调用返回的实体类的完全限定名称。
  • columns:这是一个数据库列名称数组。这些用于确定在实体中保存哪些数据到数据库。
  • primaryKey:表的主键列名称。
  • table:经理管理的表的名称。如果此字段未填充,则经理将根据类的名称设置它。

要使用Silex,我建议使用Thoom\Provider\DbServiceProvider。这将创建一个指向ManagerFactory的对象引用,这将在下面详细解释。然而,为了在Silex 控制器中通用地使用经理

$app->get('/user/{primary_key}', function($primary_key) use ($app)
{
    $userManager = new My\DBNamespace\UserManager($app['db']);
    $user = $userManager->read($primary_key);

    return $app['twig']->render('index.html.twig', array('name' => $user['fullName'], 'email' => $user['email']));
});

每当您将实体发送到经理以更新数据库时,如果您想使其反映对数据库所做的更改(例如通过触发器等),则需要刷新实体。

以下是一个创建名为Bruce Banner的新用户并刷新实体以便数据存在的示例

$user = $userManager->fresh();
$user['fullName'] = 'Bruce Banner';

$id = $userManager->create($user);

if (!$id){
    //Handle this error condition

$user['id'] = $id;
$userManager->refresh($user);

或者,您可以使用便利方法(对创建和更新方法都可用)

$user = $userManager->fresh();
$user['fullName'] = 'Bruce Banner';

$user = $userManager->createAndRefresh($user);

if (!$user){
    //Handle this error condition

经理工厂

每次创建经理的替代方案是使用ManagerFactory。一旦实例化,工厂对象有两个方法

  • get($name):根据名称返回对象的实例。如果一个对象已经被创建,它返回存储的对象。

  • fresh($name):始终根据名称返回对象的新的实例。

用法

在Silex 控制器中使用Thoom\Provider\DbServiceProvider

$app->get('/user/{primary_key}', function($primary_key) use ($app)
{
    $user = $app['dbm']->get('User')->read($primary_key);

    return $app['twig']->render('index.html.twig', array('name' => $user['name'], 'email' => $user['email']));
});

手动创建对象

$factory = new Thoom\Db\ManagerFactory($db, 'My\Db\%sManager');
$userManager = $factory->get('User');

工厂的第二个参数是您的经理命名的printf格式。您只需要在getfresh方法中传递格式中的缺失部分。