From f50b71c93fe8f05f904da7d619fadbb96255712a Mon Sep 17 00:00:00 2001 From: Jasper Smet Date: Thu, 29 Jan 2026 10:46:29 +0100 Subject: [PATCH 1/2] consolidate convetions with folder structure and greatly improve cognitive load --- docs/en/intro/cakephp-folder-structure.md | 74 --- docs/en/intro/conventions.md | 588 ++++++++++++---------- toc_en.json | 6 +- 3 files changed, 331 insertions(+), 337 deletions(-) delete mode 100644 docs/en/intro/cakephp-folder-structure.md diff --git a/docs/en/intro/cakephp-folder-structure.md b/docs/en/intro/cakephp-folder-structure.md deleted file mode 100644 index a7ad0d7221..0000000000 --- a/docs/en/intro/cakephp-folder-structure.md +++ /dev/null @@ -1,74 +0,0 @@ -# CakePHP Folder Structure - -After you've downloaded the CakePHP application skeleton, there are a few top -level folders you should see: - -- `bin/` holds the Cake console executables so you can execute e.g. `bin/cake bake all`. - -- `config/` holds the [Configuration](../development/configuration) files. - Database connection details, bootstrapping, core configuration files - and more should be stored here. - -- `plugins/` is where the [Plugins](../plugins) your application uses are stored. - -- `logs/` contains your log files, can be adjusted via [Log Configuration](../core-libraries/logging.md#logging-configuration). - -- `src/` will be where your application's source files like Controllers, Models, Commands etc. will be placed. - -- `templates/` has presentational files placed here: - elements, error pages, layouts, and view template files. - -- `resources/` is primarily used for the `locales/` subfolder storing language files for static internationalization. - -- `tests/` will be where you put the test cases for your application. - -- `tmp/` is where CakePHP stores temporary data. The actual data it - stores depends on how you have CakePHP configured, but this folder - is usually used to store translation messages, model descriptions and sometimes - session information. - -- `vendor/` is where CakePHP and other application dependencies will - be installed by [Composer](https://getcomposer.org). **Editing these files is not - advised, as Composer will overwrite your changes next time you update.** - -- `webroot/` is the public document root of your application. It - contains all the files you want to be publicly reachable. - -Make sure that the `tmp/` and `logs/` folders exist and are writable, -otherwise the performance of your application will be severely -impacted. In debug mode, CakePHP will warn you if these directories are not -writable. - -## The src Folder - -CakePHP's `src/` folder is where you will do most of your application -development. Let's look a little closer at the folders inside. - -### Command - -Contains your application's console commands. See -[Command Objects](../console-commands/commands) to learn more. - -> [!NOTE] -> The folder `Command/` is not present by default. -> It will be auto generated when you create your first command using bake. - -### Console - -Contains the installation script executed by Composer. - -### Controller - -Contains your application's [Controllers](../controllers) and their components. - -### Middleware - -Stores any [Middleware](../controllers/middleware) for your application. - -### Model - -Contains your application's [Tables](../orm/table-objects.md), [Entities](../orm/entities.md) and [Behaviors](../orm/behaviors.md). - -### View - -Presentational classes are placed here: [Views](../views.md), [Cells](../views/cells.md), [Helpers](../views/helpers.md). diff --git a/docs/en/intro/conventions.md b/docs/en/intro/conventions.md index f845b969c0..2002f50b33 100644 --- a/docs/en/intro/conventions.md +++ b/docs/en/intro/conventions.md @@ -1,296 +1,368 @@ -# CakePHP Conventions +# Structure & Conventions -We are big fans of convention over configuration. While it takes a bit of time -to learn CakePHP's conventions, you save time in the long run. By following -conventions, you get free functionality, and you liberate yourself from the -maintenance nightmare of tracking config files. Conventions also make for a very -uniform development experience, allowing other developers to jump in and help. +CakePHP embraces **convention over configuration**. By following conventions, you get free functionality without tracking config files, and create a uniform codebase that other developers can quickly understand. This guide covers both where files go and how to name them. -## Controller Conventions +> [!TIP] +> Following these conventions means CakePHP automatically wires up your application - controllers find their models, views find their templates, and URLs map to actions without any configuration. -Controller class names are plural, CamelCased, and end in `Controller`. -`UsersController` and `MenuLinksController` are both examples of -conventional controller names. +## Application Folder Structure -Public methods on Controllers are often exposed as 'actions' accessible through -a web browser. They are camelBacked. For example the `/users/view-me` maps to the `viewMe()` method -of the `UsersController` out of the box (if one uses default dashed inflection in routing). -Protected or private methods cannot be accessed with routing. +After downloading the CakePHP application skeleton, you'll see these top-level folders: -For inflection of acronyms it is useful to treat them as words, so `CMS` would be `Cms`. +**Essential Folders:** -### URL Considerations for Controller Names +- `src/` - Your application's source code (Controllers, Models, Commands, etc.) +- `templates/` - View template files, elements, layouts, and error pages +- `config/` - [Configuration](../development/configuration) files for database, routes, and application settings +- `webroot/` - Public document root containing publicly accessible files -As you've just seen, single word controllers map to a simple lower case URL -path. For example, `UsersController` (which would be defined in the file name -**UsersController.php**) is accessed from `https://example.com/users`. +::: details Other Application Folders -While you can route multiple word controllers in any way you like, the -convention is that your URLs are lowercase and dashed using the `DashedRoute` -class, therefore `/menu-links/view-all` is the correct form to access -the `MenuLinksController::viewAll()` action. +**Development & Testing:** -When you create links using `this->Html->link()`, you can use the following -conventions for the url array: +- `tests/` - Your application's test cases +- `bin/` - Cake console executables (`bin/cake bake all`, etc.) -``` php -$this->Html->link('link-title', [ - 'prefix' => 'MyPrefix' // CamelCased - 'plugin' => 'MyPlugin', // CamelCased - 'controller' => 'ControllerName', // CamelCased - 'action' => 'actionName', // camelBacked -] +**Runtime & Dependencies:** + +- `tmp/` - Temporary data (cache, sessions, logs). Must be writable! +- `logs/` - Application log files. Must be writable! +- `vendor/` - Dependencies installed by [Composer](https://getcomposer.org). **Don't edit - Composer will overwrite changes!** + +**Extensions & Localization:** + +- `plugins/` - [Plugins](../plugins) used by your application +- `resources/` - Contains `locales/` subfolder for internationalization files + +::: + +> [!WARNING] +> Make sure `tmp/` and `logs/` folders are writable! Poor performance or errors will occur otherwise. CakePHP warns you in debug mode if they're not writable. + +## The src/ Directory + +The `src/` folder is where you'll do most development. Here's what goes in each subfolder: + +| Folder | Contains | Naming Convention | +|--------|----------|-------------------| +| **Command** | Console commands | `*Command.php` - See [Command Objects](../console-commands/commands) | +| **Console** | Installation scripts | Executed by Composer | +| **Controller** | HTTP request handlers | [Controllers](../controllers), [Components](../controllers/components) | +| **Middleware** | Request/response filters | `*Middleware.php` - See [Middleware](../controllers/middleware) | +| **Model** | Data layer | [Tables](../orm/table-objects), [Entities](../orm/entities), [Behaviors](../orm/behaviors) | +| **View** | Presentation logic | [Views](../views), [Cells](../views/cells), [Helpers](../views/helpers) | + +> [!NOTE] +> The `Command/` folder isn't present by default - it's auto-generated when you create your first command using bake. + +## Naming Conventions + +### Controllers + +::: code-group + +```php [✅ Correct] +// File: src/Controller/UsersController.php +namespace App\Controller; + +class UsersController extends AppController +{ + // URL: /users/view-me + public function viewMe() + { + // camelBacked method names + } +} ``` -For more information on CakePHP URLs and parameter handling, see -[Routes Configuration](../development/routing#routes-configuration). +```php [❌ Incorrect] +// Wrong: singular, lowercase, no suffix +class user extends AppController +{ + // Wrong: underscores instead of camelCase + public function view_me() + { + } +} +``` - +::: -## File and Class Name Conventions +**Rules:** -In general, filenames match the class names, and follow the PSR-4 standard for -autoloading. The following are some examples of class names and their filenames: - -- The Controller class `LatestArticlesController` would be found in a file - named **LatestArticlesController.php** -- The Component class `MyHandyComponent` would be found in a file named - **MyHandyComponent.php** -- The Table class `OptionValuesTable` would be found in a file named - **OptionValuesTable.php**. -- The Entity class `OptionValue` would be found in a file named - **OptionValue.php**. -- The Behavior class `EspeciallyFunkableBehavior` would be found in a file - named **EspeciallyFunkableBehavior.php** -- The View class `SuperSimpleView` would be found in a file named - **SuperSimpleView.php** -- The Helper class `BestEverHelper` would be found in a file named - **BestEverHelper.php** - -Each file would be located in the appropriate folder/namespace in your app -folder. +- **Class names:** Plural, CamelCased, end in `Controller` + - `UsersController`, `MenuLinksController` +- **File names:** Match class name exactly - `UsersController.php` +- **Location:** `src/Controller/UsersController.php` +- **Actions:** camelBacked public methods - `viewMe()`, `editProfile()` +- **URLs:** Lowercase with dashes - `/users/view-me` maps to `viewMe()` - +> [!TIP] +> **Acronyms:** Treat them as words. `CMS` becomes `CmsController`, not `CMSController` + +**URL Arrays:** -## Database Conventions +```php +$this->Html->link('title', [ + 'prefix' => 'MyPrefix', // CamelCased + 'plugin' => 'MyPlugin', // CamelCased + 'controller' => 'Users', // CamelCased + 'action' => 'viewProfile' // camelBacked +]); +``` + +### Models (Tables & Entities) + +::: code-group + +```php [✅ Table Class] +// File: src/Model/Table/UsersTable.php +namespace App\Model\Table; + +class UsersTable extends Table +{ + // Plural, CamelCased, ends in "Table" +} +``` -Table names corresponding to CakePHP models are plural and underscored. For -example `users`, `menu_links`, and `user_favorite_pages` -respectively. Table name whose name contains multiple words should only -pluralize the last word, for example, `menu_links`. +```php [✅ Entity Class] +// File: src/Model/Entity/User.php +namespace App\Model\Entity; -Column names with two or more words are underscored, for example, `first_name`. +class User extends Entity +{ + // Singular, CamelCased, no suffix +} +``` -Foreign keys in hasMany, belongsTo/hasOne relationships are recognized by -default as the (singular) name of the related table followed by `_id`. So if -Users hasMany Articles, the `articles` table will refer to the `users` -table via a `user_id` foreign key. For a table like `menu_links` -whose name contains multiple words, the foreign key would be -`menu_link_id`. +::: -Join (or "junction") tables are used in BelongsToMany relationships between -models. These should be named for the tables they connect. The names should be -pluralized and sorted alphabetically: `articles_tags`, not `tags_articles` -or `article_tags`. *The bake command will not work if this convention is not -followed.* If the junction table holds any data other than the linking foreign -keys, you should create a concrete entity/table class for the table. +**Rules:** -In addition to using an auto-incrementing integer as primary keys, you can also -use UUID columns. CakePHP will create UUID values automatically using -(`Cake\Utility\Text::uuid()`) whenever you save new records using -the `Table::save()` method. +- **Table class:** Plural, CamelCased, ends in `Table` + - `UsersTable`, `MenuLinksTable`, `UserFavoritePagesTable` +- **Entity class:** Singular, CamelCased, no suffix + - `User`, `MenuLink`, `UserFavoritePage` +- **Enum class:** `{Entity}{Column}` - e.g., `UserStatus`, `OrderState` +- **Behavior class:** Ends in `Behavior` - `TimestampBehavior` -## Model Conventions +### Views & Templates -Table class names are plural, CamelCased and end in `Table`. `UsersTable`, -`MenuLinksTable`, and `UserFavoritePagesTable` are all examples of -table class names matching the `users`, `menu_links` and -`user_favorite_pages` tables respectively. +::: code-group -Entity class names are singular CamelCased and have no suffix. `User`, -`MenuLink`, and `UserFavoritePage` are all examples of entity names -matching the `users`, `menu_links` and `user_favorite_pages` -tables respectively. +```php [✅ Template Files] +// Controller method: ArticlesController::viewAll() +templates/Articles/view_all.php -Enum class names should use a `{Entity}{Column}` convention, and enum cases -should use CamelCased names. +// Controller method: MenuLinksController::editItem() +templates/MenuLinks/edit_item.php +``` + +```php [✅ View Classes] +// File: src/View/ArticlesView.php +class ArticlesView extends View +{ +} +``` -## View Conventions +::: -View template files are named after the controller functions they display, in an -underscored form. The `viewAll()` function of the `ArticlesController` class -will look for a view template in **templates/Articles/view_all.php**. +**Rules:** -The basic pattern is -**templates/Controller/underscored_function_name.php**. +- **Template files:** `templates/{Controller}/{underscored_action}.php` + - Method `viewAll()` → `templates/Articles/view_all.php` +- **View classes:** CamelCased, end in `View` - `ArticlesView.php` +- **Helpers:** CamelCased, end in `Helper` - `BestEverHelper.php` +- **Cells:** CamelCased, end in `Cell` - `InboxCell.php` > [!NOTE] -> By default CakePHP uses English inflections. If you have database -> tables/columns that use another language, you will need to add inflection -> rules (from singular to plural and vice-versa). You can use -> `Cake\Utility\Inflector` to define your custom inflection -> rules. See the documentation about [Inflector](../core-libraries/inflector) for more -> information. +> CakePHP uses English inflections by default. For other languages, use `Cake\Utility\Inflector` to define custom rules. See [Inflector](../core-libraries/inflector) documentation. + +### Database Tables + +::: code-group + +```sql [✅ Correct Table Names] +-- Plural, underscored +CREATE TABLE users; +CREATE TABLE menu_links; +CREATE TABLE user_favorite_pages; + +-- Foreign keys: {singular_table}_id +ALTER TABLE articles ADD user_id INT; +ALTER TABLE photos ADD menu_link_id INT; + +-- Junction tables: alphabetically sorted plurals +CREATE TABLE articles_tags; +``` + +```sql [❌ Incorrect] +-- Wrong: singular +CREATE TABLE user; + +-- Wrong: not underscored +CREATE TABLE MenuLinks; + +-- Wrong: plural both words +CREATE TABLE users_favorites_pages; + +-- Wrong: not alphabetical +CREATE TABLE tags_articles; +``` + +::: + +**Rules:** + +- **Table names:** Plural, underscored - `users`, `menu_links` +- **Multiple words:** Only pluralize the last word - `user_favorite_pages` (not `users_favorites_pages`) +- **Columns:** Underscored - `first_name`, `created_at` +- **Foreign keys:** `{singular_table}_id` - `user_id`, `menu_link_id` +- **Junction tables:** Alphabetically sorted plurals - `articles_tags` (not `tags_articles`) + +> [!WARNING] +> The bake command requires junction tables to be alphabetically sorted! Use `articles_tags`, not `tags_articles`. + +**Primary Keys:** + +- Auto-incrementing integers (default) +- UUIDs: CakePHP generates automatically with `Cake\Utility\Text::uuid()` when using `Table::save()` + +> [!TIP] +> If your junction table has extra columns beyond the foreign keys, create a dedicated Table and Entity class for it. + +### Plugins + +::: code-group + +```text [✅ Good Plugin Names] +your-name/cakephp-blog +awesome-dev/cakephp-payment +company/cakephp-api-client +``` + +```text [❌ Bad Plugin Names] +cakephp/blog // Reserved namespace! +YourName/CakePHP-Blog // Use lowercase & dashes +your-name/blog // Missing cakephp- prefix +``` + +::: + +**Rules:** + +- Prefix with `cakephp-` in package name +- Use lowercase letters and dashes +- **Never** use `cakephp/` as vendor name (reserved for official plugins) +- Format: `your-vendor/cakephp-plugin-name` + +See [awesome list recommendations](https://github.com/FriendsOfCake/awesome-cakephp/blob/master/CONTRIBUTING.md#tips-for-creating-cakephp-plugins) for details. + +## File and Class Name Conventions -## Plugins Conventions +All files follow **PSR-4 autoloading** - filenames must match class names exactly: -It is useful to prefix a CakePHP plugin with "cakephp-" in the package name. -This makes the name semantically related on the framework it depends on. +| Class Type | Class Name | File Name | Location | +|------------|-----------|-----------|----------| +| Controller | `LatestArticlesController` | `LatestArticlesController.php` | `src/Controller/` | +| Component | `MyHandyComponent` | `MyHandyComponent.php` | `src/Controller/Component/` | +| Table | `OptionValuesTable` | `OptionValuesTable.php` | `src/Model/Table/` | +| Entity | `OptionValue` | `OptionValue.php` | `src/Model/Entity/` | +| Behavior | `EspeciallyFunkableBehavior` | `EspeciallyFunkableBehavior.php` | `src/Model/Behavior/` | +| View | `SuperSimpleView` | `SuperSimpleView.php` | `src/View/` | +| Helper | `BestEverHelper` | `BestEverHelper.php` | `src/View/Helper/` | +| Command | `UpdateCacheCommand` | `UpdateCacheCommand.php` | `src/Command/` | -Do **not** use the CakePHP namespace (cakephp) as vendor name as this is -reserved to CakePHP owned plugins. The convention is to use lowercase letters -and dashes as separator: + + + +## Complete Example: Articles Feature + +Here's how all the conventions work together for a complete feature: + +**Database:** -``` text -// Bad -cakephp/foo-bar +```sql +CREATE TABLE articles ( + id INT PRIMARY KEY AUTO_INCREMENT, + user_id INT, + title VARCHAR(255), + body TEXT, + created DATETIME, + modified DATETIME +); -// Good -your-name/cakephp-foo-bar +CREATE TABLE users ( + id INT PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(50), + email VARCHAR(255) +); ``` -See [awesome list recommendations](https://github.com/FriendsOfCake/awesome-cakephp/blob/master/CONTRIBUTING.md#tips-for-creating-cakephp-plugins) -for details. - -## Summarized - -By naming the pieces of your application using CakePHP conventions, you gain -functionality without the hassle and maintenance tethers of configuration. -Here's a final example that ties the conventions together: - -- Database table: "articles", "menu_links" -- Table class: `ArticlesTable`, found at **src/Model/Table/ArticlesTable.php** -- Entity class: `Article`, found at **src/Model/Entity/Article.php** -- Controller class: `ArticlesController`, found at - **src/Controller/ArticlesController.php** -- View template, found at **templates/Articles/index.php** - -Using these conventions, CakePHP knows that a request to -`https://example.com/articles` maps to a call on the `index()` method of the -`ArticlesController`, where the `Articles` model is automatically available. -None of these relationships have been configured by any means other than by -creating classes and files that you'd need to create anyway. - - ------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Examplearticlesmenu_links
Database Tablearticlesmenu_linksTable names corresponding to CakePHP models are plural and underscored.
FileArticlesController.phpMenuLinksController.php
TableArticlesTable.phpMenuLinksTable.phpTable class names are plural, CamelCased and end in Table
EntityArticle.phpMenuLink.phpEntity class names are singular, CamelCased: Article and MenuLink
ClassArticlesControllerMenuLinksController
ControllerArticlesControllerMenuLinksControllerPlural, CamelCased, end in Controller
TemplatesArticles/index.php Articles/add.php Articles/get_list.phpMenuLinks/index.php MenuLinks/add.php MenuLinks/get_list.phpView template files are named after the controller functions they display, in an underscored form
BehaviorArticlesBehavior.phpMenuLinksBehavior.php
ViewArticlesView.phpMenuLinksView.php
HelperArticlesHelper.phpMenuLinksHelper.php
ComponentArticlesComponent.phpMenuLinksComponent.php
PluginBad: cakephp/articles Good: you/cakephp-articlescakephp/menu-links you/cakephp-menu-linksUseful to prefix a CakePHP plugin with "cakephp-" in the package name. Do not use the CakePHP namespace (cakephp) as vendor name as this is reserved to CakePHP owned plugins. The convention is to use lowercase letters and dashes as separator.
Each file would be located in the appropriate folder/namespace in your app folder.
- -## Database Convention Summary - - ---- - - - - - - - - - - - - - - - - - - -

Foreign keys

-

hasMany belongsTo/ hasOne BelongsToMany

Relationships are recognized by default as the (singular) name of the related table followed by _id. Users hasMany Articles, articles table will refer to the users table via a user_id foreign key.
Multiple Wordsmenu_links whose name contains multiple words, the foreign key would be menu_link_id.
Auto IncrementIn addition to using an auto-incrementing integer as primary keys, you can also use UUID columns. CakePHP will create UUID values automatically using (Cake\Utility\Text::uuid()) whenever you save new records using the Table::save() method.
Join tablesShould be named after the model tables they will join or the bake command won't work, arranged in alphabetical order (articles_tags rather than tags_articles). Additional columns on the junction table you should create a separate entity/table class for that table.
- -Now that you've been introduced to CakePHP's fundamentals, you might try a run -through the [Content Management Tutorial](../tutorials-and-examples/cms/installation) to see how things fit -together. +**File Structure:** + +```text +src/ +├── Controller/ +│ └── ArticlesController.php → class ArticlesController +├── Model/ +│ ├── Table/ +│ │ └── ArticlesTable.php → class ArticlesTable +│ └── Entity/ +│ └── Article.php → class Article +templates/ +└── Articles/ + ├── index.php → ArticlesController::index() + ├── view.php → ArticlesController::view() + └── add.php → ArticlesController::add() +``` + +**How It Works:** + +URL: `https://example.com/articles/view/5` + +1. Routes to `ArticlesController::view()` +2. Controller automatically loads `ArticlesTable` +3. Method fetches `Article` entity with ID 5 +4. Renders `templates/Articles/view.php` + +**No configuration required!** CakePHP wires everything automatically through conventions. + +::: details Click to see comprehensive reference table + +| Component | `articles` Example | `menu_links` Example | Convention | +|-----------|-------------------|---------------------|------------| +| **Database Table** | `articles` | `menu_links` | Plural, underscored | +| **Table Class** | `ArticlesTable` | `MenuLinksTable` | Plural, CamelCased, ends in `Table` | +| **Entity Class** | `Article` | `MenuLink` | Singular, CamelCased | +| **Controller Class** | `ArticlesController` | `MenuLinksController` | Plural, CamelCased, ends in `Controller` | +| **Template Path** | `templates/Articles/` | `templates/MenuLinks/` | Matches controller name | +| **Template File** | `index.php`, `add.php` | `index.php`, `add.php` | Underscored action name | +| **Behavior** | `ArticlesBehavior` | `MenuLinksBehavior` | Ends in `Behavior` | +| **Helper** | `ArticlesHelper` | `MenuLinksHelper` | Ends in `Helper` | +| **Component** | `ArticlesComponent` | `MenuLinksComponent` | Ends in `Component` | +| **View Class** | `ArticlesView` | `MenuLinksView` | Ends in `View` | +| **Plugin Package** | `you/cakephp-articles` | `you/cakephp-menu-links` | Lowercase, dashed, prefixed | + +::: + +::: details Database Convention Summary + +| Convention | Description | Example | +|------------|-------------|---------| +| **Foreign Keys** | `{singular_table}_id` for hasMany/belongsTo/hasOne | Users hasMany Articles → `articles.user_id` | +| **Multi-word FKs** | Use singular of full table name | `menu_links` table → `menu_link_id` | +| **Junction Tables** | Alphabetically sorted plurals | `articles_tags` (not `tags_articles`) | +| **Primary Keys** | Auto-increment INT or UUID | UUID auto-generated via `Text::uuid()` | +| **Column Names** | Underscored for multiple words | `first_name`, `created_at` | + +> [!WARNING] +> If junction tables have additional data columns, create a dedicated Table and Entity class for them. + +::: + +## Next Steps + +Now that you understand CakePHP's structure and conventions, try the [Content Management Tutorial](../tutorials-and-examples/cms/installation) to see how everything fits together in a real application. + +For routing and URL handling, see [Routes Configuration](../development/routing#routes-configuration). diff --git a/toc_en.json b/toc_en.json index aff3bc9f13..4e7e53d36c 100644 --- a/toc_en.json +++ b/toc_en.json @@ -7,11 +7,7 @@ { "text": "Quickstart", "link": "/quickstart" }, { "text": "Installation", "link": "/installation" }, { "text": "Introduction", "link": "/intro" }, - { "text": "Conventions", "link": "/intro/conventions" }, - { - "text": "CakePHP Folder Structure", - "link": "/intro/cakephp-folder-structure" - }, + { "text": "Structure & Conventions", "link": "/intro/conventions" }, { "text": "Where to Get Help", "link": "/intro/where-to-get-help" From 6f6c019e26d0ccc9e2b0d4c07ed739ca5919a692 Mon Sep 17 00:00:00 2001 From: Jasper Smet Date: Thu, 29 Jan 2026 11:18:05 +0100 Subject: [PATCH 2/2] copilot feedback --- docs/en/intro.md | 3 +-- docs/en/intro/conventions.md | 12 +++++++++--- docs/en/tutorials-and-examples/cms/installation.md | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/en/intro.md b/docs/en/intro.md index e5f70c3a94..910cd8306b 100644 --- a/docs/en/intro.md +++ b/docs/en/intro.md @@ -160,5 +160,4 @@ The next obvious steps are to [download CakePHP](installation), read the ## Additional Reading - [Where to Get Help](intro/where-to-get-help) -- [CakePHP Conventions](intro/conventions) -- [CakePHP Folder Structure](intro/cakephp-folder-structure) +- [Structure & Conventions](intro/conventions) diff --git a/docs/en/intro/conventions.md b/docs/en/intro/conventions.md index 2002f50b33..408f097b75 100644 --- a/docs/en/intro/conventions.md +++ b/docs/en/intro/conventions.md @@ -97,9 +97,15 @@ class user extends AppController - **Actions:** camelBacked public methods - `viewMe()`, `editProfile()` - **URLs:** Lowercase with dashes - `/users/view-me` maps to `viewMe()` +> [!WARNING] +> Only **public** methods are accessible through routing. Protected and private methods cannot be accessed via URLs, providing automatic security for internal helper methods. + > [!TIP] > **Acronyms:** Treat them as words. `CMS` becomes `CmsController`, not `CMSController` +> [!NOTE] +> CakePHP uses the `DashedRoute` class by convention to automatically convert camelCase action names to dashed URLs. See [Routes Configuration](../development/routing#routes-configuration) for details. + **URL Arrays:** ```php @@ -258,6 +264,9 @@ your-name/blog // Missing cakephp- prefix See [awesome list recommendations](https://github.com/FriendsOfCake/awesome-cakephp/blob/master/CONTRIBUTING.md#tips-for-creating-cakephp-plugins) for details. + + + ## File and Class Name Conventions All files follow **PSR-4 autoloading** - filenames must match class names exactly: @@ -273,9 +282,6 @@ All files follow **PSR-4 autoloading** - filenames must match class names exactl | Helper | `BestEverHelper` | `BestEverHelper.php` | `src/View/Helper/` | | Command | `UpdateCacheCommand` | `UpdateCacheCommand.php` | `src/Command/` | - - - ## Complete Example: Articles Feature Here's how all the conventions work together for a complete feature: diff --git a/docs/en/tutorials-and-examples/cms/installation.md b/docs/en/tutorials-and-examples/cms/installation.md index 6140eb3dcc..19a167e149 100644 --- a/docs/en/tutorials-and-examples/cms/installation.md +++ b/docs/en/tutorials-and-examples/cms/installation.md @@ -89,7 +89,7 @@ cms/ ``` Now might be a good time to learn a bit about how CakePHP's directory structure -works: check out the [CakePHP Folder Structure](../../intro/cakephp-folder-structure) section. +works: check out the [Structure & Conventions](../../intro/conventions) guide. ::: tip Completed Tutorial If you get lost during this tutorial, you can see the finished result [on GitHub](https://github.com/cakephp/cms-tutorial).