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

Filament Resource Lock Laravel Package

androsamp/filament-resource-lock

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to Enable Locking

  1. Install the package:

    composer require androsamp/filament-resource-lock
    php artisan filament-resource-lock:install
    php artisan migrate
    
    • Publishes config, migrations, and JS assets.
    • Adds resource_lock and resource_lock_audits tables to your database.
  2. Add locking to your model:

    use Androsamp\FilamentResourceLock\Concerns\HasResourceLocks;
    
    class Customer extends Model
    {
        use HasResourceLocks;
    }
    
  3. Enable locking on your EditRecord page:

    use Androsamp\FilamentResourceLock\Concerns\InteractsWithResourceLock;
    
    class EditCustomer extends EditRecord
    {
        use InteractsWithResourceLock;
        protected static string $resource = CustomerResource::class;
    }
    
  4. Display lock status in your table:

    use Androsamp\FilamentResourceLock\Resources\Columns\ResourceLockColumn;
    
    public static function table(Table $table): Table
    {
        return $table->columns([
            ResourceLockColumn::make(),
            // ... other columns
        ]);
    }
    

First Use Case: Basic Locking

  • Open a record in Filament. The lock is automatically acquired.
  • Attempt to open the same record in another tab/browser: the form will be disabled, and a notification will show the current lock owner.
  • No code changes needed beyond the 3 steps above.

Implementation Patterns

Core Workflow: Locking in Action

  1. Lock Acquisition:

    • When a user navigates to an EditRecord page, the package checks for existing locks.
    • If no lock exists, it creates one tied to the current user and record.
    • If a lock exists, the UI disables the form and shows the owner’s details.
  2. Heartbeat vs. Broadcast Modes:

    • Heartbeat (default):
      • Polls the server every ttl_seconds (configurable) to refresh the lock.
      • Simple to set up; works without Laravel Echo.
      • Example config:
        'update_driver' => 'heartbeat',
        'ttl_seconds' => 20, // Lock expires after 20 seconds of inactivity
        
    • Broadcast (real-time):
      • Uses Laravel Echo to push lock updates instantly.
      • Requires broadcasting setup (Pusher, Reverb, etc.).
      • Lower latency; ideal for SPAs with wire:navigate.
      • Example config:
        'update_driver' => 'broadcast',
        'transports' => [
            'broadcast' => [
                'channel_prefix' => 'filament-resource-lock',
                'event' => 'filament-resource-lock',
            ],
        ],
        
  3. Collaboration Actions:

    • Save and Unlock: Allows the lock owner to save changes and release the lock (configurable via permissions).
    • Ask to Unblock: Lets a waiting user request the lock owner to release the lock (also permission-gated).
    • Example permission setup:
      'permission' => [
          'save_and_unlock' => [
              'enabled' => true,
              'permission' => 'filament-resource-lock.save_and_unlock',
          ],
          'ask_to_unblock' => [
              'enabled' => true,
              'permission' => 'filament-resource-lock.ask_to_unblock',
          ],
      ],
      
  4. Audit History Integration:

    • Enable auditing in your EditRecord page:
      use Androsamp\FilamentResourceLock\Concerns\HasResourceAudit;
      
      class EditProduct extends EditRecord
      {
          use InteractsWithResourceLock, HasResourceAudit;
      
          protected function getHeaderActions(): array
          {
              return [
                  $this->getAuditHistoryAction(),
              ];
          }
      }
      
    • Audits are stored in the resource_lock_audits table and grouped by lock_cycle_id.
    • Rollback: Users can selectively restore field values from past versions via the audit UI.
  5. Soft Release Handling:

    • When a user closes a tab or navigates away, the lock enters a "soft release" state.
    • The lock is fully released after release_grace_seconds (default: 3 seconds).
    • Configured via:
      'release_grace_seconds' => 3,
      'stale_soft_release_ignore_seconds' => 5, // Ignore stale soft releases older than 5s
      

Integration Tips

  • Custom Fields in Audit Diffs: Extend the package to support custom fields by implementing HasAuditDiffPreview:

    use Androsamp\FilamentResourceLock\Forms\Concerns\HasAuditDiffPreview;
    
    class MapPicker extends Field
    {
        use HasAuditDiffPreview;
    
        protected function setUp(): void
        {
            $this->auditDiffPreviewUsing(function (mixed $state): string {
                return '<p class="text-sm">' . e($state['lat'] ?? '-') . ', ' . e($state['lng'] ?? '-') . '</p>';
            });
        }
    }
    
  • Storage Backend: Choose between database (default) or redis for lock storage:

    'storage' => [
        'driver' => 'redis', // or 'database'
    ],
    

    Redis is faster for high-concurrency scenarios but requires Redis setup.

  • Localization: Override translations in your resources/lang directory:

    // config/filament-resource-lock.php
    'localization' => [
        'path' => resource_path('lang/vendor/filament-resource-lock'),
    ],
    
  • Testing: Use the LockTestCase trait for unit/integration tests:

    use Androsamp\FilamentResourceLock\Testing\LockTestCase;
    
    class CustomerLockTest extends LockTestCase
    {
        protected function getModel(): string
        {
            return Customer::class;
        }
    }
    

Gotchas and Tips

Pitfalls and Debugging

  1. Lock Expiration Issues:

    • Symptom: Locks expire too quickly or not at all.
    • Cause: Misconfigured ttl_seconds or release_grace_seconds.
    • Fix: Adjust in config/filament-resource-lock.php:
      'ttl_seconds' => 30, // Increase for longer sessions
      'release_grace_seconds' => 5, // Give more time for soft releases
      
  2. Broadcast Mode Failures:

    • Symptom: Lock updates don’t appear in real-time, or Echo events fail silently.
    • Common Causes:
      • Laravel Echo not properly initialized (missing window.Echo in bootstrap.js).
      • Incorrect channel prefix or event name in config.
      • Broadcasting driver not configured (e.g., Pusher credentials missing).
    • Debugging Steps:
      • Check browser console for Echo errors.
      • Verify resources/js/filament-resource-lock/echo.js is published and aligned with your broker.
      • Test with telescope:install to monitor broadcast events.
  3. Audit Data Loss:

    • Symptom: Audit history is missing or incomplete.
    • Cause:
      • Overridden save() method in EditRecord that doesn’t call syncResourceAuditBeforeSave()/syncResourceAuditAfterSave().
      • Audit table not migrated (php artisan migrate).
    • Fix: Ensure your save() method includes audit hooks:
      public function save(bool $shouldRedirect = true): void
      {
          $this->syncResourceAuditBeforeSave();
          parent::save($shouldRedirect);
          $this->syncResourceAuditAfterSave();
      }
      
  4. Permission Denied Errors:

    • Symptom: Users can’t save/unlock or ask to unblock, even with correct permissions.
    • Cause: Permissions not properly configured in config/filament-resource-lock.php or user lacks the policy.
    • Fix:
      • Set permission.enabled to true for the action.
      • Ensure the user has the permission (e.g., filament-resource-lock.save_and_unlock).
  5. Multiple Tabs Issue:

    • Symptom: Opening the same record in two tabs of the same browser causes UniqueConstraintViolationException.
    • Fix: Upgrade to v2.1.2+ (this was fixed in #12).
  6. Soft Release Not Working:

    • Symptom: Locks aren’t released when closing tabs.
    • Cause: The signed filament-resource-lock.release route isn’t reachable (e.g., APP_URL misconfigured).
    • Fix:
      • Ensure APP_URL is correct in .env.
      • Verify the route is registered (check routes/web.php for signed routes).

Configuration Quirks

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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor