定制 mtvs/eloquent-approval 二次开发

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

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

mtvs/eloquent-approval

Composer 安装命令:

composer require mtvs/eloquent-approval

包简介

Approval process for Laravel Eloquent models.

README 文档

README

Build Status

Eloquent Approval

Approval process for Laravel's Eloquent models.

eloquent-approval-preview

Why we need content approval in our apps

Unless you're comfortable with unacceptable content, spam and any other violations that may appear in what the users post, you need to include some sort of content approval in your app.

Why approval process with three states

Although it's possible to approve a model by using a boolean field but a field that has three possible values: pending, approved and rejected gives us more power. It differentiates between the models waiting for the decision and the rejected ones and also makes it clear for the user if their content gets rejected.

How it works

After the setup, when new entities are being created, they are marked as pending. Then their status can be changed to approved or rejected.

Also, when an update occurs that modifies attributes that require approval the entity becomes suspended again.

By default the approval scope is applied on every query and filters out the pending and rejected entities, so only approved entities are included. You can include the entities that aren't approved by explicitly specifying it.

Install

$ composer require mtvs/eloquent-approval

Setup

Registering the service provider

By default the service provider is registered automatically by Laravel package discovery otherwise you need to register it in your config\app.php

Mtvs\EloquentApproval\ApprovalServiceProvider::class

Database

The following method adds two columns to the schema, one to store the approval status named approval_status and another to store the timestamp at which the last status update is occurred named approval_at.

$table->approvals()

You can change the default column names but then you need to specify them on the model too.

Model

Add Approvable trait to the model

use Illuminate\Database\Eloquent\Model;
use Mtvs\EloquentApproval\Approvable;

class Entity extends Model
{
    use Approvable;
}

If you want to change the default column names you need to specify them by adding class constants to your model

use Illuminate\Database\Eloquent\Model;
use Mtvs\EloquentApproval\Approvable;

class Entity extends Model
{
    use Approvable;
    
    const APPROVAL_STATUS = 'custom_approval_status';
    const APPROVAL_AT = 'custom_approval_at';
}

Add approval_at to the model $dates list to get Carbon instances when accessing it.

Approval Required Attributes

When an update occurs that modifies attributes that require approval, the entity becomes suspended again.

$entity->update($attributes); // an update with approval required modification

$entity->isPending(); // true

Note that this happens only when you perform the update on Model object itself not by using a query Builder instance.

By default all attributes require approval.

/**
 * @return array
 */
public function approvalRequired()
{
    return ['*'];
}

/**
 * @return array
 */
public function approvalNotRequired()
{
    return [];
}

You can override them to have a custom set of approval required attributes.

They work like $fillable and $guarded in the Eloquent. approvalRequired() returns the black list while approvalNotRequired() returns the white list.

Usage

Newly created entities are marked as pending and by default excluded from queries on the model.

Entity::create(); // #1 pending

Entity::all(); // []

Entity::find(1); // null

Including all the entities

Entity::anyApprovalStatus()->get(); // retrieving all

Entity::anyApprovalStatus()->find(1); // retrieving one

Entity::anyApprovalStatus()->delete(); // deleting all

If you want to disable the approval scope totally on every query, you can set the approvalScopeDisabled on the model.

use Illuminate\Database\Eloquent\Model;
use Mtvs\EloquentApproval\Approvable;

class Entity extends Model
{
    use Approvable;
    
    public $approvalScopeDisabled = true;
}

Limiting to only a specific status

Entity::onlyPending()->get(); // retrieving only pending entities
Entity::onlyRejected()->get(); // retrieving only rejected entities
Entity::onlyApproved()->get(); // retrieving only approved entities

Updating the status

On model objects

You can update the status of an entity by using provided methods on the Model object.

$entity->approve(); // returns bool if the entity exists otherwise null  
$entity->reject(); // returns bool if the entity exists otherwise null  
$entity->suspend(); // returns bool if the entity exists otherwise null  

On Builder objects

You can update the status of more than one entity by using provided methods on Builder objects.

Entity::whereIn('id', $updateIds)->approve(); // returns number of updated
Entity::whereIn('id', $updateIds)->reject(); // returns number of updated
Entity::whereIn('id', $updateIds)->suspend(); // returns number of updated

Approval Timestamp

