slaxweb/ci-basemodel

CodeIgniter 的 BaseModel

0.4.2 2015-03-15 13:35 UTC

README

Build Status

CodeIgniter 的基础模型,帮助您在模型中执行数据库操作。它自动猜测表名,节省您软删除等麻烦。BaseModel 也被BaseController使用。

BaseModel 的想法来自 Jamie Rumbelow 的 基础模型,并进行了一些添加和修改。如果您遇到问题或有疑问/想法,请在此处提交 GitHub 上的工单。

这仍然处于开发阶段,但已准备好投入生产。它只经过 mySQL 测试,当时可能只能与 mySQL 一起工作,尽管已添加了对其他驱动程序的支持,但这是实验性的。

目录

安装

目前安装的最简单方法是使用 composer,或者通过安装版本 0.2+ 的 BaseController,其中将 BaseModel 列为需求。只需在项目根目录中创建 composer.json 文件

{
  "require": {
    "slaxweb/ci-basemodel": "~0.3"
  }
}

然后运行 composer.phar install。完成后,在 application/config/config.php 配置文件中启用 composer 自动加载器。

使用 BaseModel

BaseModel 意味着要由您的模型扩展,因此,您应从 \SlaxWeb\BaseModel\Model 扩展,而不是从 CI_Model 扩展

class Some_model extends \SlaxWeb\BaseModel\Model

有了这些,您的 BaseModel 就可以使用了。

作为替代,您还可以从 MY_Model 扩展,并让 MY_Model 扩展 BaseModel。

属性

BaseModel 提供了您可以设置的下一组属性

  • table - 模型的表,尽管 BaseModel 会自动从其名称中猜测表名。
  • tablePrefix - 表前缀,如果您为每个模型使用特殊的前缀,请在此设置
  • primaryKey - 默认为 "id",如果您使用其他内容作为主键,请在此设置
  • keyType - 键的类型,自增(默认),UUID 键,或您用于生成主键的特定 PHP 或自定义函数
  • keyFunc - 如果您使用一个函数来生成主键,请在此处分配,接受可调用类型
  • keyFuncParams - keyFunc函数使用的参数
  • softDelete - 使用软删除,默认为“硬删除”。有3个选项,软删除状态列,软删除标记列,硬删除
  • deleteCol - 如果使用软删除标记列,请在此处定义它,默认为“deleted”
  • statusCol - 如果使用软删除状态列,请在此处定义该列,默认为“status”
  • deleteStatus - 为状态列设置已删除的状态值,默认为“deleted”
  • rules - 验证规则
  • where - 一个自定义的where字符串
  • whereBinds - 如果使用自定义的where字符串,并且您想将参数绑定到where字符串中,可以将这些参数添加到该属性的数组中

目前BaseModel提供了一个回调函数beforeInit,此回调在BaseModel初始化之前调用。

表名

定义表名有3种方式,首先是在您的模型中定义一个公共属性table,在构造函数中将表名传递给BaseModel __construct 方法,或者让BaseModel尝试并确定您的表名。

猜测表名

在猜测表名时,BaseModel会取您的模型类名,删除_model_m后缀,将剩余部分复数化,并将所有内容转换为小写字母。所以例如User_model变成users

配置常量

BaseModel提供了一个\SlaxWeb\BaseModal\Constants类用于配置软删除和主键类型。要在控制器中使用,最佳方式是在声明模型之前使用该类。

<?php
use \SlaxWeb\BaseModel\Constants as C;

class Test_model extends \SlaxWeb\BaseModel\model
{

}

如果您需要更改软删除设置或主键类型,只需使用这些常量即可

  • DELETEHARD - 硬删除
  • DELETESOFTMARK - 使用删除列标记已删除的行
  • DELETESOFTSTATUS - 使用状态列标记已删除的行
  • PKEYAI - 自增主键
  • PKEYUUID - 由数据库中的UUID()生成的主键
  • PKEYFUNC - 由PHP函数或您的自定义函数生成的主键
  • PKEYNONE - 无主键

数据库操作

插入数据

要插入数据,BaseModel提供了一个insert方法,该方法接受要插入的数据作为数组。

$this->insert(array("column" => "value"));

此方法将首先尝试验证数据,如果您已设置rules属性并且未设置跳过验证。

出错时,方法将返回一个Error对象,或成功时返回true。

获取数据

您可以通过主键、您自己的where参数或获取表中的一切来获取数据。为此,有两种方法,getgetBy。要按主键检索一行,请使用具有主键值作为输入参数的get方法。

// retrieves row with primary key value 123
$this->get(123);

如果您想获取所有内容,只需在get方法中省略主键值。要基于您自己的where语句获取数据,您有两个选项,要么设置BaseModel的where属性,要么将“where”数组传递给getBy方法。

$this->getBy(array("column" => "value"));

此方法还提供了选择特定列的方法。您可以将列数组作为第二个参数传递,或作为字符串传递,就像您在SELECT SQL语句中使用它们一样。

所有get方法都返回Result对象。

更新数据

除了获取数据外,更新也提供了3种方式,按主键更新、按您自己的where语句更新或更新表中的所有内容。这两个方法分别是updateupdateBy。它们的工作方式几乎与获取数据相同,除了您需要提供要更新的数据数组作为第一个参数,以及主键值或您的where语句作为第二个参数。

$this->update(array("column" => "value"), 123);

这将更新名为“column”的列,其中主键值为123。

要使用自己的 WHERE 语句,您需要将其作为数组或与 SQL 语句中使用相同的方式传递给 updateBy 方法。

$this->updateBy(array("column" => "value"), array("whereColumn" => "whereValue"));

更新操作首先会尝试验证数据,如果设置了规则并且您没有标记跳过验证。

发生错误时,方法将返回 错误 对象。

删除数据

对于删除操作,您仍然有两种方法:deletedeleteBy,并且同样,您可以通过主键值、自己的 WHERE 语句或删除所有内容来进行删除。如果您正在使用按状态或已删除列进行删除,此方法将自动为您执行更新,并将行标记为已删除。有关用法示例,请参阅(获取数据),因为用法完全相同,只是方法名称不同。

连接表

BaseModel 还提供了连接表的方式。为此,提供了一个 join 方法,它接受 3 个输入参数。第一个是要连接的表名,第二个是连接条件数组,第三个是连接类型,默认为 INNER。要切换连接类型,Constants 类提供了 3 个常量:JOININNER(默认)、JOINLEFT 用于左连接、JOINRIGHT 用于右连接。

第一个参数是您希望与之连接的表。第二个参数是连接条件数组,必须是嵌套数组,可以选择以下选项

  • leftTable - 条件中的左表,如果未设置,则使用模型表
  • leftColumn - 条件中的左列,不能为空
  • rightTable - 条件中的右表,如果未设置,则使用第一个传入的参数作为表名
  • rightColumn - 条件中的右列,不能为空
  • logicalOperator - 多个 JOIN 条件之间的逻辑运算符,如果未设置,则使用 AND
$this->join(
  "table2",
  array(
    array(
      "leftTable"   =>  "customTable",
      "leftColumn"  =>  "leftCol1",
      "rightTable"  =>  "rightCustomTable",
      "rightColumn" =>  "rightCol1",
    ),
    array(
      "leftColumn"      =>  "leftCol2",
      "rightColumn"     =>  "rightCol2",
      "logicalOperator" =>  "OR"
    )
  )
);

上面的示例将生成:INNER JOIN `table2` ON (`customTable`.`leftCol1` = `rightCustomTable`.`rightCol1` OR `models_table`.`leftCol2` = `table2`.`rightCol2`)

已弃用

以下方法已弃用,应避免使用。

第一个参数是自解释的,只需传递表名。第二个参数必须是一个嵌套数组,可以包含 2 到 3 个项目。第一个项目是连接左表中的列,第二个项目是连接右表中的列。第三个参数是多个连接条件之间的链接,默认为 AND。

