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

Cli Progress Bar Laravel Package

dariuszp/cli-progress-bar

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require dariuszp/cli-progress-bar
    
  2. First Use Case: Add a progress bar to a loop in an Artisan command or script:

    use Dariuszp\CliProgressBar;
    
    $bar = new CliProgressBar(100); // Total iterations
    $bar->display();
    
    for ($i = 0; $i <= 100; $i++) {
        // Your processing logic here
        $bar->setDetails("Processing record $i");
        sleep(0.1); // Simulate work
    }
    $bar->end();
    
  3. Where to Look First:

    • Examples Directory: Clone the repo and check examples/ for use cases like colors, animations, and alternate styles.
    • README.md: Focus on the Usage section for core methods (display(), setDetails(), end()).
    • Alternate Style: Test Windows compatibility with displayAlternateProgressBar().

Implementation Patterns

Usage Patterns

  1. Artisan Commands: Integrate into Laravel’s CLI workflows by extending Illuminate\Console\Command:

    use Dariuszp\CliProgressBar;
    
    protected function handle() {
        $bar = new CliProgressBar(100, 0, "Migrating data...");
        $bar->display();
    
        foreach ($this->records as $record) {
            $this->processRecord($record);
            $bar->increment(); // Update progress
        }
        $bar->end();
    }
    
  2. Queue Workers: Use in handle() methods of Laravel jobs for async progress feedback:

    public function handle() {
        $bar = new CliProgressBar(10, 0, "Exporting files...");
        $bar->display();
    
        foreach ($this->files as $file) {
            $this->exportFile($file);
            $bar->increment();
        }
        $bar->end();
    }
    
  3. Dynamic Updates: Update progress bars asynchronously (e.g., during API calls or DB queries):

    $bar = new CliProgressBar(5, 0, "Fetching data...");
    $bar->display();
    
    foreach ($this->apiCalls as $call) {
        $response = Http::get($call);
        $bar->setDetails("Fetched {$response->status()} for {$call}");
        $bar->increment();
    }
    

Workflows

  1. Progress Bar Lifecycle:

    • Initialize: Pass total steps and optional initial progress.
    • Display: Call display() to render the bar.
    • Update: Use increment(), setDetails(), or setProgress() during loops.
    • Cleanup: Call end() to finalize output.
  2. Cross-Platform Handling: Auto-detect Windows and switch to ASCII style:

    $bar = new CliProgressBar(100);
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        $bar->displayAlternateProgressBar();
    }
    $bar->display();
    
  3. Customization:

    • Text: Set context with setDetails() or pass during initialization.
    • Length: Adjust bar size via constructor (e.g., new CliProgressBar(100, 0, "Text", 30) for a 30-character bar).
    • Colors: Extend the class to add ANSI color support (see examples/colors.php).

Integration Tips

  1. Laravel Service Container: Bind the progress bar to the container for dependency injection:

    $this->app->singleton(CliProgressBar::class, function ($app) {
        return new CliProgressBar(100, 0, "Default text");
    });
    
  2. Command Options: Allow users to enable/disable progress bars via CLI flags:

    protected $signature = 'command {--progress : Show progress bar}';
    protected function handle() {
        if ($this->option('progress')) {
            $bar = new CliProgressBar(100);
            $bar->display();
            // ... loop with updates
            $bar->end();
        }
    }
    
  3. Testing: Mock progress bars in unit tests by extending the class:

    class MockProgressBar extends CliProgressBar {
        public function display() {}
        public function end() {}
        public function increment() {}
    }
    

Gotchas and Tips

Pitfalls

  1. Windows UTF-8 Issues:

    • Problem: Progress bars may render incorrectly on Windows due to UTF-8 block characters (▓░).
    • Fix: Use displayAlternateProgressBar() or set the environment variable DARIUSZP_CLI_PROGRESS_BAR_ALTERNATE=1.
  2. Async Updates:

    • Problem: Rapid setDetails() calls may cause output corruption or lag.
    • Fix: Throttle updates or batch them (e.g., update every 5 iterations).
  3. Non-Interactive Shells:

    • Problem: Progress bars may appear broken in cron jobs or pipes.
    • Fix: Detect non-interactive shells and disable progress bars:
      if (php_sapi_name() !== 'cli' || !stream_isatty(STDERR)) {
          return; // Skip progress bar
      }
      
  4. Memory Leaks:

    • Problem: Long-running processes may retain progress bar state.
    • Fix: Explicitly call end() to clean up output buffers.

Debugging

  1. Broken Output:

    • Check: Ensure your terminal supports ANSI escape sequences (most modern terminals do).
    • Test: Run echo -e "\e[31mRed Text\e[0m" in your terminal to verify ANSI support.
  2. Progress Not Updating:

    • Check: Verify increment() or setProgress() is called in the correct loop iteration.
    • Debug: Add sleep(0.1) after updates to force terminal refreshes.
  3. Windows-Specific Issues:

    • Check: Use displayAlternateProgressBar() or install a UTF-8-compatible terminal (e.g., Windows Terminal).

Config Quirks

  1. Bar Length:

    • The constructor’s second parameter is the initial progress (not length). Length is fixed unless extended.
    • To change length, extend the class and override the getBarLength() method.
  2. Text Truncation:

    • Long setDetails() text may overflow. Limit text length or adjust terminal width dynamically:
      $bar->setDetails(substr("Long text...", 0, 30));
      
  3. Percentage Precision:

    • Progress is rounded to 1 decimal place by default. Override the formatPercentage() method for custom formatting.

Extension Points

  1. Custom Styling: Extend the class to add colors or symbols:

    class ColoredProgressBar extends CliProgressBar {
        protected function getFilledChar(): string {
            return "\033[32m▓\033[0m"; // Green filled block
        }
        protected function getEmptyChar(): string {
            return "\033[31m░\033[0m"; // Red empty block
        }
    }
    
  2. Dynamic Length: Adjust bar length based on terminal width:

    $bar = new CliProgressBar(100);
    $bar->setBarLength(exec('tput cols') - 20); // Leave space for text
    
  3. Event-Based Updates: Hook into Laravel events (e.g., job.processed) to update progress bars:

    event(new JobProcessed($job));
    $bar->setDetails("Processed {$job->payload['data']['command']}");
    $bar->increment();
    
  4. Fallback to Symfony Console: Create a wrapper that falls back to symfony/console if issues arise:

    class ProgressBarService {
        public function create(int $total, string $text = ''): CliProgressBar {
            try {
                return new CliProgressBar($total, 0, $text);
            } catch (\Exception $e) {
                return new SymfonyProgressBar($total, $text);
            }
        }
    }
    

Laravel-Specific Tips

  1. Artisan Output: Use Artisan::output() alongside progress bars for mixed output:

    Artisan::output("Starting migration...");
    $bar = new CliProgressBar(10);
    $bar->display();
    // ... loop
    $bar->end();
    Artisan::output("Migration complete!");
    
  2. Queue Workers: Integrate with laravel-horizon or backstage by extending the worker class:

    class ProgressWorker extends Worker {
        protected function getProgressBar(int $total): CliProgressBar {
            return new CliProgress
    
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.
althinect/enum-permission
andydefer/laravel-actions
aimeos/prisma
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