hawkbit/database

面向对象的数据库处理

1.0.2 2016-12-15 12:57 UTC

This package is not auto-updated.

Last update: 2024-09-14 19:47:40 UTC


README

Latest Version on Packagist Software License Build Status Total Downloads Coverage Status

使用 POPO's、工作单元、标识映射和数据映射进行面向对象的数据库处理。

安装

使用 Composer

Hawkbit Database 可在 Packagist 上找到,并可以使用 Composer 安装。可以通过运行以下命令或更新您的 composer.json 文件来实现。

composer require hawkbit/database

composer.json

{
    "require": {
        "hawkbit/database": "~1.0"
    }
}

请确保还将您的 Composer 自动加载文件包含到您的项目中

<?php

require __DIR__ . '/vendor/autoload.php';

下载 .zip 文件

此项目也可作为 .zip 文件在 GitHub 上下载。访问 发行页面,选择您想要的版本,然后单击“源代码(zip)”下载按钮。

要求

此版本支持以下版本的 PHP。

  • PHP 5.5
  • PHP 5.6
  • PHP 7.0
  • PHP 7.1
  • HHVM

使用

连接并开始!

  1. 注册连接
  2. 如果您需要使用工作单元和映射器,请注册映射器
  3. 享受乐趣!

示例

我们还提供了 示例 用于以下文档。

连接

<?php
use Hawkbit\Database\ConnectionManager;

// setup connection
$connection = ConnectionManager::create([
    'url' => 'sqlite:///:memory:',
    'memory' => 'true'
]);

共享连接

在大型应用程序中,您需要在多个点访问连接。只需共享您的连接

<?php
use Hawkbit\Database\ConnectionManager;

ConnectionManager::getInstance()->add($connection);

您可能想节省时间或代码行数,并直接添加连接

<?php
use Hawkbit\Database\ConnectionManager;

ConnectionManager::getInstance()->add([
  'url' => 'sqlite:///:memory:',
  'memory' => 'true'
]);

并在应用程序的另一个点访问连接

<?php
use Hawkbit\Database\ConnectionManager;

ConnectionManager::getInstance()->get();
多个连接

在某些情况下,您可能需要两个或更多的连接。因此,连接可以有一个名称,默认名称是 default (Hawkbit\Database\ConnectionManager::DEFAULT_CONNECTION)。

<?php
use Hawkbit\Database\ConnectionManager;

// add connections
ConnectionManager::getInstance()->add([
  'url' => 'sqlite:///:memory:',
  'memory' => 'true'
]);

ConnectionManager::getInstance()->add([
  'url' => 'mysql://<user>:<password>@<host>/<database>?charset=utf8',
], 'second');

// and access connections

$default = ConnectionManager::getInstance()->get();
$second = ConnectionManager::getInstance()->get('second');
前缀

在共享数据库上,使用特定名称前缀表非常有用,例如应用程序缩写。您需要在您的连接上设置前缀。系统将自动前缀所有表名。

添加 PHP 7.1 支持

<?php

// setup prefixes
$connection->setPrefix('custom_');
$gateway = $connection->createGateway('user'); // connects to custom_user table

如您所见,您(以及映射器)传递表名,内部表名将被前缀。

迁移

使用 SQL 简单设置模式
<?php
use Hawkbit\Database\ConnectionManager;

// add connections
$connection = ConnectionManager::getInstance()->get();

// setup schema
$connection->exec('CREATE TABLE post (id int, title VARCHAR(255), content TEXT, date DATETIME DEFAULT CURRENT_DATE )');
使用 phinx 进行高级迁移

此包不提供模式迁移。我们建议使用类似 Phinx 的包进行高级迁移。

网关

网关在数据库和映射器之间进行调解。它能够执行特定表或视图的操作,并提供 CRUD 查询。

从连接创建新的网关

<?php

$gateway = $connection->createGateway('post');

创建

创建新条目

<?php
// create a new post
$gateway->create()
    ->setValue('title', 'Anything')
    ->setValue('content', 'Lorem Ipsum')
    ->execute();

读取(选择)

以数组形式获取条目(参考 \PDO::FETCH_ASSOC)。条目有以下数组表示形式

<?php
$posts = [
    0 => [
        'id' => 1,
        'title' => 'Anything',
        'content' => 'Lorem Ipsum',
    ],
    1 => [
        'id' => 2,
        'title' => 'Anything else',
        'content' => 'More text',
    ]
];
<?php

use Doctrine\DBAL\Types\Type;

$posts = $gateway
    ->select()
    ->where('title = ?')
    ->setParameter(0, 'Anything', Type::STRING)
    ->execute()
    ->fetchAll();

// process entries
foreach ($posts as $post){
    echo sprintf('<h1>%s</h1><p>%s</p>', $post['title'], $post['content']);
}

您还可以使用 doctrines 表达式生成器与 QueryBuilder::createPositionalParameterQueryBuilder::createNamedParameter 结合,进行更复杂的查询!

更新

更新条目

<?php

$gateway
    ->update()
    ->set('content', 'Cool text instead of Lorem Ipsum, but Lorem Ipsum is cool at all!')
    ->where('id = 1')
    ->execute();

删除

删除条目

<?php

$gateway
    ->delete()
    ->where('id = 1')
    ->execute();

映射器

数据映射器

数据映射器 将数据映射到实体并从实体提取数据。映射器还了解数据库表配置,并将数据类型转换为两个方向 - PHP 和数据库。它利用 标识映射,确保对象只加载一次。

示例映射器配置

建议扩展映射器以自定义逻辑来访问关联数据或其他特定数据集。目前不支持数据关联/数据关系!

映射器和实体的组合可能具有Table-Data-Gateway的被动记录风味。

实体

实体表示数据库表或视图的单个条目(行)。它是一组设置器和获取器,没有任何逻辑——被动记录。实体是纯旧PHP对象(POPO)。

示例实体

准备和加载映射器

将映射器注册到映射器定位器中,以预加载配置并确保访问。当定位器无法找到映射器时,将抛出异常。

<?php


use Application\Persistence\Mappers\PostMapper;

// register mappers
$connection->getMapperLocator()->register(PostMapper::class);

定位已注册的映射器

<?php

use Application\Persistence\Entities\Post;

$entity = new Post();
$mapper = $connection->loadMapper($entity);

根据实体定位已注册的映射器

<?php

use Application\Persistence\Entities\Post;

// entity instance is also allowed
$mapper = $connection->loadMapper(Post::class);

// or create entity from mapper

从映射器创建实体,如果您不想创建新实例的实体

<?php
$entity = $mapper->createEntity();

修改数据

映射器能够确定实体状态并保存(创建或更新)数据。映射器正在修改相同的实体实例。对数据库所做的所有更改也将同时存储到实体中。

创建

创建条目

<?php

// create entity
$entity->setContent('cnt');
$mapper->create($entity);
更新

更新条目

<?php

$entity->setContent('FOO');
$mapper->update($entity);
保存

映射器还能够检测新或现有的实体,并选择在数据库中创建或更新相关条目。

<?php

$entity->setContent('FOO');
$entity->setTitle('Philosophy of bar, baz & foo');

// create or update
$mapper->save($entity);

删除

删除条目

<?php
// delete entity
$mapper->delete($entity);

获取数据

查找

通过主键或复合键查找条目并返回单个实体结果或false

<?php
 
$post = $mapper->find(['id' => 1]);
自定义选择

以实体列表的形式获取条目。条目具有以下表示

<?php
$posts = [
    0 => new Post(), // 'id': 1, 'title': 'Anything', 'content': 'Lorem Ipsum'
    1 => new Post(), // 'id': 2, 'title': 'Anything else', 'content': 'More text'
];

选择接受所有有效的可调用的类型来修改查询。

<?php

use \Doctrine\DBAL\Query\QueryBuilder;

$posts = $mapper->select(function(QueryBuilder $queryBuilder){
    // build even more complex queries
    $queryBuilder->where('id = 1');
});

// process entries

/** @var \Application\Persistence\Entities\Post $post */
foreach ($posts as $post){
    echo sprintf('<h1>%s</h1><p>%s</p>', $post->getTitle(), $post->getContent());
}

获取单个条目将返回一个实体而不是实体列表

<?php

use \Doctrine\DBAL\Query\QueryBuilder;

$one = true;
$post = $mapper->select(function(QueryBuilder $queryBuilder){
    // build even more complex queries
    $queryBuilder->where('id = 1');
}, ['*'], $one);

事务(工作单元)

为了数据一致性,您想要使用事务。基本上,所有查询都包裹在一个事务中,如果启用了自动提交选项,则自动提交。您也可以创建、更新和删除大量数据,并一次提交它们。

内置的doctrine事务

要使用工作单元,您需要注册一个映射器。在某些情况下,例如原型设计,您可能希望使用网关以快速访问。因此,您应使用内置事务。

<?php

try {
    $connection->beginTransaction();
    
    $gateway->update()->set('content', 'blah')->where('id = 1');
    $gateway->update()->set('content', 'blub')->where('id = 2');
    $gateway->delete()->where('id in(32,45,16)');
    $gateway->create()->setValue('content', 'i am new!')->execute();
    
    $connection->commit();

} catch (\Exception $e) {
    $connection->rollBack();
    
    // you may want to pass exception to next catch
    throw $e;
}

工作单元 - 与映射器的事务

事务需要注册的映射器才能正确工作。

以任何顺序修改您的数据,工作单元会为您排序创建、更新和删除的执行。如果所有修改都已完成,您需要执行UnitOfWork::commit。请参考以下工作单元示例。

<?php

use Application\Persistence\Entities\Post;

$unitOfWork = $connection->createUnitOfWork();
$entity = new Post();

// or create entity from mapper
//$entity = $mapper->createEntity();

// create entity
$entity->setContent('cnt');
$unitOfWork->create($entity);

// commit transaction
if(false === $unitOfWork->commit()){
    //handle exception
    $unitOfWork->getException();

    // get last processed entity
    $unitOfWork->getLastProcessed();
}

// get all modified entities
$unitOfWork->getModified();

// get a list of all entities by state
$unitOfWork->getProcessed();

// find entity by primary key or compound key
$mapper = $connection->loadMapper($entity);
$mapper->find(['id' => 1]);

// update entity
$entity->setContent('FOO');
$unitOfWork->update($entity);

// delete entity
$unitOfWork->delete($entity);

// commit transaction, again
$unitOfWork->commit();

变更日志

有关最近更改的更多信息,请参阅CHANGELOG

测试

$ composer test

贡献

有关详细信息,请参阅CONTRIBUTING

安全

如果您发现任何与安全相关的漏洞,请通过电子邮件mjls@web.de而不是使用问题跟踪器。

鸣谢

许可协议

MIT许可(MIT)。有关更多信息,请参阅许可文件