$this->join("table2", array(array("column1", "column1"), array("column2", "column2", "OR")));

上面的示例将生成:INNER JOIN `table2` ON (`models_table`.`column1` = `table2`.`column1` OR `models_table`.`column2` = `table2`.`column2`)

在执行了连接查询之后,连接会被重置,如果您想再次使用它,则必须重新进行。

构建 WHERE 语句

BaseModel 提供了一个 WHERE 构建器类,您可以轻松构建自己的 WHERE 语句。

BaseModel 在其自己的属性 wBuild 中提供了此构建器,并且已经初始化,因此您可以立即使用它。要向 WHERE 语句添加表达式,Builder 类提供了一个 add 方法,它接受各种输入参数,其中两个是强制性的。

除了通过 wBuild 属性获取 WHERE 构建器外,您还可以使用 BaseModel 的 where 方法,该方法返回对象本身,因此您也可以将多个 WHERE 表达式链接在一起以及进一步链接到查询中。

已弃用 - BaseModel 提供了一些构建 WHERE 语句的变体,因此您可以构建比正常的 WHERE `column1` = 'value' AND `column2` = 'value' 更复杂的 WHERE 语句。

WHERE 表达式

要将表达式添加到 WHERE 语句中,只需使用列名和值作为输入参数调用 Builder 类的 add 方法。

$this->wBuild->add("columnName", "value");

上面的示例将生成一个简单的 WHERE 语句:`columnName` = ? 并将表达式的值放入 bind 数组中,该数组将在稍后自动绑定到您的查询。

where 方法类似。

$this->where("columnName1", "value")->get();

add 方法返回构建器对象,因此您可以链接方法调用,并且每次后续调用 add 方法都会在表达式之间使用 AND 逻辑运算符。

$this->wBuild->add("columnName1", "value1")->add("columnName2", 10);

上述示例将生成:`columnName1` = ? AND `columnName2` = 10,注意第二个不是 问号,因为它不需要绑定,并且安全地直接将值添加到查询中。

您还可以传递一个数组,构建器将组成一个由逗号分隔的项目列表。如果有多个项目,逗号分隔的列表被括号括起来,如果数组中有多个项目,因此这用于 IN/NOT IN 表达式。

$this->wBuild->add("columnName", array("value1", "value2"), "",  "IN");

上述示例将生成:`columnName` IN (?,?),并且它将再次将值添加到 bind 数组中。您可能也注意到这个示例使用了超过 2 个输入参数,但稍后再讨论。

除了数组之外,您还可以传递一个对象,该对象将被转换为字符串,然后整个字符串被分解为一个数组,逗号用作分隔符,因此可以使用与数组相同的方式组成一个安全列表。这使得您可以使用先前查询的 Result 对象来构建 where 构建器。Result 方法 __toString 将组成所有行中第一列的列表,所以在这个例子中我们假设 $this->get(123),返回 2 行,第一列的值分别为 value1value2

$this->wBuild->add("columnName", $this->get(123), "", "NOT IN");

上述示例将生成 `columnName` IN (?,?),其中 value1value2bind 数组中。

要使用完全定制的 where 语句,您可以将其作为数组传递到 where 方法中,该数组包含作为第一个元素的 where 语句和作为第二个元素的绑定。

$this->where(array("columnName1 = ?", array("value1")))->get();

如果您没有绑定参数,只需将 where 语句字符串作为数组传递即可。

条件运算符

要将条件运算符更改为除默认的 AND 之外的任何运算符,只需将您想要的任何逻辑运算符作为第三个输入参数传递。

比较运算符

要将比较运算符从默认的 = 更改为其他运算符,将其传递到 add 方法作为第四个输入参数。

将列名前缀为表名

在某些情况下,特别是连接查询中,可能需要将某些列名与相应的表名一起预置,这可以通过传递表名作为第五个参数来实现。

$this->wBuild->add("columnName", "value", "", "", "tableName");

上述示例将生成:`tableName`.`columnName` = ?

