ppi/skeleton-app
A starter skeleton application for the PPi PHP framework, providing the base structure, bootstrap wiring, and configuration needed to quickly create and launch a new PPi project.
Architecture fit — ppi/skeleton-app is not a library you depend on; it is a project template you fork. Adopting it means adopting the whole PPI stack: Zend Framework 2 components, Symfony 2 components, Doctrine ORM, Twig, and Assetic, wired together through a ZF2-style module system. There is no partial adoption path. It fits only if the target is an existing PPI application, or if the goal is to study a 2013-era modular PHP application structure. It does not fit a Laravel, Symfony 5+, or API-first codebase, and it cannot be dropped into one as a package. The 2.1.2 release does not alter this: it touches a skeleton module and a repository artifact, not the dependency graph, the runtime floor, or the framework versions.
Integration feasibility — Low. The supported entry point is composer create-project, which resolves a Composer 1-era dependency graph against packages that have since been abandoned or renamed (zendframework/* → laminas/*). Expect resolution failures on PHP 7.4+ and hard failure on PHP 8.x. Release 2.1.2 removes composer.lock from the repository, which makes this worse rather than better: upstream no longer ships a known-good resolution, so create-project will resolve against current (post-abandonment) Packagist state and is more likely to fail or drift than before. Reproducing the 2016 build therefore requires pinning Composer 1, pinning PHP 5.6/7.0, and generating and freezing your own lockfile as an artifact. That is achievable in a container but is archaeology, not integration. The scoring signal is unchanged and agrees: 1.86/5 overall with an opportunity score of 1.14 indicates the model sees no meaningful upside.
Technical risk — High, bordering on unacceptable for anything customer-facing:
composer.lock means there is no upstream reference resolution to fall back on, compounding the supply-chain exposure from abandoned Packagist entries that can be renamed or removed.Key questions
skeleton-app deployment that this assessment is meant to maintain, or is this greenfield evaluation?composer.lock removed upstream, where does our own frozen lockfile live, and is it mirrored internally before the next rebuild?Stack fit — No fit with a modern PHP stack (PHP 8.x, Composer 2, PSR-15 middleware, Laravel/Symfony 6+). The 2.1.2 removal of a PSR-7 reference in the skeleton module is a cleanup of a stale import, not a move toward PSR-7/PSR-15 interoperability; the request/response layer remains ZF2-shaped. Partial fit only where the organization already runs ZF2/Symfony 2 services and needs a compatible scaffold. Treat it as a reference implementation, not a dependency.
Migration path — Two viable strategies, and they diverge immediately:
vendor/, pin the PHP base image by digest, pin to the 2.1.2 tag explicitly (never track a branch, given the multi-year gaps), and begin a strangler-fig migration in parallel. Do not start new feature work in PPI.Compatibility — Verify explicitly before any commitment:
| Layer | Constraint to confirm |
|---|---|
| PHP | 5.6 / 7.0 required; confirm no 8.x compatibility |
| Composer | v1 required; 2.1.2 ships no lockfile, so you must author and version your own |
| Extensions | intl, mbstring, pdo_*, soap/ldap per legacy modules |
| Packages | zendframework/* abandonment; mirrored or vendored copies required |
| Assets | Assetic pipeline and its Java/node tooling dependencies |
| Skeleton module | 2.1.2 changed it; diff against your fork before merging to confirm no local module customization is clobbered |
Sequencing — If proceeding: (1) inventory existing PPI modules and business logic; (2) pin to tag 2.1.2 and build/prove reproducibility in a pinned container with our own committed lockfile; (3) isolate domain logic behind interfaces with tests; (4) stand up the replacement stack in parallel; (5) cut over module by module, retiring PPI last. Do not interleave new feature delivery with the migration, and do not treat the 2.1.2 skeleton change as an invitation to re-base an existing fork — diff first.
Maintenance — Internal ownership remains effectively 100%. The 2.1.2 release is a narrow, low-signal maintenance event: it did not refresh Symfony 2, ZF2, Doctrine, or Twig, so every CVE in those components is still unfixable without a manual backport. Track upstream releases opportunistically, but do not budget on them. Budget ongoing maintenance as a fixed tax, not a per-release cost, and expect it to grow as the runtime drifts further from current OS baselines.
Support — No vendor, no active maintainer, no community. Documentation is 2014-era and incomplete. Incident response depends entirely on institutional memory, so knowledge concentration in one or two engineers is a standing risk. A single 2.1.2 drop does not create a support channel.
Scaling — Horizontal scaling is technically possible because PHP-FPM is stateless, but you inherit the performance ceiling of Doctrine 2.x and PHP 5-era opcache behavior, with no modern profiling or observability integration out of the box. Autoscaling and container orchestration require custom health checks and logging shims.
Failure modes — Most likely failure is composer install breaking on dependency resolution or a yanked package during an unrelated rebuild; 2.1.2 increases this probability by removing the upstream lockfile, so any environment that previously leaned on it will now resolve differently. Next is an unpatched vulnerability in a framework component with no remediation path. Also plan for asset-pipeline breakage (Assetic), template injection risk if Twig templates are ever user-editable, silent drift between environments because builds are not reproducible, and merge conflicts if a local skeleton-module patch overlaps the 2.1.2 change.
Ramp-up — A senior PHP engineer needs roughly two to four weeks to become productive, most of it spent on archaeology rather than learning. Engineers with PPI experience are essentially unhirable, so every onboarding is a bespoke training exercise. This should be weighed as a recurring cost against the near-zero license cost of the package.
How can I help you explore Laravel packages today?