Weave 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

Swoole Reflection Laravel Package

upscale/swoole-reflection

A niche PHP utility adding reflection support for Swoole classes, helping developers introspect Swoole objects and coroutine-related structures. Lightweight and low-profile, aimed at projects running Swoole or Laravel with Swoole.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a single-purpose, low-adoption package (2 stars, 0 dependents), so treat the source as the documentation. Budget 15 minutes to read src/ and tests/ before writing any code against it.

Install and verify the environment

composer require upscale/swoole-reflection
php -r "echo SWOOLE_VERSION, PHP_EOL;"
composer show upscale/swoole-reflection   # note the exact version/tag

Confirm two things immediately:

  1. Swoole version constraints — reflection against internal classes like Swoole\Http\Request or Swoole\Coroutine is version-sensitive. Check composer.json for ext-swoole constraints and any SWOOLE_VERSION guards in src/.
  2. Autoload namespace — open composer.json and note the PSR-4 root (likely Upscale\SwooleReflection\ or similar). Everything else in this assessment assumes you've mapped the real entry class.

First use case: inspect a live request inside a coroutine

The typical first win is dumping the internals of a Swoole request/response object that PHP's native reflection can't reach cleanly, or that var_dump truncates. Run it inside an actual Swoole HTTP handler, not the CLI — Swoole internal objects behave differently outside a coroutine/server context:

$server->on('request', function ($request, $response) {
    // Confirm the exact API from src/ first — illustrative only.
    $props = \Upscale\SwooleReflection\Reflector::properties($request);
    error_log(print_r($props, true));
    $response->end('ok');
});

If that works, you have a debugging tool. If you need route/attribute scanning (likely, given "web-server" in the description), jump to the WorkerStart pattern below — do not reflect per request.

Implementation Patterns

1. Cache reflection metadata at worker boot, never per request. Reflection is cheap-ish but not free, and doing it inside a coroutine handler on every request is the fastest way to regress throughput. Build your class/property/method maps once in WorkerStart and store them in a plain array or a container singleton that survives the worker's lifetime.

$server->on('WorkerStart', function ($server, int $workerId) use ($container) {
    $container->singleton('swoole.reflection', fn () => new Reflector());
    $container->set('routes', RouteScanner::scan(__DIR__ . '/Controllers'));
});

2. Wrap it behind your own interface. With 2 stars and zero dependents, the API surface has no community stability guarantee. Bind it once:

final class SwooleInspector
{
    public function __construct(private Reflector $reflector) {}
    public function internals(object $swooleObj): array { /* delegate */ }
}

Now a breaking change or an abandoned package means editing one file, not fifty call sites — or forking it. Apache-2.0 makes forking trivially legal, and the package is small enough that a fork is often cheaper than adapting.

3. Use it to fake Swoole objects in tests. The highest-value day-to-day use: constructing Swoole\Http\Request / Response doubles with populated private state so you can unit-test handlers without booting a server. Build a test helper that returns a configured fake, and keep it in tests/Support/ — this is the pattern most likely to pay for the dependency on its own.

4. Debug middleware in non-production environments. A middleware that reflects the current request/coroutine context and logs it, gated on APP_DEBUG and SWOOLE_DEBUG:

if (! config('app.debug')) { return $next($request); }
$log->debug('swoole.request', ['internals' => $inspector->internals($request)]);

Never register this unconditionally — reflecting and serializing internals is slow and can leak client socket data into logs.

5. Attribute/route discovery, if that's the package's focus. Scan controllers once per worker, cache the resulting route table (in memory, or a cache file if startup cost matters), and invalidate on deploy. Do not rely on Swoole's hot-reload for this unless you've verified the worker actually re-runs your scan.

Gotchas and Tips

  • Internal Swoole classes are not a stable ABI. Private properties on Swoole\Http\Request, Swoole\Coroutine, and friends can be renamed or restructured between Swoole 4.x, 5.x, and 6.x. Pin ext-swoole in CI (pecl install swoole-5.1.x) and run your reflection-dependent tests against that exact version.
  • Pin the Composer version. With no releases to speak of, you may be pulling dev-main. Use "upscale/swoole-reflection": "dev-main#<commit-sha>" so an upstream force-push doesn't silently change behaviour between deploys.
  • Reflection does not always mean initialized. Reading a property that the engine hasn't populated (e.g. a request object before headers are parsed) yields null or throws Error: Typed property must not be accessed before initialization. Wrap reads in try/catch and treat failures as "not available yet", not as bugs.
  • setAccessible(true) is a no-op since PHP 8.1. Old examples call it everywhere; it's harmless, but don't assume it's doing anything. Access control on reflection reads was removed.
  • Don't cache live Swoole objects across workers. Forked workers don't share heap state, and any reflected object holding an fd or connection becomes stale after WorkerStart. Cache metadata (class names, property maps), never instances.
  • Coroutine context matters. Some internals are only populated inside a coroutine (Co::getCid() > 0). A CLI smoke test that "works" may behave differently under Swoole\Http\Server. Always validate in the real server.
  • Debugging aid: when an internal property read fails, enumerate what is visible with (new \ReflectionClass($obj))->getProperties() and log both the Swoole version and the package version together — that pair is what you'll need when filing an issue upstream or deciding to fork.
  • Extension point to prefer: a thin adapter class you own, as in pattern 2. Subclassing the package's classes directly couples you to its constructor signatures, which are the most likely thing to change in an unversioned library.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route