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

Laravel Patches Laravel Package

aaix/laravel-patches

Laravel Patches adds a simple, command-based patching system for Laravel. Create one-off Artisan commands for data fixes and deployments, run them manually, and track executions in the database to prevent reruns. Delete patches when done.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require aaix/laravel-patches
    php artisan vendor:publish --provider="Aaix\LaravelPatches\LaravelPatchesServiceProvider" --tag="config"
    
    • Publishes the default config (config/patches.php) and migration (database/migrations/..._create_patches_table.php).
  2. Run Migration

    php artisan migrate
    
    • Creates the patches table to track patch metadata.
  3. First Patch

    php artisan patch:create my_first_patch --description="Fixes critical bug in user auth"
    
    • Generates a patch file at database/patches/my_first_patch.php with a skeleton:
      <?php
      return function () {
          // Your patch logic here
      };
      
    • Registers the patch in the database.
  4. Apply the Patch

    php artisan patch:apply my_first_patch
    
    • Executes the patch logic and marks it as applied.

First Use Case: Hotfix Deployment

  • Scenario: Deploy a quick fix to production without a full release.
  • Workflow:
    1. Create a patch:
      php artisan patch:create hotfix_user_permissions --description="Grant admin access to inactive users"
      
    2. Edit database/patches/hotfix_user_permissions.php:
      return function () {
          DB::table('users')->where('is_admin', false)->update(['is_admin' => true]);
      };
      
    3. Apply in staging first:
      php artisan patch:apply hotfix_user_permissions
      
    4. Test thoroughly, then apply to production via:
      php artisan patch:apply hotfix_user_permissions --env=production
      

Implementation Patterns

Patch Lifecycle Management

  1. Creation

    • Use patch:create for ad-hoc fixes or feature toggles.
    • Example: Schema migrations, data corrections, or feature flags.
    php artisan patch:create add_missing_index --description="Add index to orders table for performance"
    
  2. Application

    • Single Patch:
      php artisan patch:apply add_missing_index
      
    • Batch Apply (e.g., during deployments):
      php artisan patch:apply --all --env=staging
      
    • Conditional Apply (e.g., skip if already applied):
      php artisan patch:apply --force
      
  3. Rollback

    • Patches are not reversible by default, but you can:
      • Create a dedicated rollback patch:
        php artisan patch:create revert_missing_index --description="Revert index addition"
        
      • Use transactions in your patch logic for safety:
        DB::transaction(function () {
            // Patch logic
        });
        

Integration with Laravel Features

  1. Artisan Commands

    • Extend the package by publishing its commands and modifying them:
      // app/Console/Commands/CustomPatchCommand.php
      use Aaix\LaravelPatches\Commands\PatchApplyCommand;
      
      class CustomPatchCommand extends PatchApplyCommand {
          protected $signature = 'patch:custom {name}';
          // Override logic
      }
      
  2. Event Listeners

    • Trigger actions when patches are applied/created:
      // app/Providers/EventServiceProvider.php
      protected $listen = [
          \Aaix\LaravelPatches\Events\PatchApplied::class => [
              \App\Listeners\LogPatchApplication::class,
          ],
      ];
      
  3. Database Seeding

    • Use patches to seed initial data or fix corrupted data:
      // database/patches/seed_initial_data.php
      return function () {
          factory(App\User::class, 10)->create();
      };
      
    • Apply during php artisan db:seed.
  4. Environment-Specific Patches

    • Store patches in database/patches/{env}/ (e.g., database/patches/production/) and use the --env flag:
      php artisan patch:apply --env=production
      

Advanced Workflows

  1. Patch Dependencies

    • Enforce patch order with metadata:
      // database/patches/fix_order_total.php
      return [
          'run' => function () {
              // Fix logic
          },
          'depends_on' => ['add_missing_index'], // Requires this patch first
      ];
      
    • Note: The package doesn’t natively support dependencies; implement this in your patch logic or via a custom command.
  2. Patch Testing

    • Test patches in isolation using patch:test (if the package adds this in future) or manually:
      // tests/Feature/PatchesTest.php
      public function test_my_patch() {
          $this->artisan('patch:apply', ['name' => 'my_first_patch'])
               ->expectsOutput('Patch applied successfully');
          $this->assertDatabaseHas('users', ['is_admin' => true]);
      }
      
  3. Patch Documentation

    • Store patch descriptions in the database and expose them via a custom route:
      // routes/web.php
      Route::get('/patches', function () {
          return \Aaix\LaravelPatches\Models\Patch::latest()->get();
      });
      

Gotchas and Tips

Pitfalls

  1. Idempotency

    • Patches must be idempotent (safe to run multiple times). Non-idempotent patches (e.g., DELETE queries) will cause issues.
    • Fix: Use INSERT IGNORE or check existence first:
      if (!DB::table('patches_metadata')->where('key', 'exists')->exists()) {
          DB::table('patches_metadata')->insert(['key' => 'exists', 'value' => 1]);
      }
      
  2. Database Locks

    • Long-running patches can block migrations or other commands.
    • Fix: Run patches during low-traffic periods or use DB::connection()->disableEvents() to reduce overhead.
  3. Patch Discovery

    • Patches are loaded from database/patches/ by default. Custom paths require config:
      // config/patches.php
      'patch_paths' => [
          database_path('patches'),
          database_path('patches/custom'),
      ],
      
  4. Environment Mismatches

    • Applying a patch to the wrong environment (e.g., production) can cause data loss.
    • Fix: Use --env explicitly and restrict production access:
      php artisan patch:apply --env=staging
      
  5. Patch Conflicts

    • Multiple patches modifying the same data can lead to race conditions.
    • Fix: Use database transactions or locks:
      DB::transaction(function () {
          // Critical patch logic
      });
      

Debugging

  1. Failed Patches

    • Check the patches table for status = 'failed'.
    • Inspect logs (storage/logs/laravel.log) for exceptions.
  2. Missing Patches

    • Ensure patch files are in the correct directory and named exactly as registered in the database.
  3. Permission Issues

    • Verify the Laravel storage directory (bootstrap/cache/) and database/ are writable:
      chmod -R 775 storage bootstrap/cache database
      

Tips

  1. Naming Conventions

    • Use kebab-case for patch names (e.g., fix_user_auth_bug) to avoid issues with PHP constants.
  2. Patch Metadata

    • Extend the patches table to track additional metadata:
      // Add columns via migration
      Schema::table('patches', function (Blueprint $table) {
          $table->string('author')->nullable();
          $table->timestamp('scheduled_at')->nullable();
      });
      
  3. Automated Patch Application

    • Trigger patches via deploy hooks (e.g., Deployer):
      task('deploy:patch', function () {
          run('php artisan patch:apply --env=production --all');
      });
      
  4. Patch Validation

    • Validate patch files before applying (e.g., check for syntax errors):
      // app/Console/Kernel.php
      protected function schedule(PatchSchedule $schedule) {
          $schedule->command('patch:validate')->everyMinute();
      }
      
  5. Backup Before Patching

    • Always back up critical data before applying patches, especially in production:
      php artisan backup:run --only-db
      php artisan patch:apply my_patch
      
  6. Patch Testing in CI

    • Add patch testing to your CI pipeline:
      # .github/workflows/tests.yml
      jobs:
        test:
          runs-on: ubuntu-latest
      
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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