phpdot/package

Auto-discovery and lifecycle management for PHPdot packages.

Maintainers

Package info

github.com/phpdot/package

pkg:composer/phpdot/package

Statistics

Installs: 4

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-04-05 19:42 UTC

This package is auto-updated.

Last update: 2026-04-05 19:52:27 UTC


README

Auto-discovery and lifecycle management for PHPdot packages. Reads Composer's installed.json, topologically sorts by dependencies, runs register then boot.

Install

composer require phpdot/package
Requirement Version
PHP >= 8.3
phpdot/container >= 1.1
psr/container >= 2.0

How It Works

composer.json (per package)
    extra.phpdot.package = "Vendor\\Pkg\\PkgPackage"
        ↓
PackageDiscovery → reads installed.json, filters phpdot packages, caches result
        ↓
DependencyResolver → topological sort via DFS, detects cycles
        ↓
PackageKernel
    Phase 1: register() → each package feeds definitions into ContainerBuilder
    Phase 2: boot()     → each package runs post-build logic with live container

PackageInterface

Every package implements this. Two methods, zero magic.

use PHPdot\Container\ContainerBuilder;
use PHPdot\Package\PackageInterface;
use Psr\Container\ContainerInterface;

final class MongoDBPackage implements PackageInterface
{
    public function register(ContainerBuilder $builder): void
    {
        $builder->addDefinitions([
            Connection::class => scoped(static function (ContainerInterface $c): Connection {
                return new Connection($c->get(ConnectionConfig::class));
            }),
        ]);
    }

    public function boot(ContainerInterface $container): void
    {
    }
}

Register in composer.json:

{
    "extra": {
        "phpdot": {
            "package": "PHPdot\\MongoDB\\MongoDBPackage"
        }
    }
}

Install via Composer. Next boot picks it up automatically. No code changes.

PackageKernel

use PHPdot\Container\ContainerBuilder;
use PHPdot\Package\DependencyResolver;
use PHPdot\Package\PackageDiscovery;
use PHPdot\Package\PackageKernel;

$builder = new ContainerBuilder();

$kernel = new PackageKernel(new PackageDiscovery(), new DependencyResolver());
$kernel->register($vendorPath, $builder);

$container = $builder->build();

$kernel->boot($container);

Dependency Order

Dependencies come from Composer's require keys. Only phpdot-enabled packages are considered.

phpdot/config    → deps: []
phpdot/i18n      → deps: [phpdot/config]
phpdot/mongodb   → deps: [phpdot/config]
company/billing  → deps: [phpdot/mongodb]

Sorted: [config, i18n, mongodb, billing]

When any package's register() or boot() runs, every package it depends on has already completed that phase.

Cyclic dependencies throw CyclicDependencyException.

Caching

Discovery caches the sorted result as a PHP file in the vendor directory. Cache is invalidated when installed.json is newer than the cache file.

PackageDiscovery::clearCache($vendorPath);

Works as a Composer script:

{
    "scripts": {
        "post-autoload-dump": [
            "PHPdot\\Package\\PackageDiscovery::clearCache"
        ]
    }
}

API Reference

PackageInterface

interface PackageInterface

register(ContainerBuilder $builder): void
boot(ContainerInterface $container): void

PackageKernel

final class PackageKernel

__construct(PackageDiscovery $discovery, DependencyResolver $resolver)
register(string $vendorPath, ContainerBuilder $builder): void
boot(ContainerInterface $container): void
packages(): list<DiscoveredPackage>
instances(): list<PackageInterface>

PackageDiscovery

final class PackageDiscovery

discover(string $vendorPath): list<DiscoveredPackage>
static clearCache(mixed $eventOrVendorPath): void

DependencyResolver

final class DependencyResolver

resolve(list<DiscoveredPackage> $packages): list<DiscoveredPackage>

DiscoveredPackage

final readonly class DiscoveredPackage

public string $name
public string $class       (class-string<PackageInterface>)
public array  $dependencies (list<string>)

Exceptions

PackageDiscoveryException — class not found, interface not implemented
CyclicDependencyException — circular dependency detected

License

MIT