When you change the approval status of an entity its approval_at column updates. Before the first approval action on an entity itsapproval_at is null.

Check the status of an entity

You can check the status of an entity using provided methods on Model objects.

$entity->isApproved(); // returns bool if entity exists otherwise null
$entity->isRejected(); // returns bool if entity exists otherwise null
$entity->isPending(); // returns bool if entity exists otherwise null

Approval Events

There are some model events that are dispatched before and after each approval action.

Action Before After
approve approving approved
suspend suspending suspended
reject rejecting rejected

Also, there is a general event named approvalChanged that is dispatched whenever the approval status is changed regardless of the actual status.

You can hook to them by calling the provided static methods, which are named after them, and passing your callbacks. Or by registring observers with methods with the same names.

use Illuminate\Database\Eloquent\Model;
use Mtvs\EloquentApproval\Approvable;

class Entity extends Model
{
    use Approvable;
    
    protected static function boot()
    {
        parent::boot();
        
        static::approving(function ($entity) {
            // You can halt the process by returning false
        });
        
        static::approved(function ($entity) {
            // $entity has been approved
        });

        // or:

        static::observe(ApprovalObserver::class);
    }
}

class ApprovalObserver
{
    public function approving($entity)
    {
        // You can halt the process by returning false
    }

    public function approved($entity)
    {
        // $entity has been approved
    }
}

Eloquent model events can also be mapped to your application event classes.

Duplicate Approvals

Trying to set the approval status to the current value is ignored, i.e.: no event will be dispatched and the approval timestamp won't be updated. In this case the approval method returns false.

The Model Factory

Import the ApprovalFactoryStates to be able to use the approval states when using the model factory.

    namespace Database\Factories;

    use Illuminate\Database\Eloquent\Factories\Factory;
    use Mtvs\EloquentApproval\ApprovalFactoryStates;

    class EntityFactory extends Factory
    {
        use ApprovalFactoryStates;

        public function definition()
        {
            //
        }
    }
    Entity::factory()->approved()->create();
    Entity::factory()->rejected()->create();
    Entity::factory()->suspended()->create();

Handling Approval HTTP Requests

You can import the HandlesApproval in a controller to perform the approval operations on a model. It contains an abstract method which has to be implemented to return the model's class name.

    namespace App\Http\Controllers\Admin;

    use App\Http\Controllers\Controller;
    use App\Models\Entity;
    use Mtvs\EloquentApproval\HandlesApproval;

    class EntitiesController extends Controller
    {
        use HandlesApproval;

        protected function model()
        {
            return Entity::class;
        }
    }

The trait's performApproval() does the approval and the request should be routed to this method. It has the key and request parameters which are passed to it by the router.

When do the routing, don't forget to apply the auth and can middlewares for authentication and authourization.

    Route::post(
        'admin/enitiy/{key}/approval', 
        'Admin\EntitiesController@performApproval'
    )->middleware(['auth', 'can:perform-approval'])

The request must have a approval_status key with one of the possible values: approved, pending, rejected.

Frontend Components

There are also some UI components here written for Vue.js and Bootstrap that you can use. First install them using the approval:ui artisan command and then register them in your app.js file.

Approval Buttons Component

Call <approval-buttons> and pass the current-status and the approval-url props to be able to make HTTP requests to set the approval status.

It emits the approval-changed event when an approval action happens. The payload of the event is an object with the new approval_status and approval_at values. Use the event to modify the corresponding keys on the entity that in turn should change the current-status prop on the following cycle.

Approval Status Component

Call <approval-status> and pass the value prop to show the current status.

Inspirations

When I was searching for an existing package for approval functionality on eloquent models I encountered hootlex/laravel-moderation even though I decided to write my own package I got some helpful inspirations from that one.

I also wrote different parts of the code following the way that similar parts of Eloquent itself is written.

mtvs/eloquent-approval 适用场景与选型建议

mtvs/eloquent-approval 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 21.75k 次下载、GitHub Stars 达 147, 最近一次更新时间为 2017 年 12 月 03 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「eloquent」 「approval」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 mtvs/eloquent-approval 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 mtvs/eloquent-approval 我们能提供哪些服务?
定制开发 / 二次开发

基于 mtvs/eloquent-approval 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

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

GitHub 信息

  • Stars: 147
  • Watchers: 2
  • Forks: 12
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2017-12-03