Architecture
OwnWork is a small PHP application framework built around an HTTP request pipeline.
OwnWork provides the application bootstrap, HTTP kernel, route registration, middleware orchestration, application structure, helpers, view workflow, and development tooling.
Some lower-level HTTP, routing, view, environment, and error-handling functionality is provided by the dhruv125/coretex package.
The architecture is therefore best understood as two cooperating layers:
OwnWork
│
├── Application bootstrap
├── HTTP Kernel
├── Application structure
├── Middleware orchestration
├── Helpers
├── Worker CLI
└── Coretex integration
│
▼
Coretex
├── Request
├── Response
├── Route
├── RouteResolver
├── View
├── Environment
└── Error handlingHigh-Level Request Architecture
A request moves through the application approximately as follows:
HTTP Request
│
▼
public/index.php
│
▼
Bundler
│
├── Composer autoloader
├── Environment
└── Global error handler
│
▼
Http\Kernel
│
├── Request
├── Response
├── Route
└── RouteResolver
│
▼
bundle/Routes.php
│
▼
Route Matching
│
├── Dynamic parameters
└── Route middleware
│
▼
Global Middleware
│
▼
Route Middleware
│
▼
RouteResolver
│
├── Callable
├── View
└── Controller
│
▼
Response
│
▼
HTTP Output The application entry point is intentionally small. Bundler handles application initialization, while Kernel coordinates request processing. The actual HTTP request, response, routing, and route resolution classes used by the kernel come from Coretex.
Application Entry Point
The public entry point is:
public/index.phpIts current implementation is:
<?php
declare(strict_types = 1);
ob_start();
use Bundle\Bundler;
require __DIR__ . "/../bundle/Bundler.php";
$app = new Bundler();
$app->bundle();
ob_end_flush(); public/index.php loads bundle/Bundler.php, creates the Bundler, and starts the application by calling bundle().
The output buffer is started before application execution and flushed after the application finishes.
You normally do not need to modify public/index.php.
Bundler
The bundler is located at:
bundle/Bundler.php Bundler is responsible for initializing the application before the HTTP kernel starts.
Its constructor:
- Checks that
.envexists. - Checks that
vendor/autoload.phpexists. - Loads Composer's autoloader.
- Creates Coretex's
Environment. - Loads the root
.envconfiguration. - Creates Coretex's
GlobalErrorHandler. - Stores the resulting error-level configuration for the handler.
Its bundle() method then creates the OwnWork Kernel and calls handle().
Conceptually:
Bundler
│
├── Check .env
├── Check Composer autoloader
├── Load Composer
├── Load environment
├── Initialize error handler
└── Start Kernel Bundler does not register individual routes or execute controllers itself.
If the required .env or Composer autoloader is missing, Bundler stops the application and displays the setup error page when the corresponding error view exists.
HTTP Kernel
The application kernel is located at:
app/Http/Kernel.phpThe kernel coordinates request processing.
It creates:
- Coretex
Request - Coretex
Response - Coretex
Route - Coretex
RouteResolver - Coretex
Pager
The relevant classes are imported directly from:
Dhruv125\CoretexThe kernel then loads:
bundle/Routes.phpusing the application's root path.
After the routes are registered, it calls the route object's end() method to determine whether the current HTTP request matches a registered route.
Route Registration and Matching
Routing itself is implemented by Coretex's Route class.
OwnWork creates the route object in the kernel and exposes it to:
bundle/Routes.phpApplications register routes such as:
<?php
$route->get("/", "home.temp.php");or:
<?php
$route->get("/users", [
UserController::class,
"index"
]);Coretex currently supports these HTTP methods:
GET
POST
PUT
PATCH
DELETERoute matching is performed against the request URL and HTTP method. Routes are checked in their registered order for the current method.
Dynamic parameters use {name} syntax:
<?php
$route->get("/users/{id}", [
UserController::class,
"show"
]);For a request such as:
/users/42the route matcher produces:
id = 42The kernel stores the resulting parameters on the request as:
dynamicParamsIt also stores the matched route as:
currentRouteand the registered route list as:
routesArrayThese are request attributes available to application code.
Route Resolver
After route matching and middleware execution, the kernel passes the selected handler to Coretex's RouteResolver.
The resolver supports three main handler forms.
Callable Handler
A route can use a callable:
<?php
$route->get("/hello", function () {
return "Hello from OwnWork";
});The resolver invokes the callable directly.
When dynamic route parameters are present, the resolver uses the callable's parameter count to pass matching dynamic values to it.
View Handler
A string handler is treated as a view name:
<?php
$route->get("/", "home.temp.php");The Coretex resolver passes the view name to its view system.
Controller Handler
A controller action can be registered as:
<?php
$route->get("/users", [
UserController::class,
"index"
]);The resolver creates an instance of the controller and calls the specified method with:
Request
Response
Route parameters If only the controller class is supplied, the resolver falls back to an index method when that method exists.
This means controller classes do not need to extend a framework-provided base controller.
Middleware
Middleware is executed between route matching and route resolution.
OwnWork's kernel builds the middleware chain and executes it recursively.
A middleware receives the request and response objects followed by a $next callable:
<?php
function (
Request $request,
Response $response,
callable $next
) {
return $next();
}A middleware can:
- inspect the request
- modify processing
- return a response without continuing
- call
$next()to continue to the next middleware
The effective processing order is:
Request
│
▼
Global Middleware
│
▼
Route Middleware
│
▼
Route Handler
│
▼
ResponseThe kernel collects middleware attached to the matched route and then prepends global middleware before executing the complete chain.
Coretex supports registering middleware against individual routes or groups of routes, as well as global middleware.
Controllers
Controllers normally live under:
app/Controller/A controller is an application class. OwnWork does not require controllers to extend a framework base class.
A typical controller action receives:
<?php
public function index(
Request $request,
Response $response
) {
return "Hello";
}The request and response classes are provided by Coretex.
When a route contains dynamic parameters, the route resolver also passes the parameter array as the third argument:
<?php
public function show(
Request $request,
Response $response,
array $params
) {
return "User: " . $params["id"];
}Controllers are therefore responsible for application-specific request handling rather than framework configuration.
Models
Models belong under:
app/Model/This directory is part of OwnWork's application structure.
OwnWork does not define a model base class or impose an ORM on model classes.
The bundled helper contains an optional get_db_instance() function that can create a database instance when the optional delight-im/db package is installed and the corresponding DB_* environment variables are configured.
Applications can also implement their own data-access layer or use another database package.
Therefore, app/Model/ is an application convention rather than a required OwnWork ORM layer.
Services
Services normally belong under:
app/Service/A service is an application-level class that can contain reusable operations or business logic.
For example:
Controller
│
▼
Service
│
├── Model
├── Database
└── External APIOwnWork does not define a service base class or require a particular service interface.
The app/Service/ directory is an application organization convention supported by the worker's service generator.
Views
View source files normally live under:
resources/views/ OwnWork's view workflow uses .temp.php files as template source.
For example:
resources/views/home.temp.phpThe worker transpiles these templates into generated PHP files under:
storage/views/and maintains the compiled-view mapping in:
storage/views.jsonThe template language is implemented by Coretex's template system.
OwnWork therefore separates:
resources/views/
│
│ source templates
▼
transpilation
│
▼
storage/views/
│
│ generated PHP
▼
output Generated files in storage/views/ are build output and should not be edited as the source of a view.
Helpers
OwnWork's predefined helper functions are located in:
bundle/Helper.phpThe helper file provides functions including:
<?php
approot();<?php
env("APP_NAME");<?php
view("home.temp.php");<?php
comp("button.php");<?php
out($value); It also provides additional helpers such as getTempTranspiled(), url(), pre(), get_db_instance(), clean(), isArrElemEmpty(), separateEmptyElements(), printArr(), and isUrl().
For example, view() delegates to Coretex's View::instantView(), while getTempTranspiled() delegates to Coretex's View::includeTemp().
The helper layer is therefore an OwnWork convenience layer around application and Coretex functionality.
Worker
The worker script provides OwnWork's command-line development and code-generation functionality.
It can:
- start the development server
- generate controllers
- generate middleware
- generate models
- generate services
- generate views
- transpile templates
- clear generated view files
For example:
php worker make controller UserControllerGenerated application components use templates stored under:
resources/template/The worker is also responsible for the development view-transpilation workflow.
Coretex Dependency
OwnWork depends on:
dhruv125/coretexCoretex currently provides several lower-level pieces used directly by OwnWork.
HTTP
OwnWork's kernel uses Coretex:
Dhruv125\Coretex\Support\Request
Dhruv125\Coretex\Support\ResponseRouting
OwnWork's kernel uses:
Dhruv125\Coretex\Router\Route
Dhruv125\Coretex\Router\RouteResolverView System
OwnWork's helper layer delegates view operations to:
Dhruv125\Coretex\Viewer\ViewEnvironment
OwnWork's Bundler creates:
Dhruv125\Coretex\Environment\Environment to load the application's .env configuration.
Error Handling
OwnWork's Bundler creates:
Dhruv125\Coretex\Handler\GlobalErrorHandlerfor global PHP error and exception handling.
This distinction is important:
OwnWork integrates these Coretex components into its application lifecycle; they are not all implemented inside the OwnWork repository itself.
When investigating framework behavior, check the OwnWork source first for application-specific orchestration, then check Coretex when the relevant class is imported from Dhruv125\Coretex.
OwnWork and Coretex Responsibilities
The separation can be summarized as:
| Responsibility | OwnWork | Coretex |
|---|---|---|
| Application entry point | ✓ | |
| Bundler | ✓ | |
| HTTP Kernel | ✓ | |
| Application directory conventions | ✓ | |
| Worker CLI | ✓ | |
| Application helpers | ✓ | |
| Request object | ✓ | |
| Response object | ✓ | |
| Route registration/matching | ✓ | |
| Route resolution | ✓ | |
| View implementation | ✓ | |
| Environment loading | ✓ | |
| Global error handler | ✓ |
This separation is important when reading the source or debugging behavior.
Application Responsibilities
OwnWork intentionally leaves much of the application-specific behavior to the developer.
A typical application can organize responsibilities like this:
| Layer | Responsibility |
|---|---|
public/ |
HTTP entry point and public files |
bundle/ |
Bootstrap, routes, and helpers |
app/Http/ |
OwnWork HTTP kernel |
app/Controller/ |
Application request handling |
app/Middleware/ |
Request pipeline behavior |
app/Model/ |
Application data layer |
app/Service/ |
Reusable application logic |
resources/views/ |
View source templates |
resources/template/ |
Worker generation templates |
storage/views/ |
Generated view output |
The framework provides the application plumbing while application code defines the application's behavior.
Request Lifecycle Summary
The complete lifecycle can be summarized as:
HTTP Request
│
▼
public/index.php
│
▼
Bundler
│
├── Load Composer
├── Load .env through Coretex
└── Initialize Coretex error handler
│
▼
Kernel
│
├── Create Request
├── Create Response
├── Create Route
└── Create RouteResolver
│
▼
bundle/Routes.php
│
▼
Route::end()
│
├── Match HTTP method
├── Match URL
└── Extract dynamic parameters
│
▼
Middleware Pipeline
│
├── Global middleware
└── Route middleware
│
▼
RouteResolver
│
├── Callable
├── View
└── Controller
│
▼
Response
│
▼
HTTP OutputThe key architectural boundary is that OwnWork controls the application lifecycle and orchestration, while Coretex supplies several of the lower-level HTTP framework primitives.
fundamentals/project-structure.md