Phred/SPECS.md

6.4 KiB

Phred Technical Specifications

← Back to README | MILESTONES.md

Table of Contents

This document outlines the technical specifications and architectural standards of the Phred framework.

1. Core Framework

1.1 API Formats and Content Negotiation

Phred supports two primary API formats:

  • Pragmatic REST (default): Plain JSON responses using RFC 7807 for error handling.
  • JSON:API: Compliant with the JSON:API specification for documents and error objects.

Negotiation can be set globally via .env:

  • API_FORMAT=rest
  • API_FORMAT=jsonapi

Clients can override the format per request using the Accept header:

  • Accept: application/vnd.api+json forces JSON:API.
  • Accept: application/xml or text/xml (M12+).

1.2 Pluggability Model (M5)

The framework is fully pluggable. Core components depend on Phred contracts and PSRs; concrete implementations are provided by Service Providers.

  • Providers implement Phred\Support\Contracts\ServiceProviderInterface.
  • Lifecycle methods: register(ContainerBuilder) and boot(Container).
  • Loading order: Core → App → Modules (defined in config/providers.php).

Primary Contracts:

  • Template\Contracts\RendererInterface
  • Orm\Contracts\ConnectionInterface
  • Flags\Contracts\FeatureFlagClientInterface
  • Testing\Contracts\TestRunnerInterface

1.3 URL Extension Negotiation

Optional middleware that hints content negotiation based on URL suffix.

  • Enabled via URL_EXTENSION_NEGOTIATION=true (default).
  • Whitelist via URL_EXTENSION_WHITELIST (default: "json|xml|php|none").
  • Mappings:
    • .jsonapplication/json
    • .xmlapplication/xml
    • .php or none → text/html (View convention)

1.4 Dependencies

Phred leverages several industry-standard packages:

  • Dependency Injection: php-di/php-di
  • Static Analysis: phpstan/phpstan
  • Code Style: friendsofphp/php-cs-fixer
  • Logging: monolog/monolog
  • Environment: vlucas/phpdotenv
  • HTTP Client: guzzlehttp/guzzle
  • CORS: middlewares/cors
  • Authentication: lcobucci/jwt
  • Feature Flags: getphred/flagpole
  • ORM: getphred/pairity
  • Template Engine: getphred/eyrie
  • Router: nikic/fast-route
  • PSR-7/15: relay/relay, nyholm/psr7

2. MVC Components

2.1 Controllers

  • Invokable: Controllers are "Actions" with a single entry point: public function __invoke(Request $request).
  • Response Factories: Injected via Phred\Http\Contracts\ApiResponseFactoryInterface.
  • Base Classes (M6):
    • Phred\Mvc\APIController: For API-only endpoints.
    • Phred\Mvc\ViewController: For HTML/Template endpoints.

2.2 Views (M6)

  • Classes dedicated to data preparation before rendering.
  • Extend Phred\Mvc\View.
  • Methods:
    • transformData(array $data): Manipulate data before it hits the template.
    • defaultTemplate(): Define the default template for the view.
  • Conventions: Controllers call renderView($view, $data, ?$templateOverride). If no override is provided, the View decides the template.

2.3 Services

  • Business logic should reside in Service classes to keep controllers lean and models ORM-neutral.

3. Modular Architecture (M7)

Phred follows a Django-style modular structure where all user code lives inside modules.

3.1 Module Layout (ORM-Agnostic)

  • modules/<Module>/Controllers/
  • modules/<Module>/Views/
  • modules/<Module>/Templates/
  • modules/<Module>/Services/
  • modules/<Module>/Models/ (Domain models, pure PHP)
  • modules/<Module>/Repositories/ (Interfaces consumed by services)
  • modules/<Module>/Persistence/Pairity/ (Driver-specific implementations)
  • modules/<Module>/Persistence/Eloquent/ (Driver-specific implementations)
  • modules/<Module>/Database/Migrations/ (Canonical migrations)
  • modules/<Module>/Routes/web.php and api.php
  • modules/<Module>/Providers/*ServiceProvider.php

3.2 Modular Separation

Modules encapsulate their own:

  • Models, Controllers, Views, Services, Migrations, Providers, Routes, Templates, and Tests.

4. Infrastructure

4.1 Service Providers (M5)

Providers are the glue of the framework.

  • Configuration: config/providers.php
  • Route Registration: Use RouteRegistry::add(static function($collector, $router) { ... }).

4.2 Configuration and Environment

  • Dotenv: Loads .env from the project root.
  • Config Facade: Phred\Support\Config::get(<key>, <default>).
  • Precedence: Environment variables > Config files (config/*.php) > Defaults.
  • Notation: Supports both UPPER_SNAKE and dot.notation.

4.3 Command Discovery

  • Core Commands: Discovered from src/commands.
  • User Commands: Discovered from console/commands.
  • Custom commands must return an instance of Phred\Console\Command.

5. Technical Examples

5.1 Configuration Access

use Phred\Support\Config;

$env = Config::get('APP_ENV', 'local');      // environment check
$tz  = Config::get('app.timezone', 'UTC');   // dotted notation from config/app.php

5.2 API Negotiation

The chosen format is stored on the request as phred.api_format and used by the ApiResponseFactoryInterface to determine the response shape.

5.3 Route Group Inclusion

use Phred\Http\Routing\RouteGroups;
use Phred\Http\Router;

RouteGroups::include($router, '/prefix', function (Router $router) {
    require __DIR__ . '/../path/to/routes.php';
});