chrisandchris/passive-record-orm

此包已被废弃且不再维护。未建议替代包。

这是一个针对您的PHP应用程序的数据库层、被动记录和ORM抽象层。


README

Build Status Code Climate Test Coverage Version Downloads Licence

尽管它的包名为passive-record-orm,但它不仅仅是一个行映射器。它也不仅仅是为Symfony准备的。此项目是一个QueryBuilder和一个SQL结果集映射器,两者结合但仍非常独立,因此您可以独立使用它们。

<?php

use ChrisAndChris\Common\RowMapperBundle\Services\Model\ConcreteModel;

class DemoRepo {
    /** @var ConcreteModel  */
    private $model;
    
    public function __construct(ConcreteModel $model){
        $this->model = $model;
    }
    
    public function getCustomerName($customerId) {
        $query = $this->model->getDependencyProvider()->getBuilder()->select()
            ->field('customer_name')
            ->table('customer')
            ->where()
                ->field('customer_id')->equals()->value($customerId)
            ->close()
            ->getSqlQuery();

        return $this->model->runWithFirstKeyFirstValue($query);
    }
}

本文档简要概述了此包提供的所有功能。我们将内容持续移动到doc/目录中,因此请在那里查找更详细的信息。

它能做什么

  • 打开并处理MySQL连接
  • 提供一个简单的接口来构建预处理语句和查询数据库
  • 提供一个简单的接口来将结果映射到类

内部原理

基本内部原理如下

  • 存在类型(简单的键值类),它们代表语句的一部分
  • 使用解析器和同名片段(它们包含SQL)解析查询
  • 返回查询

如何使用

## 配置 如同往常一样配置您的symfony2项目。该捆绑包使用在parameters.yml中存储的数据库信息并自动连接到指定的数据库。

实际上,没有其他配置选项。

一个简单的查询

让我们创建一个服务定义

services:
    project.demo_repo:
        class: DemoRepo
        arguments: ['@common_rowmapper.model']

创建存储库

<?php

use ChrisAndChris\Common\RowMapperBundle\Services\Model\ConcreteModel;

class DemoRepo {
    /** @var ConcreteModel  */
    private $model;
    
    public function __construct(ConcreteModel $model){
        $this->model = $model;
    }
    
    public function getCustomerName($customerId) {
        $query = $this->model->getDependencyProvider()->getBuilder()->select()
            ->field('customer_name')
            ->table('customer')
            ->where()
                ->field('customer_id')->equals()->value($customerId)
            ->close()
            ->getSqlQuery();

        return $this->model->runWithFirstKeyFirstValue($query);
    }
}

如果您想将更复杂的查询映射到类,可以使用类似以下的方法

<?php

use ChrisAndChris\Common\RowMapperBundle\Entity\Entity;

class CustomerEntity implements Entity {
    public $customerId;
    public $name;
    public $street;
    public $zip;
    public $city;
}

映射时,使用此方法

<?php

use ChrisAndChris\Common\RowMapperBundle\Services\Model\ConcreteModel;

class DemoModel {
    
    /** @var ConcreteModel  */
    private $model;
    
    public function __construct(ConcreteModel $model){
        $this->model = $model;
    }
    
    public function getCustomer($customerId) {
        $query = $this->model->getDependencyProvider()->getBuilder()->select()
            ->fieldlist([
                'customer_id' => 'customerId',
                'cus_name' => 'name',
                'street',
                'zip',
                'city'
            ])
            ->table('customer')
            ->where()
                ->field('customer_id')->equals()->value($customerId)
            ->close()
            ->getSqlQuery();

        return $this->model->run($query, new SomeEntity());
    }
}

更多信息

field()方法

您可以使用数组来分隔数据库、表和字段

field(['database', 'table', 'field'])`

如果您提取单个字段,您必须自己添加逗号

->field('field1')->c()
->field('field2')->c()

您还可以提供一个闭包作为参数

->field(function () { return $value; });

value()方法

使用此方法将参数附加到查询

->value($someValue);
->value(function () { return $someValue; });

fieldlist()方法

此方法功能更强大,请按以下方式使用它

简单的键值使用

fieldlist([
    'field' => 'alias',
    'customer_id' => 'customerId',
    'cus_name' => 'name'
])

指定数据库、表、字段

fieldlist([
    'database:table:field' => 'alias'
]);

混合任何内容

fieldlist([
    'database:table:field' => 'alias',
    'field1', // fetched by real field name
    'field2' => 'alias1'
]);

f(),where(),order(),groupBy()

这四种类型中的任何一种都打开所谓的“大括号”。大括号代表一种完全独立于之前查询的子查询。在解析此子查询的内部,解析器原则上无法访问其他语句。

因此,如果您完成其中之一,只需调用close()或end()来关闭括号

->where()
    ->field('field1')->equals()->value(true)
->close()

The raw()

由于时间有限且为了满足任何要求,我简单地实现了一个raw方法。而且很高兴地看到,这个方法能够使用参数 :D

->raw('SELECT customer_id FROM customer WHERE customer_name LIKE ?', [
    '%github%'
]);

The in()

您可以使用以下两种方法简单地构建IN子句

// option a
->in([1, 2, 3, 4, 5, 6])
// option b
->in()
    ->select()
    ->value(1)
->close()

选项A始终使用预处理语句,数组中的任何值都作为参数传递给数据库。

条件追加

有三种方法提供条件追加

  • _if()
  • _else()
  • _end()

您可以嵌套使用if,并且可以将闭包作为参数推送到if中

->_if($condition === true)
    ->where()
    ->_if(function() { return $condition === true; })
        // ...
    ->_end()
        // ...
    ->close()
->_else()
    //
->_end()

一些其他方法

  • f() - 用于函数
  • where() - 构建WHERE子句
  • any() - 神赐的星星(邪恶的SELECT *
  • value() - 参数
  • null() - SQL中的NULL
  • isNull() - 使用IS NULL比较null
  • join() - 连接表
  • using() - 连接表的using子句
  • on() - 连接表的on子句
  • union() - 创建UNION语句
  • asLong() - 创建while循环
  • each() - 创建each循环