Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Eloquent Approval Laravel Package

mtvs/eloquent-approval

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require mtvs/eloquent-approval
    

    Publish the migration and config:

    php artisan vendor:publish --provider="Mtvs\EloquentApproval\EloquentApprovalServiceProvider"
    php artisan migrate
    
  2. Apply to a Model: Use the Approvable trait in your Eloquent model:

    use Mtvs\EloquentApproval\Traits\Approvable;
    
    class Post extends Model
    {
        use Approvable;
    }
    

    This adds status (pending/approved/rejected/suspended) and approved_at fields.

  3. First Use Case: Create a new record—it defaults to pending:

    $post = Post::create(['title' => 'Draft Post']);
    // $post->status === 'pending'
    

Implementation Patterns

Core Workflows

  1. Approval States:

    • Pending: New records or after updates to approved attributes.
    • Approved: Manually approved via:
      $post->approve(); // Sets status to 'approved', updates `approved_at`
      
    • Rejected: Manually rejected:
      $post->reject(); // Sets status to 'rejected'
      
    • Suspended: Automatically triggered on updates to approved attributes (configurable via approvedAttributes).
  2. Query Scoping:

    • Default scope filters out pending/rejected records. Override with:
      Post::withStatus('pending')->get(); // Explicitly include non-approved
      Post::withoutStatusScope()->get();  // Disable scope entirely
      
  3. Mass Actions:

    • Approve/reject multiple records:
      Post::where('user_id', 1)->approve();
      Post::where('title', 'like', '%draft%')->reject();
      
  4. Event Listeners:

    • Listen for status changes:
      Post::approved(function ($post) {
          // Send notification, etc.
      });
      

Integration Tips

  • Custom Attributes: Configure approvedAttributes in your model to auto-suspend on updates:
    protected $approvedAttributes = ['title', 'content'];
    
  • Soft Deletes: Works seamlessly with SoftDeletes trait. Use withTrashed() to include deleted records in queries.
  • API Responses: Filter responses in API controllers:
    return Post::approved()->get(['title', 'approved_at']);
    

Gotchas and Tips

Pitfalls

  1. Default Scope Overrides:

    • Forgetting to use withoutStatusScope() when querying pending/rejected records.
    • Fix: Always explicitly specify status if deviating from default behavior.
  2. Auto-Suspend on Updates:

    • Updates to approvedAttributes trigger suspended state, even if no changes were made to those fields.
    • Fix: Manually check for changes before updating:
      if ($post->isDirty('title')) {
          $post->update(['title' => 'New Title']);
      }
      
  3. Race Conditions:

    • Concurrent approval/rejection actions may cause inconsistencies.
    • Fix: Use database transactions:
      DB::transaction(function () use ($post) {
          $post->approve();
          // Other related updates
      });
      
  4. Model Caching:

    • Cached models may not reflect status changes. Use fresh() to reload:
      $post->approve();
      $post = $post->fresh(); // Ensure latest status
      

Debugging

  • Check Status:
    dd($post->status); // 'pending'|'approved'|'rejected'|'suspended'
    
  • Log Queries: Enable Laravel query logging to debug scope issues:
    DB::enableQueryLog();
    Post::all();
    dd(DB::getQueryLog());
    

Extension Points

  1. Custom Statuses: Extend the status field by overriding the getStatusAttribute method:

    public function getStatusAttribute($value) {
        return $value === 'pending' ? 'under_review' : $value;
    }
    
  2. Custom Approval Logic: Override approve()/reject() methods to add pre/post actions:

    public function approve() {
        $this->fireModelEvent('approving');
        parent::approve();
        $this->fireModelEvent('approved');
    }
    
  3. Global Config: Override default settings in config/eloquent-approval.php:

    'default_status' => 'pending',
    'approved_attributes' => ['title', 'content'],
    
  4. Policy Integration: Use Laravel Policies to restrict who can approve/reject:

    public function approve(Post $post) {
        return $this->user()->isAdmin();
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle