@@ -53,8 +53,10 @@ The `src/` folder is where you'll do most development. Here's what goes in each
5353| ** Command** | Console commands | ` *Command.php ` - See [ Command Objects] ( ../console-commands/commands ) |
5454| ** Console** | Installation scripts | Executed by Composer |
5555| ** Controller** | HTTP request handlers | [ Controllers] ( ../controllers ) , [ Components] ( ../controllers/components ) |
56+ | ** Form** | Non-ORM form objects | ` *Form.php ` - See [ Form] ( ../core-libraries/form ) |
57+ | ** Mailer** | Email sending classes | ` *Mailer.php ` - See [ Email] ( ../core-libraries/email ) |
5658| ** Middleware** | Request/response filters | ` *Middleware.php ` - See [ Middleware] ( ../controllers/middleware ) |
57- | ** Model** | Data layer | [ Tables] ( ../orm/table-objects ) , [ Entities] ( ../orm/entities ) , [ Behaviors] ( ../orm/behaviors ) |
59+ | ** Model** | Data layer | [ Tables] ( ../orm/table-objects ) , [ Entities] ( ../orm/entities ) , [ Behaviors] ( ../orm/behaviors ) , [ Enums ] ( ../orm/database-basics#enum-type ) |
5860| ** View** | Presentation logic | [ Views] ( ../views ) , [ Cells] ( ../views/cells ) , [ Helpers] ( ../views/helpers ) |
5961
6062> [ !NOTE]
@@ -146,6 +148,18 @@ class User extends Entity
146148}
147149```
148150
151+ ``` php [✅ Enum Class]
152+ // File: src/Model/Enum/ArticleStatus.php
153+ namespace App\Model\Enum;
154+
155+ enum ArticleStatus: string
156+ {
157+ case Draft = 'draft';
158+ case Published = 'published';
159+ case Archived = 'archived';
160+ }
161+ ```
162+
149163:::
150164
151165** Rules:**
@@ -154,7 +168,7 @@ class User extends Entity
154168 - ` UsersTable ` , ` MenuLinksTable ` , ` UserFavoritePagesTable `
155169- ** Entity class:** Singular, CamelCased, no suffix
156170 - ` User ` , ` MenuLink ` , ` UserFavoritePage `
157- - ** Enum class:** ` {Entity}{Column} ` - e.g., ` UserStatus ` , ` OrderState `
171+ - ** Enum class:** ` {Entity}{Column} ` in ` src/Model/Enum/ ` - e.g., ` ArticleStatus ` , ` UserRole `
158172- ** Behavior class:** Ends in ` Behavior ` - ` TimestampBehavior `
159173
160174### Views & Templates
@@ -227,7 +241,7 @@ CREATE TABLE tags_articles;
227241
228242- ** Table names:** Plural, underscored - ` users ` , ` menu_links `
229243- ** Multiple words:** Only pluralize the last word - ` user_favorite_pages ` (not ` users_favorites_pages ` )
230- - ** Columns:** Underscored - ` first_name ` , ` created_at `
244+ - ** Columns:** Underscored - ` first_name ` , ` is_processed `
231245- ** Foreign keys:** ` {singular_table}_id ` - ` user_id ` , ` menu_link_id `
232246- ** Junction tables:** Alphabetically sorted plurals - ` articles_tags ` (not ` tags_articles ` )
233247
@@ -282,10 +296,13 @@ All files follow **PSR-4 autoloading** - filenames must match class names exactl
282296| Component | ` MyHandyComponent ` | ` MyHandyComponent.php ` | ` src/Controller/Component/ ` |
283297| Table | ` OptionValuesTable ` | ` OptionValuesTable.php ` | ` src/Model/Table/ ` |
284298| Entity | ` OptionValue ` | ` OptionValue.php ` | ` src/Model/Entity/ ` |
299+ | Enum | ` ArticleStatus ` | ` ArticleStatus.php ` | ` src/Model/Enum/ ` |
285300| Behavior | ` EspeciallyFunkableBehavior ` | ` EspeciallyFunkableBehavior.php ` | ` src/Model/Behavior/ ` |
286301| View | ` SuperSimpleView ` | ` SuperSimpleView.php ` | ` src/View/ ` |
287302| Helper | ` BestEverHelper ` | ` BestEverHelper.php ` | ` src/View/Helper/ ` |
288303| Command | ` UpdateCacheCommand ` | ` UpdateCacheCommand.php ` | ` src/Command/ ` |
304+ | Mailer | ` UserMailer ` | ` UserMailer.php ` | ` src/Mailer/ ` |
305+ | Form | ` ContactForm ` | ` ContactForm.php ` | ` src/Form/ ` |
289306
290307## Complete Example: Articles Feature
291308
@@ -299,6 +316,7 @@ CREATE TABLE articles (
299316 user_id INT ,
300317 title VARCHAR (255 ),
301318 body TEXT ,
319+ status VARCHAR (20 ), -- backed by App\Model\Enum\ArticleStatus
302320 created DATETIME,
303321 modified DATETIME
304322);
@@ -319,8 +337,10 @@ src/
319337├── Model/
320338│ ├── Table/
321339│ │ └── ArticlesTable.php → class ArticlesTable
322- │ └── Entity/
323- │ └── Article.php → class Article
340+ │ ├── Entity/
341+ │ │ └── Article.php → class Article
342+ │ └── Enum/
343+ │ └── ArticleStatus.php → enum ArticleStatus
324344templates/
325345└── Articles/
326346 ├── index.php → ArticlesController::index()
@@ -346,6 +366,7 @@ URL: `https://example.com/articles/view/5`
346366| ** Database Table** | ` articles ` | ` menu_links ` | Plural, underscored |
347367| ** Table Class** | ` ArticlesTable ` | ` MenuLinksTable ` | Plural, CamelCased, ends in ` Table ` |
348368| ** Entity Class** | ` Article ` | ` MenuLink ` | Singular, CamelCased |
369+ | ** Enum Class** | ` ArticleStatus ` | ` MenuLinkType ` | ` {Entity}{Column} ` in ` src/Model/Enum/ ` |
349370| ** Controller Class** | ` ArticlesController ` | ` MenuLinksController ` | Plural, CamelCased, ends in ` Controller ` |
350371| ** Template Path** | ` templates/Articles/ ` | ` templates/MenuLinks/ ` | Matches controller name |
351372| ** Template File** | ` index.php ` , ` add.php ` | ` index.php ` , ` add.php ` | Underscored action name |
@@ -359,13 +380,13 @@ URL: `https://example.com/articles/view/5`
359380
360381::: details Database Convention Summary
361382
362- | Convention | Description | Example |
363- | ------------| -------------| ---------|
383+ | Convention | Description | Example |
384+ | ------------| -------------| --------------------------------------------- |
364385| ** Foreign Keys** | ` {singular_table}_id ` for hasMany/belongsTo/hasOne | Users hasMany Articles → ` articles.user_id ` |
365- | ** Multi-word FKs** | Use singular of full table name | ` menu_links ` table → ` menu_link_id ` |
366- | ** Junction Tables** | Alphabetically sorted plurals | ` articles_tags ` (not ` tags_articles ` ) |
367- | ** Primary Keys** | Auto-increment INT or UUID | UUID auto-generated via ` Text::uuid() ` |
368- | ** Column Names** | Underscored for multiple words | ` first_name ` , ` created_at ` |
386+ | ** Multi-word FKs** | Use singular of full table name | ` menu_links ` table → ` menu_link_id ` |
387+ | ** Junction Tables** | Alphabetically sorted plurals | ` articles_tags ` (not ` tags_articles ` ) |
388+ | ** Primary Keys** | Auto-increment INT or UUID | UUID auto-generated via ` Text::uuid() ` |
389+ | ** Column Names** | Underscored for multiple words | ` first_name ` , ` is_processed ` |
369390
370391> [ !WARNING]
371392> If junction tables have additional data columns, create a dedicated Table and Entity class for them.
0 commit comments