Clean-room copy of the reusable engines from comiida, with all instance data, secrets, dependencies, and build output excluded: - app/ Astro theme skeleton (no comiida blog posts; hero image -> placeholder) - api/ SeedProject PHP framework (no vendor/.env/config.php) - content-pipeline/ engine only (scripts/admin/prompts; empty runtime state) - astroagent.config.json + app/.astroagent/skills Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
128 lines
3.7 KiB
Markdown
128 lines
3.7 KiB
Markdown
# Core Framework — `core/`
|
|
|
|
Framework internals. **Rarely modified.** Contains the request lifecycle engine.
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `Bootstrap.php` | Bootstraps environment, loads config, starts routing |
|
|
| `Controller.php` | Base controller class — all UI controllers extend this (via `AppController`) |
|
|
| `View.php` | View renderer — handles `render()`, `PartialView()`, asset injection |
|
|
| `AltoRouter.php` | URL router used for complex custom routes |
|
|
|
|
---
|
|
|
|
## Request Lifecycle
|
|
|
|
```
|
|
Request
|
|
→ public/index.php
|
|
→ config.php (loads .env, defines constants)
|
|
→ core/Bootstrap.php (environment setup, session, autoload)
|
|
→ AltoRouter / auto-routing
|
|
→ ControllerClass::method($param)
|
|
→ $this->view->render(...)
|
|
→ Response (HTML or JSON)
|
|
```
|
|
|
|
Auto-routing maps `/controller/method/param` directly to `ControllerClass::method($param)`.
|
|
|
|
---
|
|
|
|
## `Controller` (`core/Controller.php`)
|
|
|
|
Base class. Provides:
|
|
|
|
- `$this->view` — View instance
|
|
- `$this->JavaScript[]` — array of JS paths to inject
|
|
- `$this->Styles[]` — array of CSS paths to inject
|
|
- `redirect($url)` — HTTP redirect helper
|
|
|
|
**Do not modify this file.** App-wide customisation belongs in `app/Controllers/AppController.php`.
|
|
|
|
---
|
|
|
|
## `AppController` (`app/Controllers/AppController.php`)
|
|
|
|
Sits between `core/Controller` and all UI page controllers.
|
|
UI controllers extend `AppController`, not `Controller` directly.
|
|
|
|
**Current responsibilities:**
|
|
- Injects `$UserProfile` (logged-in user's full profile via `User::profile()`) into every view automatically.
|
|
|
|
**`use` statement scoping rule:**
|
|
- Namespaces needed on every page → `AppController`
|
|
- Namespaces needed by one controller → that controller only
|
|
- Namespaces needed by one method → inline as fully-qualified class name
|
|
|
|
```php
|
|
// app/Controllers/AppController.php
|
|
use App\Components\User;
|
|
|
|
class AppController extends Controller {
|
|
function __construct() {
|
|
parent::__construct();
|
|
if (!empty($_SESSION['login']['userid'])) {
|
|
$this->view->UserProfile = User::profile($_SESSION['login']['userid']);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## `View` (`core/View.php`)
|
|
|
|
**Properties:**
|
|
- Any property set on `$this->view` becomes a variable in the rendered template.
|
|
|
|
**Methods:**
|
|
- `render($viewPath, $wrapper = '', $useWelcome = true)` — render a view
|
|
- `PartialView($partialName)` — load and return a partial as a string
|
|
|
|
**Render signatures used in practice:**
|
|
```php
|
|
$this->view->render(__CLASS__ . '/' . __FUNCTION__); // default admin wrapper
|
|
$this->view->render(__CLASS__ . '/' . __FUNCTION__, 'login'); // login wrapper
|
|
$this->view->render('clients/index', true, 'site'); // legacy style
|
|
```
|
|
|
|
---
|
|
|
|
## Routing
|
|
|
|
### Auto-Routing (default)
|
|
|
|
| URL | Maps to |
|
|
|-----|---------|
|
|
| `/clients` | `Clients::index()` |
|
|
| `/clients/show/123` | `Clients::show(123)` |
|
|
| `/products/edit/456` | `Products::edit(456)` |
|
|
|
|
### AltoRouter (complex routes)
|
|
|
|
Define in `public/routes.php` or `api/routes.php`:
|
|
|
|
```php
|
|
// Named route with typed parameter
|
|
$router->map('GET', '/users/[i:id]', 'Users#show', 'user_show');
|
|
|
|
// Multiple parameters
|
|
$router->map('GET', '/blog/[i:year]/[i:month]/[*:slug]', 'Blog#show', 'blog_post');
|
|
|
|
// POST
|
|
$router->map('POST', '/api/users/create', 'UsersAPI#create', 'api_user_create');
|
|
```
|
|
|
|
**Match type tokens:**
|
|
- `[i:id]` — integer
|
|
- `[a:action]` — alphanumeric (A-Z, a-z, 0-9, -)
|
|
- `[h:key]` — hex
|
|
- `[*:trailing]` — catch-all (no slashes)
|
|
- `[**:path]` — catch-all including slashes
|
|
|
|
```php
|
|
// Generate URL from named route
|
|
echo $router->generate('user_show', ['id' => 5]); // → /users/5
|
|
```
|