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

Zippy Laravel Package

alchemy/zippy

Zippy is a PHP library to read, create, list, and extract archives using CLI tools or PHP extensions. Supports ZIP plus GNU/BSD tar formats (.tar, .tar.gz, .tar.bz2) via a simple API for opening, iterating members, extracting, and creating archives.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require alchemy/zippy
    

    Add to composer.json if using Laravel's autoloader:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Alchemy\\Zippy\\": "vendor/alchemy/zippy/src/"
        }
    }
    
  2. Basic Usage:

    use Alchemy\Zippy\Zippy;
    
    $zippy = Zippy::load();
    

First Use Case: Extracting a ZIP File

$archive = $zippy->open('path/to/file.zip');
$archive->extract(storage_path('app/extracted'));

First Use Case: Creating a ZIP Archive

$archive = $zippy->create('backup.zip', [
    'folder' => storage_path('app'),
    'file.txt' => fopen('path/to/file.txt', 'r'),
]);

Implementation Patterns

Common Workflows

1. Handling Multiple Archive Types

Leverage Zippy’s adapter system to handle .zip, .tar, .tar.gz, and .tar.bz2 without switching libraries:

$zippy = Zippy::load(['adapter' => 'zip']); // Force ZIP adapter
// or
$zippy = Zippy::load(['adapter' => 'tar']); // Force TAR adapter

2. Streaming Remote Archives

Use teleporters (e.g., Guzzle) to fetch and extract archives directly from URLs:

$archive = $zippy->open('https://example.com/archive.zip');
$archive->extract(storage_path('app/remote'));

3. Customizing Archive Contents

Map local paths to custom names inside the archive:

$archive = $zippy->create('custom.zip', [
    'public/images' => 'assets/images', // Rename directory
    'README.md' => 'documentation/README.md', // Custom path
]);

4. Iterating and Filtering Archive Contents

$archive = $zippy->open('archive.zip');
foreach ($archive as $member) {
    if (str_contains($member, 'config/')) {
        $member->extract(storage_path('app/config'));
    }
}

5. Laravel Integration

Use Zippy in Laravel controllers/services:

// In a Laravel service
public function backupDatabase()
{
    $zippy = Zippy::load();
    $archive = $zippy->create(storage_path('app/backup/backup.zip'), [
        'database' => database_path(),
    ]);
    return $archive->close();
}

Integration Tips

1. Artisan Commands

Create a custom Artisan command for archive operations:

// app/Console/Commands/MakeArchive.php
use Alchemy\Zippy\Zippy;

class MakeArchive extends Command
{
    protected $signature = 'archive:create {name} {--path=}';
    public function handle()
    {
        $zippy = Zippy::load();
        $archive = $zippy->create(
            storage_path("app/{$this->argument('name')}.zip"),
            [$this->option('path') ?: 'storage/app' => '.']
        );
        $this->info("Archive created: {$archive->getPathname()}");
    }
}

2. File System Events

Listen for file uploads and auto-archive them:

// In a Laravel event listener
use Alchemy\Zippy\Zippy;

public function handle(FileUploaded $event)
{
    $zippy = Zippy::load();
    $archive = $zippy->create(
        storage_path('app/uploads/archive.zip'),
        [$event->file->path() => 'uploads/' . $event->file->getClientOriginalName()]
    );
}

3. Queue Jobs for Large Archives

Offload archive creation to a queue job:

// app/Jobs/CreateArchiveJob.php
use Alchemy\Zippy\Zippy;

class CreateArchiveJob implements ShouldQueue
{
    public function handle()
    {
        $zippy = Zippy::load();
        $archive = $zippy->create('large_archive.zip', [
            'huge_directory' => storage_path('app/huge_directory'),
        ]);
    }
}

4. Testing

Mock Zippy in PHPUnit tests:

$mockArchive = $this->createMock(Archive::class);
$mockArchive->method('extract')->willReturn(true);
$zippy = $this->createMock(Zippy::class);
$zippy->method('open')->willReturn($mockArchive);

Gotchas and Tips

Pitfalls

1. Path Handling

  • Issue: Relative paths may cause extraction failures. Fix: Use absolute paths or normalize them:
    $archive->extract(realpath('/tmp/extracted'));
    

2. File Permissions

  • Issue: Extracted files may inherit incorrect permissions. Fix: Use Filesystem to set permissions post-extraction:
    $files = File::allFiles(storage_path('app/extracted'));
    foreach ($files as $file) {
        File::chmod($file, 0644);
    }
    

3. UTF-8 Filenames

  • Issue: Non-ASCII filenames may be corrupted. Fix: Ensure mbstring extension is enabled (Zippy requires it).

4. Large Files

  • Issue: Memory issues with large archives. Fix: Use streaming adapters (e.g., zip or tar CLI tools) or chunked processing.

5. Adapter Availability

  • Issue: PHP’s built-in zip extension may not be available. Fix: Fall back to CLI tools (e.g., zip or tar commands):
    $zippy = Zippy::load(['adapter' => 'zip-cli']); // Use system zip tool
    

Debugging Tips

1. Log Archive Contents

$archive = $zippy->open('archive.zip');
foreach ($archive as $member) {
    Log::debug("Member: {$member->getPathname()}");
}

2. Verify Adapter Support

$zippy = Zippy::load();
Log::info('Supported adapters:', $zippy->getSupportedAdapters());

3. Handle Exceptions

Wrap Zippy operations in try-catch blocks:

try {
    $archive = $zippy->open('nonexistent.zip');
} catch (ArchiveException $e) {
    Log::error("Archive error: " . $e->getMessage());
}

Extension Points

1. Custom Adapters

Extend Zippy to support additional formats (e.g., .7z):

// app/Adapters/CustomAdapter.php
use Alchemy\Zippy\Adapter\AdapterInterface;

class CustomAdapter implements AdapterInterface
{
    public function open($pathname) { /* ... */ }
    public function create($pathname, array $resources) { /* ... */ }
}

Register the adapter in Zippy::load():

$zippy = Zippy::load(['adapters' => ['custom' => new CustomAdapter()]]);

2. Pre/Post-Processing

Hook into archive events (e.g., before extraction):

$archive->on('extract', function ($member, $target) {
    Log::info("Extracting: {$member->getPathname()} to {$target}");
});

3. Override Default Config

Customize Zippy’s behavior globally:

$zippy = Zippy::load([
    'adapter' => 'zip',
    'options' => [
        'compression_level' => 9, // Max compression
        'exclude' => ['*.log', 'node_modules/'],
    ],
]);

4. Laravel Service Provider

Bind Zippy to the container for dependency injection:

// app/Providers/AppServiceProvider.php
public function register()
{
    $this->app->singleton(Zippy::class, function () {
        return Zippy::load();
    });
}

Configuration Quirks

1. CLI Tools Path

If system tools (zip, tar) are not in PATH, specify their paths:

$zippy = Zippy::load([
    'adapter' => 'zip-cli',
    'options' => ['zip_path' => '/usr/local/bin/zip'],
]);

2. Memory Limits

For large archives, increase PHP’s memory limit:

ini_set('memory_limit', '512M');
$zippy = Zippy::load();

3. Timezone Handling

Ensure consistent timestamps in archives:

date_default_timezone_set('UTC');
$archive = $zippy->create('archive.zip', [...]);
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
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
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