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

Destroy Laravel Package

internal/destroy

Explicit, deterministic resource cleanup for PHP via a Destroyable interface. Breaks circular reference chains and prevents memory leaks in long-running apps without relying on __destruct() or expensive gc_collect_cycles(). Ideal for daemons and event loops.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package via Composer:

composer require internal/destroy

The core is the Destroyable interface. Implement it on classes managing non-trivial resources (e.g., listeners, connections, async tasks) to expose a deterministic destroy(): void method. This replaces reliance on PHP’s unpredictable __destruct()—especially vital in long-running processes where circular references cause memory leaks.

First use case: Long-running queue workers. Example:

use Internal\Destroy\Destroyable;

class MessageConsumer implements Destroyable
{
    private \Iterator $consumer;
    private array $cache = [];

    public function __construct(\Iterator $consumer)
    {
        $this->consumer = $consumer;
    }

    public function consume(): ?array
    {
        return $this->consumer->current();
    }

    public function destroy(): void
    {
        // Explicitly release resources
        $this->cache = [];
        $this->consumer = null;
        // Close socket/connection if applicable
    }
}

Invoke destroy() at worker shutdown (e.g., in finally block or shutdown handler).

Implementation Patterns

  • Composite destruction: Wrap aggregates (e.g., EventBus, Server, EventLoop) to cascade destruction. Children must also implement Destroyable.
class WebSocketServer implements Destroyable
{
    private array $clients = [];

    public function addClient(Destroyable $client): void
    {
        $this->clients[] = $client;
    }

    public function destroy(): void
    {
        foreach ($this->clients as $client) {
            $client->destroy();
        }
        $this->clients = [];
        // Close server socket, detach event loop, etc.
    }
}
  • Service container shutdown: In Laravel, register a singleton listener that destroys all Destroyable services on App::beforeResponseShutdown() or custom lifecycle hooks.

  • Test cleanup: In PHPUnit, add destroy() calls to tearDown() to prevent cross-test pollution from lingering state.

  • Caching layers: Wrap cache adapters that hold internal pools (e.g., Redis cluster clients) in Destroyable to flush buffers and release connections.

Gotchas and Tips

  • Zero automatic behavior: destroy() is never auto-called. You must inject shutdown hooks or hooks in worker loops— forgetting this defeats the purpose. Use register_shutdown_function() or Laravel’s Queue::after() for workers.
  • Destructors ≠ destroy(): Don’t duplicate cleanup logic between __destruct() and destroy(). Prefer destroy() for long-running contexts; let __destruct() be a fallback only if absolutely necessary (but know it may not run).
  • Non-Destroyable dependencies: Laravel’s DB or Cache instances won’t implement Destroyable out-of-the-box. Manually release connections (e.g., DB::purge(), Cache::flush()) inside your destroy() implementation—even if the underlying service doesn’t.
  • Validation: Use Psalm with phpstan-phpunit to catch un-called destroy() on Destroyable types. Architectural tests (e.g., phpunit-architecture-test) can enforce that all queue job handlers implement Destroyable.
  • Memory profiling: After implementing destroy(), verify impact with Xdebug Profiler or memory_get_usage(true) before/after shutdown—don’t assume cleanup happened.
  • Avoid overuse: For short HTTP requests, do not use destroy(). PHP auto-cleans at request end. This package targets only persistent processes.
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport