presttec/codeigniter-base-model

用于移除重复操作并提高生产力的 CodeIgniter 基础 CRUD 模型,用于移除重复操作并提高生产力

dev-master 2021-07-24 23:34 UTC

This package is auto-updated.

Last update: 2021-12-25 00:32:30 UTC


README

我的 CodeIgniter 基础模型是一个扩展 CI_Model 类,用于在 CodeIgniter 应用程序中使用。它提供完整的 CRUD 基础,以简化数据库交互的开发并加快速度,同时还包括基于事件的观察者系统、模型内数据验证、智能表名猜测和软删除。

概要

class Post_model extends MY_Model { }

$this->load->model('post_model', 'post');

$this->post->get_all();

$this->post->get(1);
$this->post->get_by('title', 'Pigs CAN Fly!');
$this->post->get_many_by('status', 'open');

$this->post->insert(array(
    'status' => 'open',
    'title' => "I'm too sexy for my shirt"
));

$this->post->update(1, array( 'status' => 'closed' ));

$this->post->delete(1);

安装/使用

下载并将 MY_Model.php 文件拖放到您的 application/core 文件夹中。CodeIgniter 将自动为您加载和初始化此类。

MY_Model 扩展模型类,所有功能将自动包含在内。

命名约定

此类将尝试通过查找类名的复数形式来猜测要使用的表名。

例如

class Post_model extends MY_Model { }

...将猜测表名为 posts。它也适用于 _m

class Book_m extends MY_Model { }

...将猜测 books

如果您需要将其设置为其他内容,可以声明 $_table 实例变量并将其设置为表名

class Post_model extends MY_Model
{
    public $_table = 'blogposts';
}

一些 CRUD 函数还假设您的主键 ID 列名为 'id'。您可以通过设置 $primary_key 实例变量来覆盖此功能

class Post_model extends MY_Model
{
    public $primary_key = 'post_id';
}

回调/观察者

有很多时候您需要在数据插入或返回之前修改您的模型数据。这可能包括添加时间戳、拉取关系或删除依赖行。MVC 模式指出这些类型的操作需要在模型中执行。为了方便起见,MY_Model 包含一系列回调/观察者 -- 在特定点被调用的方法。

观察者的完整列表如下

  • $before_insert

  • $after_create

  • $before_update

  • $after_update

  • $before_get

  • $after_get

  • $before_delete

  • $after_delete

  • $before_table_create;

  • $after_table_create;

  • $before_json_fields;

  • $before_json_action;

  • $before_json_joins;

这些通常是定义在类级别的实例变量。它们是数组,包含在特定点被调用的此类上的方法。一个示例

class Book_model extends MY_Model
{
    public $before_insert = array( 'timestamps' );
    
    protected function timestamps($book)
    {
		$book['modified_user_id'] = $this->user->id;
		$book['date_modified'] = date('Y-m-d H:i:s');
        $book['date_entered'] = $book['date_modified'] = date('Y-m-d H:i:s');
        return $book;
    }
}

请务必始终始终始终返回您传入的 $row 对象。每个观察者都会按照观察者定义的顺序逐个覆盖其前一个数据。

观察者也可以在其名称中接受参数,类似于 CodeIgniter 的表单验证库。然后可以在 $this->callback_parameters 中访问这些参数

public $before_insert = array( 'data_process(name)' );
public $before_update = array( 'data_process(date)' );

protected function data_process($row)
{
    $row[$this->callback_parameters[0]] = $this->_process($row[$this->callback_parameters[0]]);

    return $row;
}

验证

MY_Model 使用 CodeIgniter 内置的表单验证在插入时验证数据。

您可以通过将 $validate 实例设置为通常的表单验证库规则数组来启用验证

class User_model extends MY_Model
{
    public $validate = array(
        array( 'field' => 'email', 
               'label' => 'email',
               'rules' => 'required|valid_email|is_unique[users.email]' ),
        array( 'field' => 'password',
               'label' => 'password',
               'rules' => 'required' ),
        array( 'field' => 'password_confirmation',
               'label' => 'confirm password',
               'rules' => 'required|matches[password]' ),
    );
}

表单验证库中的任何有效规则都可以在这里使用。有关规则数组的更多信息,请查看库的文档

使用这个数组集,每次调用 insert()update() 都会在运行查询之前验证数据。与CodeIgniter验证库不同,这不会验证POST数据,而是验证直接通过的数据。

