ray/aura-sql-module

Ray.Di 的 aura/sql 模块

1.13.2 2023-07-10 23:32 UTC

README

Scrutinizer Code Quality codecov Type Coverage Continuous Integration

Aura.Sql 模块,用于 Ray.Di

安装

Composer 安装

$ composer require ray/aura-sql-module

模块安装

use Ray\Di\AbstractModule;
use Ray\AuraSqlModule\AuraSqlModule;
use Ray\AuraSqlModule\AuraSqlQueryModule;

class AppModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(
            new AuraSqlModule(
                'mysql:host=localhost;dbname=test',
                'username',
                'password',
                'slave1,slave2,slave3' // optional slave server list
                $options,              // optional key=>value array of driver-specific connection options
                $queries               // Queries to execute after the connection.
        );
    }
}

使用 AuraSqlEnvModule 在每次运行时从环境变量获取值,而不是直接指定值。

        $this->install(
            new AuraSqlEnvModule(
                'PDO_DSN',             // getenv('PDO_DSN')
                'PDO_USER',            // getenv('PDO_USER')
                'PDO_PASSWORD',        // getenv('PDO_PASSWORD')
                'PDO_SLAVE'            // getenv('PDO_SLAVE')
                $options,              // optional key=>value array of driver-specific connection options
                $queries               // Queries to execute after the connection.
        );

DI 特性

复制

使用 AuraSqlReplicationModuleconnection locator 安装主/从连接。

use Ray\Di\AbstractModule;
use Ray\AuraSqlModule\AuraSqlModule;
use Ray\AuraSqlModule\Annotation\AuraSqlConfig;
use Aura\Sql\ConnectionLocator;

class AppModule extends AbstractModule
{
    protected function configure()
    {
        $locator = new ConnectionLocator;
        $locator->setWrite('master', new Connection('mysql:host=localhost;dbname=master', 'id', 'pass'));
        $locator->setRead('slave1',  new Connection('mysql:host=localhost;dbname=slave1', 'id', 'pass'));
        $locator->setRead('slave2',  new Connection('mysql:host=localhost;dbname=slave2', 'id', 'pass'));
        $this->install(new AuraSqlReplicationModule($locator));
    }
}

在使用 HTTP GET 时,您将拥有从数据库连接,而在其他 HTTP 方法中使用主数据库连接。

多个数据库

您可能希望在相同的数据库接口上注入不同的连接目标,使用 @Named($qualifier) 注解。提供了两个模块。 NamedPdoModule 用于非复制使用,而 AuraSqlReplicationModule 用于复制使用。

#[Inject]
public function setLoggerDb(#[Named('log_db') ExtendedPdoInterface $pdo)
{
    // ...
}

无复制

使用 NamedPdoModule 注入不同的命名 Pdo 实例以进行 复制使用。例如,此模块安装了名为 log_dbPdo 实例。

class AppModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new NamedPdoModule('log_db', 'mysql:host=localhost;dbname=log', 'username', 
    }
}

或者

class AppModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new NamedPdoEnvModule('log_db', 'LOG_DSN', 'LOG_USERNAME', 
    }
}


### with replication

You can set `$qaulifer` in 2nd parameter of AuraSqlReplicationModule.

