hoa/protocol
Hoa\Protocol is a PHP library for abstracting resource access through a hierarchical protocol system. It lets you register custom protocols and resolvers, then resolve paths such as hoa:// or app:// to real resources, simplifying flexible file and stream handling.
hoa/protocol is an archived Hoa path/protocol resolver. Treat it as a legacy compatibility tool: use it when maintaining Hoa-based code or an existing hoa://-style path registry, not for new greenfield projects.
Minimal setup:
composer require hoa/protocol
Look first at:
README.md for the current API examples.Hoa\Protocol\Protocol for the global registry/resolution entry point.Hoa\Protocol\Node for the protocol tree structure.Hoa\Protocol\Wrapper if your legacy code uses stream-wrapper access.First use case: register a logical application root and resolve paths from it.
use Hoa\Protocol\Protocol;
use Hoa\Protocol\Node;
Protocol::getInstance()->add(
new Node('app', [
new Node('config', __DIR__ . '/config'),
new Node('storage', __DIR__ . '/storage'),
])
);
$configFile = Protocol::getInstance()->resolve('app://config/app.php');
Use the resolved string with normal PHP filesystem functions. That keeps path selection centralized while avoiding hard-coded absolute paths throughout the app.
Bootstrap path registry. Register protocol roots once during application bootstrap, then resolve logical paths at the edges where files are read or written. This works well for config, cache, storage, uploads, and module directories.
Environment-specific roots. Register different base directories per environment, but keep the same logical protocol names:
$base = getenv('APP_ENV') === 'prod' ? '/var/www/app' : __DIR__;
Protocol::getInstance()->add(
new Node('app', [
new Node('config', $base . '/config'),
new Node('storage', $base . '/storage'),
])
);
Legacy Hoa integration. If old Hoa libraries expect hoa:// paths, use this package to keep those resolutions working. Avoid spreading new hoa:// references into modern code; isolate them behind a small path service.
Resolve, then use native I/O. Prefer resolve() and pass the result to file_get_contents(), fopen(), include, or your filesystem abstraction. If the package’s stream wrapper is already part of your legacy stack, register it once in bootstrap and test stat, is_file, realpath, and include behavior explicitly.
Testing isolation. Because the protocol registry is global, reset or rebuild it between tests. Register temporary directories per test rather than sharing one mutable tree.
Extension point. Add custom Node instances for application-specific protocols, and keep node names stable. If you need custom resolution behavior, wrap resolution in your own service rather than modifying vendor code.
composer.lock, test on your target PHP version, and avoid introducing it into new projects unless required by legacy Hoa dependencies.Protocol::getInstance() is shared process state. Duplicate node names, registration order, and test pollution are common failure modes.resolve() sanitizes .., duplicate separators, or trailing slashes. Validate user input and constrain protocol selection to a known allowlist.stat, realpath, is_file, include_path, and relative-path behavior. Some filesystem functions behave differently through custom wrappers.DIRECTORY_SEPARATOR and test path concatenation on Windows. Protocol resolution may not normalize separators for you.var_dump(Protocol::getInstance()) when resolution returns an unexpected location.How can I help you explore Laravel packages today?