3rdpartyeve/phealng
PhealNG is a PHP client library for the EVE Online XML API, offering namespaced, PSR-0 compatible classes. Note: this package is deprecated and archived, since CCP shut down the XML API in 2018, so it is not suitable for new projects.
First step: confirm you actually need it. This package targets EVE Online's XML API (api.eveonline.com), which CCP shut down in 2018, and the repository is archived. There will be no patches, no PHP 8 compatibility work, and no security fixes. Any live request will fail at DNS/connection level, not with an auth error — so if you're debugging "invalid key" messages, you're already off track.
Practical triage order:
composer why 3rdpartyeve/phealng — check whether it's a direct dependency or dragged in transitively. Packagist flags it as abandoned, so Composer will warn on install.composer.json from an old project, remove it and delete the corresponding service bindings. There is no data source behind it anymore.https://esi.evetech.net) with OAuth2 SSO. Laravel's HTTP client covers this without a third-party SDK:// config/services.php
'eve' => [
'client_id' => env('EVE_CLIENT_ID'),
'client_secret' => env('EVE_CLIENT_SECRET'),
'redirect' => env('EVE_REDIRECT_URI'),
],
// A simple public-endpoint call
$character = Http::baseUrl('https://esi.evetech.net/latest')
->withHeaders(['User-Agent' => config('app.name') . ' (' . config('app.url') . ')'])
->get("/characters/{$characterId}/")
->throw()
->json();
The one legitimate use case left is archaeology: you have an old Laravel app or a test suite containing archived XML fixtures and you need to read response shapes to port logic to ESI. For that, install it in an isolated php:7.1/7.2 container rather than your main app:
composer require 3rdpartyeve/phealng:~2.0
$pheal = new \Pheal\Pheal();
$pheal->scope = 'char';
$pheal->characterID = $characterId;
$result = $pheal->CharacterSheet();
$plain = $result->toArray(); // hydrate into your own DTOs from here
Where to look first in the source: Pheal\Core\Config (endpoint/URI overrides), Pheal\Cache\CacheInterface, Pheal\Log\LoggerInterface, Pheal\Access\AccessInterface, and the Pheal\Http\* transport classes. Those four injection points are the only genuinely reusable ideas in the package.
The package ships no Laravel service provider, no facade, and no publishable config — you wire everything yourself. If you're forced to keep it running against fixtures or a replayed archive, treat it as an internal detail behind your own boundary.
Adapter boundary. Never let \Pheal\Pheal leak into controllers or jobs. Define an interface that describes what you need, not how it's fetched, so the ESI migration is a swap rather than a rewrite:
interface CharacterDirectory
{
public function sheet(int $characterId): CharacterSheet;
}
final class LegacyPhealDirectory implements CharacterDirectory
{
public function __construct(private \Pheal\Pheal $pheal) {}
public function sheet(int $characterId): CharacterSheet
{
$this->pheal->scope = 'char';
$this->pheal->characterID = $characterId;
return CharacterSheet::fromArray($this->pheal->CharacterSheet()->toArray());
}
}
Bind it once in a provider, as a singleton, because the client carries mutable state (scope, characterID) on the instance:
$this->app->singleton(\Pheal\Pheal::class, fn () => tap(new \Pheal\Pheal(), function ($p) {
$p->setCache(new LaravelCacheAdapter(cache()->store('eve')));
$p->setLogger(new LaravelLogAdapter(logger()));
}));
Cache adapter. Implement CacheInterface over Laravel's cache so responses are shared across workers and observable in your usual tooling. This is the single highest-value pattern in the library — the interface forces you to make caching explicit instead of burying it in HTTP calls.
Access/credentials adapter. Pull keyID/vCode (or, post-migration, the OAuth token) from config or a per-user model. The original library idiom was passing credentials straight into the constructor, which reliably ends with keys in source control.
Queue bulk character pulls. Anything character-scoped is inherently N-per-user. One job per character, rate-limited via Redis::throttle(), results written to Eloquent. The library's HTTP transport is synchronous, so never fan out inside a web request.
Fixture-driven tests. Point the config at a local directory of archived XML and assert on your DTOs, not on the library. That keeps your test suite valid after you delete the package.
Pheal\Core\Config points at a host that no longer serves the XML API. A timeout here means "dead service," not "bad credentials." Don't spend an afternoon rotating keys.$pheal->scope or $pheal->characterID mutates the instance. As a singleton in a long-lived queue worker this is a cross-job leak waiting to happen — either reset scope explicitly per call or bind it as a scoped/transient instance.composer audit to have your back.CacheInterface / Log\LoggerInterface / Access\AccessInterface trio is a decent architecture for any API client — cache and logging as injected collaborators rather than hardcoded. That's the takeaway; port the idea, not the code.How can I help you explore Laravel packages today?