|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Language |
| 6 | + |
| 7 | +All commit messages, PR titles, PR descriptions, code comments, and documentation must be written in English. |
| 8 | + |
| 9 | +## Code Style |
| 10 | + |
| 11 | +### Imports |
| 12 | +- Always import classes with `use` statements. Never use fully qualified class names (FQCN) inline. |
| 13 | +- Order: PHP built-in → Ouzo framework → third-party. |
| 14 | + |
| 15 | +### Types |
| 16 | +- Always declare parameter types and return types. |
| 17 | +- Fluent methods return `static` (not `self`). |
| 18 | +- Use `is_null()` instead of `=== null`. |
| 19 | + |
| 20 | +### Strings & Arrays |
| 21 | +- Single quotes by default: `'value'`. |
| 22 | +- Double quotes only for interpolation: `"prefix_{$var}"`. |
| 23 | +- Always `[]` for arrays, never `array()`. |
| 24 | + |
| 25 | +### Docblocks |
| 26 | +- Only when types cannot be expressed in code or behavior needs explanation. |
| 27 | +- Do not add `@param`/`@return` when method signatures are sufficient. |
| 28 | + |
| 29 | +### Copyright header (every file) |
| 30 | +```php |
| 31 | +<?php |
| 32 | +/* |
| 33 | + * Copyright (c) Ouzo contributors, https://github.com/letsdrink/ouzo |
| 34 | + * This file is made available under the MIT License (view the LICENSE file for more information). |
| 35 | + */ |
| 36 | +``` |
| 37 | + |
| 38 | +### Classes |
| 39 | +- `final` only on classes with constants only (e.g. `HttpMethod`, `HttpStatus`). |
| 40 | +- `readonly class` for immutable value objects. |
| 41 | +- No leading underscore on private methods. |
| 42 | +- Keep methods short (3-20 lines), extract longer logic into private helpers. |
| 43 | + |
| 44 | +### Error Handling |
| 45 | +- Throw exceptions immediately with readable messages, no error codes. |
| 46 | +- Never suppress or silently handle errors. |
| 47 | + |
| 48 | +## What is Ouzo |
| 49 | + |
| 50 | +Ouzo is a PHP MVC framework with built-in ORM, dependency injection, and utility libraries. Requires PHP 8.4+. |
| 51 | + |
| 52 | +## Build & Test Commands |
| 53 | + |
| 54 | +```bash |
| 55 | +# Install dependencies |
| 56 | +composer install |
| 57 | + |
| 58 | +# Run all tests (defaults to PostgreSQL, excludes sqlite3 group) |
| 59 | +./vendor/bin/phpunit test |
| 60 | + |
| 61 | +# Run tests against a specific database |
| 62 | +db=mysql ./vendor/bin/phpunit --exclude-group postgres,sqlite3 test |
| 63 | +db=postgres ./vendor/bin/phpunit --exclude-group mysql,sqlite3 test |
| 64 | +db=sqlite3 ./vendor/bin/phpunit --exclude-group mysql,postgres,non-sqlite3 test |
| 65 | + |
| 66 | +# Run a single test file |
| 67 | +./vendor/bin/phpunit test/src/Ouzo/Core/Db/ModelQueryBuilderTest.php |
| 68 | + |
| 69 | +# Run a single test method |
| 70 | +./vendor/bin/phpunit --filter testMethodName test/src/Ouzo/Core/Db/ModelQueryBuilderTest.php |
| 71 | +``` |
| 72 | + |
| 73 | +Test databases must be seeded before first run using SQL scripts in `test/test-db/`. |
| 74 | + |
| 75 | +## Architecture |
| 76 | + |
| 77 | +The `Ouzo\` namespace maps to four source modules via PSR-4: |
| 78 | + |
| 79 | +- **`src/Ouzo/Core`** — MVC framework: routing, controllers, views, ORM (Active Record), database layer, config, sessions, middleware, i18n |
| 80 | +- **`src/Ouzo/Goodies`** — Standalone utility library: `Arrays`, `Strings`, `Functions`, `Clock`, `FluentArray`, `Optional`, `Json`, `Objects`, validators, iterators. Also provides test helpers (`Assert`, `CatchException`, `Mock`) |
| 81 | +- **`src/Ouzo/Inject`** — Dependency injection container using PHP 8 attributes (`#[Inject]`, `#[Named]`) |
| 82 | +- **`src/Ouzo/Migrations`** — Database migration system |
| 83 | + |
| 84 | +Goodies and Inject are also published as standalone packages (`letsdrink/ouzo-goodies`, `letsdrink/ouzo-inject`). |
| 85 | + |
| 86 | +### Request lifecycle |
| 87 | + |
| 88 | +`Bootstrap` → `FrontController` → middleware chain (`SessionStarter` → `DefaultRequestId` → `LogRequest` → custom) → `RequestExecutor` resolves route → controller action → `View` renders response. |
| 89 | + |
| 90 | +### ORM |
| 91 | + |
| 92 | +`Model` extends `Validatable`, uses Active Record pattern. Relations: `belongsTo`, `hasOne`, `hasMany`. Query building via `ModelQueryBuilder` with fluent API. Database dialects: `MySqlDialect`, `PostgresDialect`, `Sqlite3Dialect`. |
| 93 | + |
| 94 | +### Routing |
| 95 | + |
| 96 | +Static API on `Route`: `get()`, `post()`, `put()`, `delete()`, `resource()`, `group()`. Annotation-based routing also supported. |
| 97 | + |
| 98 | +## Testing Conventions |
| 99 | + |
| 100 | +- `#[Test]` attribute, not `test` prefix in method names |
| 101 | +- Method names: `shouldDoSomething()` pattern |
| 102 | +- Test structure: `//given`, `//when`, `//then` comments |
| 103 | +- `#[DataProvider('name')]` attribute, not `@dataProvider` annotation |
| 104 | +- `#[Group('mysql')]`, `#[Group('postgres')]`, `#[Group('sqlite3')]`, `#[Group('non-sqlite3')]` for DB-specific tests |
| 105 | +- Base classes: |
| 106 | + - `DbTransactionalTestCase` — wraps each test in a transaction that rolls back |
| 107 | + - `ControllerTestCase` — HTTP testing with request/response mocking |
| 108 | +- Custom fluent assertions via `Ouzo\Tests\Assert`: |
| 109 | + - `Assert::thatArray($arr)->hasSize(3)->contains('x')` |
| 110 | + - `Assert::thatString($s)->startsWith('foo')` |
| 111 | + - `Assert::thatModel($m)->hasSameAttributesAs($expected)` |
| 112 | +- `CatchException::when($obj)->method()` + `CatchException::assertThat()->isInstanceOf(...)` for exception testing |
| 113 | +- Custom mock framework in `Ouzo\Tests\Mock\Mock` |
| 114 | + |
| 115 | +## Key Directories |
| 116 | + |
| 117 | +- `bin/` — CLI commands (Symfony Console): model/controller/migration generators, route listing |
| 118 | +- `config/test/` — Test environment config (DB connection selected by `db` env var) |
| 119 | +- `test/Application/` — Fixture models and controllers used by tests |
| 120 | +- `test/test-db/` — SQL schema scripts for each database engine |
| 121 | +- `console` — CLI entry point script |
0 commit comments