定制 richardhulbert/revisions-model 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

richardhulbert/revisions-model

Composer 安装命令:

composer require richardhulbert/revisions-model

包简介

Append-only, branch-aware revision models for Laravel Eloquent. Records are never updated in place - every change is a new row, so history is permanent and any revision can be rolled back.

README 文档

README

Append-only, branch-aware revision models for Eloquent. A record is never updated in place: update() clones the row with the new values, so every change stacks up as a new revision and any change can be permanently rolled back.

The pattern

Every table using this pattern has three extra columns:

Column Meaning
prime The id of the first record in the chain. All revisions share it.
branch_id The branch the revision was made on. Branch 1 is public/published by default.
user_id The user who made the revision.

A "record" as the rest of your app sees it is identified by its prime; the individual rows are its revisions. The newest row per branch is the current state of that record on that branch.

Installation

composer require richardhulbert/revisions-model

The service provider is auto-discovered. Publish the config if you need to change any defaults:

php artisan vendor:publish --tag=revisions-config
// config/revisions.php
return [
    'branch_model'          => \App\Models\Branch::class, // your branch model
    'user_model'            => null,      // null = default auth provider model
    'public_branch_id'      => 1,         // the published/public branch
    'user_branch_attribute' => 'branch',  // attribute on the user holding their current branch id
    'default_user_id'       => 1,         // author recorded when nobody is logged in
];

Migrations

A revisions() Blueprint macro adds the three columns:

Schema::create('pages', function (Blueprint $table) {
    $table->id();
    $table->revisions();          // prime, user_id, branch_id
    $table->string('title');
    // ...
    $table->softDeletes();
    $table->timestamps();
});

Usage

Extend RevisionsModel instead of Model. The revision columns are merged into $fillable automatically — no constructor boilerplate needed:

use RichardHulbert\Revisions\RevisionsModel;

class Page extends RevisionsModel
{
    protected $fillable = ['title', 'slug', 'blocks'];
}

Creating and updating

$page = Page::new(['title' => 'Home']);       // starts a chain: prime = id

$draft = $page->update(['title' => 'Home!']); // NEW row on the user's branch
$live  = $page->update(['title' => 'Home!', 'branch_id' => 1]); // explicit branch

update() returns the new revision; the row you called it on is untouched. branch_id defaults to the logged-in user's branch, user_id to the logged-in user.

Reading

$page->lastRevision()->first();          // user's branch if it has revisions, else public
$page->lastRevisionWithBranch(3)->first();
$page->lastPublicRevision()->first();

$page->revisions();      // history: latest revision per branch per day
$page->revisions(3);     // history on one branch

Page::allLatest()->get();   // newest revision of every record (public branch)
Page::allLatest(3)->get();  // ... on branch 3

Relations

$revision->prime;    // the first record of the chain
$revision->branch;   // the branch (even if soft-deleted)
$revision->owner;    // the author (even if soft-deleted)

To point at another revisioned model, store its prime in a column and use hasOneRevision() — an eager-loadable hasOne that resolves to the latest revision on a branch:

class Page extends RevisionsModel
{
    public function templateOnBranch(): HasOne
    {
        return $this->hasOneRevision(Template::class, 'template_id');      // user's branch
    }

    public function templatePublic(): HasOne
    {
        return $this->hasOneRevision(Template::class, 'template_id', 1);   // public branch
    }
}

Page::with('templateOnBranch')->get();  // works with with()/load()

Deleting

Deleting any revision deletes the prime record of the chain (with soft deletes, this marks the whole record as deleted without losing history):

$revision->delete();

Testing

composer install
composer test

License

MIT — see LICENSE.md.

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-07

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固