stougeiro / app
A small PHP 8.2 modular application foundation for shared hosting.
Fund package maintenance!
Requires
- php: >=8.2
- ext-pdo: *
- ext-pdo_sqlite: *
- stougeiro/base: ^0.5.0
- stougeiro/base-contract: ^0.1.1
- stougeiro/cache: ^2.0
- stougeiro/container: ^4.0
- stougeiro/event: ^1.0
- stougeiro/http: ^2.2
- stougeiro/pdo-database: ^1.0
- stougeiro/router: ^1.0
- stougeiro/session: ^2.0
- stougeiro/support: ^2.0
- stougeiro/view: ^2.0
Requires (Dev)
- pestphp/pest: ^3.8
- phpstan/phpstan: ^2.2
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-10 02:15:43 UTC
README
App
A small PHP 8.2 application foundation for shared hosting.
The application runs on Apache with PHP-FPM or mod_php and follows the
shared-hosting layout: the application lives outside the public directory, while
public contains only the front controller, .htaccess and public
assets.
It is built on stougeiro/base, stougeiro/base-contract, stougeiro/router,
stougeiro/http, stougeiro/view, stougeiro/cache, stougeiro/session,
stougeiro/event and stougeiro/pdo-database.
The goal is an explicit, inspectable application with no hidden module discovery, no build step required at runtime, and behavior that is predictable on ordinary shared servers.
Reference
- Architecture: boundaries, dependency direction and where each kind of code belongs.
- Code tool: deployment configuration, commands and operations.
- Schema tool: structural database state versioning.
- AGENTS: operational rules for agents and contributors.
Features
- Shared-hosting layout: application in
application/, web root inpublic/. - Explicit wiring: providers and modules are registered in application/config/app.php.
- Module example: HelloWorld controller, view and middlewares.
- Error handling: separate development and production error pages.
- Log separation: application errors, security events and PHP errors are written to different files.
- Daily logs: application logs use
YYYYMMDDfile suffixes. - Services: cache, view, session, events, routing, database and logging are registered explicitly.
- Security primitives: optional CSRF, rate limit and security headers
middleware under
application/core/Security. - Docker development: PHP 8.2 + Apache with the vendor directory kept inside the image.
- Code tool: repeatable SSH deploys with per-target layout, overrides, maintenance mode, automatic backups and rollback.
- Schema tool: structural database state versioning for SQLite, with immutable releases and SQL artifacts.
- Quality tooling: PHPStan Level 9 and a Pest suite.
Requirements
- PHP 8.2 or newer.
ext-json.ext-pdo_sqlitefor the default database configuration.- Apache with
mod_rewritefor the front controller. - A writable application/storage directory.
Installation
git clone https://github.com/stougeiro/app.git
cd app
composer install
cp application/env-example.json application/env.json
For production dependencies, generate the vendor externally:
composer install --no-dev --optimize-autoloader
Layout
.
├── application/
│ ├── bootstrap/ runtime bootstrap
│ ├── config/ application configuration
│ ├── core/ app-level foundations
│ ├── database/ database-facing code
│ ├── module/ application modules
│ ├── provider/ service providers
│ └── storage/ cache, logs, sessions, uploads and temporary files
├── docs/ architecture, Code and Schema reference
├── tests/ Pest tests
├── tools/
│ ├── contract/ shared tool contracts
│ ├── manager/ CLI runtime, registry and Dockerfile
│ ├── code/ Code tool source and example
│ ├── schema/ Schema tool source and example
│ └── support/ shared tool support
├── .sourcerer/ local tool control, configs and secrets (not versioned)
├── schema/ versioned Schema state (database structure)
├── public/ document root
├── vendor/ Composer dependencies
├── sourcerer unified tool entrypoint
├── composer.json
└── composer.lock
The application must never be exposed through the web server. The document root is public.
Configuration
Environment:
{
"environment": "development"
}
Use production on a deployed server.
Providers and modules are declared explicitly in application/config/app.php:
return [ 'providers' => [ // ... ], 'modules' => [ // ... ], ];
The default database configuration uses SQLite in application/storage.
Logging
Logs are written under application/storage/log. Files are separated by purpose and date:
error-YYYYMMDD.log
security-YYYYMMDD.log
php-error-YYYYMMDD.log
error-*: application 5xx errors;security-*: request 4xx events such as 404 and 405;php-error-*: PHP-level errors and the final fallback.
The php-error daily path is configured on a best-effort basis. If the hosting
environment blocks ini_set, the application keeps running and the host/PHP
configuration remains in use. See
application/core/Log/PhpErrorLog.php.
Log retention is an operational concern and is not implemented by the application.
Docker development
Docker is a development convenience, not a production requirement.
# from the repository root
composer install
docker compose up -d
Open http://localhost/.
The development container uses PHP 8.2 + Apache, serves public as the document
root, keeps vendor/ inside the image and bind-mounts application/ for
real-time code and log inspection. Apache access and error logs are also written
under application/storage/log.
Tool setup
Configure the shared operator and install the local control layout:
./sourcerer operator --name="Developer" --email="developer@example.com" ./sourcerer install
This creates .sourcerer/operator.json, .sourcerer/code/ and
.sourcerer/schema/. All tool commands require the operator.
Code tool
The repository includes an optional Code tool for repeatable SSH deployments.
It runs through the unified ./sourcerer entrypoint, requires Docker locally and
keeps the application runtime independent from deployment concerns.
./sourcerer code check --target=staging ./sourcerer code push --target=staging ./sourcerer code promote --from=staging ./sourcerer code releases ./sourcerer code rollback --target=staging --list
Targets are declared in .sourcerer/code/config.json, with separate root and
webroot paths, per-target overrides, maintenance mode, remote backups and
rollback. Remote .deploy/ remains the deployment state on the server.
See docs/CODE.md for configuration, commands and operational details.
Schema tool
The Schema tool versions database structure without creating control tables in the database.
./sourcerer schema init ./sourcerer schema status ./sourcerer schema status --target=local
Configuration lives in .sourcerer/schema/config.json; local scratch data lives
in .sourcerer/schema/local. Versioned structural state lives in schema/.
It captures Genesis, maintains immutable releases, and will generate
release.sql and migration.sql artifacts. Triggers, procedures and functions
are deliberately unsupported.
See docs/SCHEMA.md for configuration and the complete model.
Shared hosting
The production deployment is a normal PHP application. Docker is not required. The manual upload flow below remains valid when the Code tool is not used.
application/ -> application directory outside the web root
public/ -> contents go to the document root (often public_html)
vendor/ -> Composer dependencies outside the web root
Steps:
- install dependencies externally with
--no-dev; - upload
application/,public/andvendor/to the server; - create
application/env.json; - make
application/storagewritable by the application user; - point the document root to the uploaded
publiccontents (oftenpublic_html).
On shared hosting, Apache access/error logs and HTTP-level rate limiting usually
belong to the provider. Application logs remain under application/storage/log.
Development
From the repository root:
composer validate --strict composer stan composer pest composer cover:app composer cover:code composer cover:schema
Run the suite as a non-root user. The permission tests exercise real filesystem behavior and must not be skipped.
The test suite covers the application bootstrap, module rendering, error pages, log classification, daily PHP error log configuration, security primitives, maintenance/fallback entrypoint behavior, the Code tool and the Schema tool.
Tool coverage is measured separately so the application coverage scope stays unchanged.
Why?
Shared hosting is heterogeneous and constrained. The application is designed around those limits:
- no long-running workers or persistent application state;
- the web root is a fixed public directory;
- dependencies are resolved before deployment;
- modules and providers are explicit and easy to inspect;
- error handling and logs remain useful without requiring platform-specific infrastructure.
Contracts live in stougeiro/base-contract; the FPM runtime lives in
stougeiro/base; this repository shows how the application wires both together.
Contributions
Contributions are welcome. Feel free to open issues or submit pull requests.