```php
class AppModule extends AbstractModule
{
    protected function configure()
    {
        $this->install(new AuraSqlReplicationModule($locator, 'log_db'));
    }
}

事务

标记有 @Transactional 的任何方法将在调用之前开始事务,并在调用之后结束事务。

use Ray\AuraSqlModule\Annotation\WriteConnection; // important
use Ray\AuraSqlModule\Annotation\Transactional;   // important

class User
{
    public $pdo;

    #[WriteConnection, Transactional]
    public function write()
    {
         // $this->pdo->rollback(); when exception thrown.
    }
}

查询构建器

Aura.SqlQuery 为 MySQL、Postgres、SQLite 和 Microsoft SQL Server 提供查询构建器。以下四个接口已绑定,并且为它们提供了setter特性。

QueryBuilder 接口

  • Aura\SqlQuery\Common\SelectInterface
  • Aura\SqlQuery\Common\InsertInterface
  • Aura\SqlQuery\Common\UpdateInterface
  • Aura\SqlQuery\Common\DeleteInterface

QueryBuilder setter 特性

  • Ray\AuraSqlModule\AuraSqlSelectInject
  • Ray\AuraSqlModule\AuraSqlInsertInject
  • Ray\AuraSqlModule\AuraSqlUpdateInject
  • Ray\AuraSqlModule\AuraSqlDeleteInject
use Ray\AuraSqlModule\AuraSqlSelectInject;
clas Foo
{
    use AuraSqlSelectInject;
    
    public function bar()
    {
        /* @var $select \Aura\SqlQuery\Common\SelectInterface */
        $this->select // 
            ->distinct()                    // SELECT DISTINCT
            ->cols(array(                   // select these columns
                'id',                       // column name
                'name AS namecol',          // one way of aliasing
                'col_name' => 'col_alias',  // another way of aliasing
                'COUNT(foo) AS foo_count'   // embed calculations directly
            ))
            ->from('foo AS f');              // FROM these tables
        $sth = $this->pdo->prepare($this->select->getStatement());
        // bind the values and execute
        $sth->execute($this->select->getBindValues());
        // get the results back as an associative array
        $result = $sth->fetch(PDO::FETCH_ASSOC);
         = $sth->fetch(PDO::FETCH_ASSOC);

分页

ExtendedPdo 原始 SQL 和 Select 查询构建器提供了分页服务。

ExtendedPdo

use Ray\AuraSqlModule\AuraSqlPagerInject;

class Foo
{
    use AuraSqlPagerInject;

    publuc function bar()
    {   
        // ...     
        $pager = $this->pagerFactory->newInstance($pdo, $sql, $params, 10, '/?page={page}&category=sports'); // 10 items per page
        $page = $pager[2]; // page 2

Select 查询构建器

use Ray\AuraSqlModule\Pagerfanta\AuraSqlQueryPagerInject;

class Foo
{
    use AuraSqlQueryPagerInject;

    publuc function bar()
    {
        // ...     
        $pager = $this->queryPagerFactory->newInstance($pdo, $select, 10, '/?page={page}&category=sports');
        $page = $pager[2]; // page 2

使用页面编号进行数组访问返回 Page 值对象。

/* @var Pager \Ray\AuraSqlModule\Pagerfanta\Page */

// $page->data // sliced data
// $page->current;
// $page->total
// $page->hasNext
// $page->hasPrevious
// $page->maxPerPage;
// (string) $page // pager html

它是可迭代的。

foreach ($page as $item) {
 // ...

视图

可以使用绑定更改视图模板。更多信息请参阅 Pagerfanta

use Pagerfanta\View\Template\TemplateInterface;
use Pagerfanta\View\Template\TwitterBootstrap3Template;
use Ray\AuraSqlModule\Annotation\PagerViewOption;

$this->bind(TemplateInterface::class)->to(TwitterBootstrap3Template::class);
$this->bind()->annotatedWith(PagerViewOption::class)->toInstance($pagerViewOption);

配置文件

要记录 SQL 执行,请安装 AuraSqlProfileModule。它将使用绑定到 PSR-3 日志记录器的记录器进行记录。此示例绑定了一个在未命名类中创建的最小函数记录器。

class DevModule extends AbstractModule
{
    protected function configure()
    {
        // ...
        $this->install(new AuraSqlProfileModule());
        $this->bind(LoggerInterface::class)->toInstance(
            /** 
            new class extends AbstractLogger {
                /** @inheritDoc */
                public function log($level, $message, array $context = [])
                {
                    $replace = [];
                    foreach ($context as $key => $val) {
                        if (! is_array($val) && (! is_object($val) || method_exists($val, '__toString'))) {
                            $replace['{' . $key . '}'] = $val;
                        }
                    }
            
                    error_log(strtr($message, $replace));
                }
            }
        );
}