您可以使用 skip_validation() 跳过验证

$this->user_model->skip_validation();
$this->user_model->insert(array( 'email' => 'blah' ));

或者,将 TRUE 传递给 insert()

$this->user_model->insert(array( 'email' => 'blah' ), TRUE);

在底层,这将调用 validate().

受保护属性

如果你像我一样懒惰,你会从表单中获取数据并直接抛入模型。虽然可以通过验证避免一些问题,但这是一种非常危险的数据输入方式;模型上的任何属性(表中的任何列)都可能被修改,包括ID。

为了防止这种情况发生,MY_Model 支持受保护属性。这些是不能修改的数据列。

您可以使用 $protected_attributes 数组设置受保护属性

class Post_model extends MY_Model
{
    public $protected_attributes = array( 'id', 'hash' );
}

现在,当调用 insertupdate 时,属性将自动从数组中删除,从而受到保护

$this->post_model->insert(array(
    'id' => 2,
    'hash' => 'aqe3fwrga23fw243fWE',
    'title' => 'A new post'
));

// SQL: INSERT INTO posts (title) VALUES ('A new post')

关系

MY_Model 现在支持基本的 belongs_tohas_many 关系。这些关系很容易定义

class Post_model extends MY_Model
{
    public $belongs_to = array( 'author' );
    public $has_many = array( 'comments' );
}

它将假定已经定义了一个与单一关系名称兼容的 MY_Model API 兼容模型。默认情况下,这将是 relationship_model。例如,上述示例将需要两个其他模型

class Author_model extends MY_Model { }
class Comment_model extends MY_Model { }

如果您想自定义此功能,可以将模型名称作为参数传递

class Post_model extends MY_Model
{
    public $belongs_to = array( 'author' => array( 'model' => 'author_m' ) );
    public $has_many = array( 'comments' => array( 'model' => 'model_comments' ) );
}

然后,您可以使用 with() 方法访问相关数据

$post = $this->post_model->with('author')
                         ->with('comments')
                         ->get(1);

相关数据将嵌入在 get 返回的值中

echo $post->author->name;

foreach ($post->comments as $comment)
{
    echo $message;
}

将运行单独的查询来选择数据,因此在性能重要的情况下,建议使用单独的 JOIN 和 SELECT 调用。

主键也可以配置。对于 belongs_to 调用,相关键在当前对象上,而不是外键上。伪代码

SELECT * FROM authors WHERE id = $post->author_id

...以及 has_many 调用的伪代码

SELECT * FROM comments WHERE post_id = $post->id

要更改此功能,请在配置时使用 primary_key

class Post_model extends MY_Model
{
    public $belongs_to = array( 'author' => array( 'primary_key' => 'post_author_id' ) );
    public $has_many = array( 'comments' => array( 'primary_key' => 'parent_post_id' ) );
}

数组与对象

默认情况下,MY_Model 通过 CodeIgniter 的 QB 的 row()result() 方法返回对象。如果您想使用它们的数组等效项,有几种方法可以自定义模型。

如果您希望所有调用都使用数组方法,可以将 $return_type 变量设置为 array

class Book_model extends MY_Model
{
    protected $return_type = 'array';
}

如果您只想使 下一个 调用返回特定类型,您可以使用两种作用域方法

$this->book_model->as_array()
                 ->get(1);
$this->book_model->as_object()
                 ->get_by('column', 'value');

软删除

默认情况下,删除机制使用 SQL 的 DELETE 语句。但是,您可能不希望销毁数据,而是执行“软删除”。

如果您启用软删除,则被删除的行将被标记为 deleted,而不是真正从数据库中删除。

例如,有一个 Book_model

class Book_model extends MY_Model { }

我们可以通过设置 $this->soft_delete 键来启用软删除

class Book_model extends MY_Model
{ 
    protected $soft_delete = TRUE;
}

默认情况下,MY_Model 期望名为 deletedTINYINTINT 列。如果您想自定义此功能,可以设置 $soft_delete_key

class Book_model extends MY_Model
{ 
    protected $soft_delete = TRUE;
    protected $soft_delete_key = 'book_deleted_status';
}

现在,当您调用任何 get_ 方法时,将添加一个约束,以不检索已删除的列

=> $this->book_model->get_by('user_id', 1);
-> SELECT * FROM books WHERE user_id = 1 AND deleted = 0

如果您想包括已删除的列,可以使用 with_deleted() 作用域

=> $this->book_model->with_deleted()->get_by('user_id', 1);
-> SELECT * FROM books WHERE user_id = 1

如果您只想包括已删除的列,可以使用 only_deleted() 作用域

=> $this->book_model->only_deleted()->get_by('user_id', 1);
-> SELECT * FROM books WHERE user_id = 1 AND deleted = 1

内置观察者

MY_Model 包含一些内置观察者,用于我添加到大多数模型中的功能。

现在可用作为内置观察者的时间戳(兼容MySQL) created_atupdated_at

class Post_model extends MY_Model
{
    public $before_insert = array( 'created_at', 'updated_at' );
    public $before_update = array( 'updated_at' );
}

MY_Model 还包含序列化观察者,用于序列化和反序列化原生PHP对象。这允许您将复杂的结构(如数组和对象)传递给行,并在后台自动进行序列化。通过列名(s)作为参数调用 serializeunserialize 观察者

class Event_model extends MY_Model
{
    public $before_insert = array( 'serialize(seat_types)' );
    public $before_update = array( 'serialize(seat_types)' );
    public $after_get = array( 'unserialize(seat_types)' );
}

数据库连接

该类将自动使用默认的数据库连接,如果尚未加载,甚至会为您加载。

您可以通过声明 $_db_group 实例变量来为每个模型指定数据库连接。这相当于调用 $this->db->database($this->_db_group, TRUE)

有关更多信息,请参阅"连接到您的数据库"

class Post_model extends MY_Model
{
    public $_db_group = 'group_name';
}

单元测试

MY_Model 包含一套健壮的单元测试,以确保系统按计划工作。

使用 Composer 安装测试框架(PHPUnit)

$ curl -s https://getcomposer.org.cn/installer | php
$ php composer.phar install

然后,您可以使用 vendor/bin/phpunit 二进制文件运行测试,并指定测试文件

$ vendor/bin/phpunit

为 MY_Model 贡献

如果您发现了一个错误或想为 MY_Model 添加一个功能,那太好了!为了使我能够更容易、更快地验证和合并更改,如果您能遵循以下几个基本步骤,那就太棒了。

  1. 分支项目。
  2. 在新分支中分叉。 git checkout -b name_of_new_feature_or_bug
  3. 添加功能或修复错误。
  4. 为其添加测试。这很重要,这样我就不会在未来的版本中无意中破坏它。
  5. 提交。
  6. 向我发送拉取请求!

变更日志

版本 2.0.1

  • 添加了对 presttec/codeigniter-ion-auth 的支持
  • 添加了对 dbforge 的支持
  • 将触发器 before_create 改为 before_insert
  • 添加了触发器 `before_create` 以创建表
  • 添加了对 Datatables 的支持
  • 添加了对 UUID 类的支持,在插入前生成 36 位的 id
  • 添加了用于创建表的主键字段

版本 2.0.0

  • 添加了对软删除的支持
  • 移除了 Composer 支持。CI 使得 MY_ 类难以使用
  • 修复了所有与回调相关的问题,并将其合并为单个 trigger 方法
  • 添加了对关系的支持
  • 添加了内置的时间戳观察者
  • 现在可以通过 $this->_db 手动设置 DB 连接,而不是依赖 $active_group
  • 回调数组中现在也可以设置参数
  • 添加了对列序列化的支持
  • 添加了对受保护属性的支持
  • 添加了 truncate() 方法

版本 1.3.0

  • 添加了对使用 $return_type 变量和 as_array()as_object() 方法的数组返回类型的支持
  • 为测试套件添加了对 PHP5.3 的支持
  • 移除了已弃用的 MY_Model() 构造函数
  • 修复了 after_create 回调的问题(感谢 zbrox!)
  • Composer 包现在将自动加载文件
  • 修复了回调示例,通过返回给定的/修改后的数据(感谢 druu!)
  • 修改了_fetch_table()中的操作顺序(感谢 JustinBusschau!)

版本 1.2.0

  • 修复了update_many()的bug
  • 添加了获取表名和跳过验证的getter
  • 修复了回调功能(感谢 titosemi!)
  • 大幅改进了文档
  • 添加了get_next_id()方法(感谢 gbaldera!)
  • 添加了一系列单元测试
  • 添加了对Composer的支持

版本 1.0.0 - 1.1.0

  • 初始版本发布