分组 WHERE 表达式

要分组 where 表达式,您需要告诉 where 构建器从哪里开始分组和在哪里结束分组,您可以通过将第六个参数设置为布尔值 true 来这样做,然后 where 构建器将在那里开始分组,当您想要结束时,传递布尔值 false 作为第六个参数,where 构建器将在该表达式之后关闭分组。

已弃用 - 条件运算符

要替换两个 WHERE 表达式之间的 AND 以其他任何条件运算符,您必须将您想要的条件运算符作为数组键中列名的前缀。

$this->getBy(array("column1" => "value1", "OR column2" => "value2"));

上述示例将生成 WHERE `column1` = 'value1' OR `column2` = 'value2'

注意:目前这仅适用于 OR,正在努力改进。

已弃用 - 比较运算符

通常 BaseModel 在列和值之间使用 equal 比较运算符,但如果您需要任何其他运算符,您可以将它作为后缀添加到 where 数组中的列名中。

$this->getBy(array("column1 <" => 10));

上述示例将生成 WHERE `column1` < 10

已弃用 - 分组 WHERE 表达式

您还可以按需分组表达式集。要这样做,只需在此子数组中添加一个包含进一步 where 表达式的子数组。

$this->getBy(
 array(
  array(
   "groupCol1" => "groupVal1",
   "groupCol2" => "groupVal2"
  ),
  "OR column1" => "value1"
 )
);

上述示例将生成 WHERE (`groupCol1` = 'groupVal1' AND `groupCol2` = 'groupVal2') OR `column1` = 'value1'

SQL 子句

BaseModel 支持一些您可以使用 SQL 子句。

GROUP BY

要将分组子句添加到下一个查询中,使用 groupBy 方法设置它。输入参数必须是一个包含您希望按其分组的列的数组的对象,因此您可以将方法调用链接起来。

ORDER BY

要向查询中添加一个排序子句,请使用 orderBy 方法。它只会在下一个查询中使用。第一个参数必须是一个数组,且必须包含列名。第二个参数是排序方向,默认为 "升序"。该方法返回模型对象,因此您可以链接方法调用。

要在 ORDER BY 语句中使用多个排序方向,请将列名作为第一个参数的数组键,并将每个列的方向作为数组值,省略第二个参数。例如:

$this->orderBy(
  array(
    "col1" => "ASC",
    "col2  => "DESC"
  )
);

上述示例将产生 ORDER BY col1 ASC, col2 DESC

LIMIT

要添加下一个查询的限制子句,请使用 limit 方法。它接受两个整数参数,第一个参数是要受查询影响的行数限制,第二个参数(默认为 int(0))是偏移量,表示从哪一行开始计数。

验证

BaseModel 在插入或更新时会自动验证您的数据,只要您在 rules 属性中提供验证规则即可。规则必须符合 CodeIgniter 表单验证。

$this->rules = array(
    array(
        "field" =>  "fieldName",
        "label" =>  "Field label",
        "rules" =>  "required|max_length[100]"
    )
);
$this->insert(array("fieldName" => "fieldValue"));

手动运行验证

您还可以使用 validate 方法手动运行验证。同样,您需要在 rules 属性中设置规则。

$this->rules = array(
    array(
        "field" =>  "fieldName",
        "label" =>  "Field label",
        "rules" =>  "required|max_length[100]"
    )
);
$this->validate(array("fieldName" => "fieldValue"));

跳过验证

要跳过验证,您可以将规则设置为空数组,或者在调用插入或更新方法之前调用 skipValidation 方法,这将跳过下一个查询的验证。skipValidation 会返回模型对象,因此您可以在其后链接查询。

$this->skipValidation()->insert($data);

对软删除行的查询

如果您想在软删除的行上运行更新/获取查询,请在执行查询之前调用 withDeleted 方法,或者使用自定义的 WHERE 字符串。 withDeleted 会使更新或选择查询的下一个查询仅包括已删除的行。它也返回模型对象,因此您可以链接查询。

$this->withDeleted()->get();

结果

选择查询将返回一个 Result 对象,您可以通过该对象访问数据,并遍历行。

获取列数据

要获取数据,只需访问 Result 对象的属性,并使用列名作为属性名。

$result = $this->getBy(array("whereColumn" => "whereValue"), "column");
$result->column;

如果结果是多行,则用于数据检索的是第一行。如果列不存在,则返回 null

获取数组

要获取所有列作为数组,只需调用 asArray 方法,这将返回当前行作为数组。

$result->asArray();

行数

要获取行数,只需调用 rowCount 方法。

获取所有行

要一次性获取所有行,调用 getResult 方法。

遍历行

要遍历行,Result 类提供了 3 个方法

  • next - 移动到下一行
  • prev - 移动到上一行
  • row - 移动到输入参数中指定的行

这三种方法都返回对象本身,或者如果下一行、上一行或指定的行不存在,则返回 false。

错误

Error 类提供了一种更简单的错误处理方式,并允许您轻松地为特定错误分配错误消息。

Error 类的初始化

为了成功分配错误消息,必须在构造时将语言数组传递给 Error 对象。BaseModel 在一些发生错误的方法中为您执行此操作,如果您需要在您自己的方法中自行执行此操作,最佳和最简单的方法是提供 CodeIgniter 语言数组 ($this->lang->language)。

添加错误

要添加一个错误,您必须提供一个错误代码,作为可选参数,您可以提供一个整数严重级别和附加错误数据数组。添加时,Error 类会根据严重性自动排序错误。此外,它会在提供的语言数组中查找相应的错误消息。消息的键必须是 "error_your_error_code",全部为小写字母。

有错误和错误计数

要检查是否存在错误,请使用 hasErrors 方法,要检查错误数量,请使用 errorCount 方法。

$error->hasErrors();
$error->errorCount();

获取错误

您可以使用 getErrors 方法一次性获取所有错误,或者使用 get 方法获取当前错误。您还可以使用 errorAt 获取特定索引处的错误,或者使用 error 方法获取包含您作为输入参数提供的代码的错误。

遍历错误

与 Result 类相同,Error 类提供了 prevnext 方法,如果没有前一个或下一个错误,则返回 false,或者返回自身以进行方法链接,但它不提供类似 row 的方法,除了 errorAt,它已经返回了提供的索引处的错误。

谢谢!

我要感谢所有为此项目做出贡献的人,无论是通过想法、测试、文档校对等。

变更日志

0.4.2

  • 没有功能更改,新增测试和版本升级

0.4.1

  • 正确处理查询中的布尔值
  • 正确处理 WHERE 表达式构建器中的布尔值

0.4.0

  • 自动尝试猜测表的主键列

0.3.6

  • 始终在括号中包装绑定的列表,即使列表中只有一个值
  • 修复 README 中的小错误

0.3.5

  • 在验证之前重置表单验证

0.3.4

  • 手动设置表单验证数据

0.3.3

  • ORDER BY 语句中的多重排序方向
  • 非 MySQL 数据库的正确 LIMIT 语法

0.3.2

  • 修复无法指定特定表进行 JOIN 语句的问题

0.3.1

  • 修复自定义 WHERE 字符串解析错误

0.3.0

  • 添加 Error 类
  • 添加验证
  • 添加主键类型
  • 添加 GROUP BY、ORDER BY 和 LIMIT 子句
  • 添加 WHERE 语句构建器
  • 添加 JOIN 语句
  • 添加除 mysql(i) 以外的其他数据库驱动程序功能 - 实验!

0.2.5

  • 在查询之间重置 WHERE 数组

0.2.4

  • 如果没有 WHERE 语句,从查询中删除 WHERE 关键字

0.2.3

  • 错误地删除了 WHERE 语句

0.2.2

  • 给列名添加反引号

0.2.1

  • 从绑定的占位符中删除引号

0.2.0

  • 添加插入方法
  • 将参数绑定到更新语句

0.1.0

  • 初始版本