定制 thoom/dbm 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

thoom/dbm

Composer 安装命令:

composer require thoom/dbm

包简介

PHP 5.3 classes that extend doctrine DBAL using an entity-manager relationship with hooks for Silex

README 文档

README

Summary

NOTE: These classes are still in development and change frequently. Use with caution and at your own risk for now!

This is a collection of database classes that are being developed to use the Silex framework for building simple websites. The database classes are built on top of the Doctrine DBAL support that is included with Silex.

Thoom\Provider\DbServiceProvider

The DbServiceProvider implements the Silex\ServiceProviderInterface. This provider also registers Silex\Provider\DoctrineServiceProvider so it doesn't need to be registered separately. In addition, this provider adds a Thoom\Db\ManagerFactory object to the DI container. This makes it possible to access managers without adding each manager to the Silex application.

There is only one additional parameter that you need to pass in the register array:

  • dbm.options: This array collection only contains one key at the moment: format. This is your managers' fully qualified name in printf format. For instance, if you had managers named My\Db\UserManager and My\Db\AppManager, the format would be My\Db\%sManager.

To register the provider:

$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

The Db classes use an Entity-Manager relationship, where an entity in abstract represents a database row. The manager is its tie to the database and provides CRUD methods to interact with it.

Understandably, there are many object-oriented database implementations. Doctrine ORM is an obvious alternative as Thoom\Db also utilizes Doctrine's DBAL to interface with the database. This framework is not meant as a full-featured replacement but rather a lighter-weight alternative with a different way of managing entities.

The entity

The entity isn't much more than a data store. The extent of its logic relates to how it silos data into three different arrays: values, modified, and container.

Each array serves a distinct purpose:

  • values: Data in this array is extremely protected, filled in only when the entity is created or in the resetData method. The values should represent current database values. This array is the only one stored on serialization!

  • modified: This array is filled in whenever data is posted using ArrayAccess or __set methods. Its values are used when inserting/updating records in the database.

  • container: Any values passed to the entity whose keys are not found in the values array are placed in the container array instead. The purpose of the container is to provide a space for additional data to be attached that doesn't pollute the table data.

Usage

Creating an entity in its simplest form is easy:

namespace My\DbNamespace;

use Thoom\Db\EntityAbstract;

class User extends EntityAbstract{}

There are several ways to access the data in an entity. Here are a few options:

  • As an object:

    $entity->foo = 'bar';
    echo $entity->foo; //prints "bar"
    
  • As an array:

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

The entity by default saves data to the modified array if key exists in the values array, otherwise it's saved to the container's array. This can be overridden very easily by creating get/set methods named after the keys to be overridden.

For example, if we want to make sure that the key foo is made lowercase before it's saved to the modified array, in your entity class add a setFoo method:

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

Now if we made the same calls as before:

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

Obviously you want to be careful with this functionality, since your input may not match the output!

Using this functionality you could also introduce some faux properties. For instance, say your database stores the user's name as firstName and lastName. You don't want to have to concat these values all the time. Instead, create a faux property!

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

Now use it like any other property (say this user has the first name: Bruce and last name: Banner):

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

Note that if you tried to set the full name, it would end up storing the value in the container array unless you also created a setFullName method:

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

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

Voila!

The manager

The manager is the entity's interface with the database. The manager behaves as an entity factory, where it creates new entities and injects any dependencies. It houses all data about the table it represents, including the table's name, the columns with their default values and types, the primary key's field name, etc.

The manager uses Dependency Injection to receive its connection to the database.

Usage

There are a few properties that should be defined when creating a new manager. Here's an example:

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';
}

Let's review these properties:

  • entity: This is the fully qualified name of the entity class that will be returned from CRUD calls.
  • columns: This is an array of the database column names. These are used to determine what data in the entity is saved to the database.
  • primaryKey: The table's primary key column name.
  • table: The name of the table the manager, um, manages. If this field is not populated, the manager will set it based on the class's name.

To use with Silex, I recommend using the Thoom\Provider\DbServiceProvider. This will create an object reference to the ManagerFactory, which is explained in detail below. However, to use the manager generically in a Silex controller:

$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']));
});

Whenever you send an entity to the Manager to update the database, you will need to refresh the entity if you want it to reflect the changes made to the database (i.e. via triggers, etc).

Here's an example of creating a new user named Bruce Banner and then refreshing the entity so that the data exists:

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

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

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

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

Alternatively, you can use a convenience method (available for both create and update methods):

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

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

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

The manager factory

An alternative to creating a manager every time is to use the ManagerFactory. Once instantiated, the factory object has two methods:

  • get($name): This returns an instance of the object based on the name. If an object has already been created, it returns the object being stored.

  • fresh($name): This always returns a new instance of the object based on the name.

Usage

Using the Thoom\Provider\DbServiceProvider in a Silex controller:

$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']));
});

To create an object manually:

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

The second argument for the factory is the format that your Managers are named in a printf format. You only need to pass in the missing piece of the format in the get and fresh methods.

thoom/dbm 适用场景与选型建议

thoom/dbm 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 9 次下载、GitHub Stars 达 1, 最近一次更新时间为 2013 年 02 月 02 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「silex」 「database」 「doctrine2」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 thoom/dbm 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 thoom/dbm 我们能提供哪些服务?
定制开发 / 二次开发

基于 thoom/dbm 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 9
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 27
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2013-02-02