prisma-php 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,374 @@
1
+ ---
2
+ title: Prisma PHP ORM
3
+ description: Learn how Prisma PHP ORM works, how to configure it, how to migrate your database, and how to generate the PHP ORM classes correctly.
4
+ related:
5
+ title: Related docs
6
+ description: Read the official Prisma PHP ORM docs before generating code or running ORM commands.
7
+ links:
8
+ - /docs/orm-get-started
9
+ - /docs/config-file
10
+ - /docs/prisma-cli
11
+ - /docs/find-many
12
+ ---
13
+
14
+ Prisma PHP ORM gives Prisma PHP applications a schema-first, Prisma-style data layer for PHP projects.
15
+
16
+ It uses your Prisma schema, Prisma migrations, and generated PHP classes so your application can query the database through the documented Prisma PHP API.
17
+
18
+ ## ORM result shape rule
19
+
20
+ Prisma PHP ORM query results should be treated as model-shaped objects returned by the generated Prisma PHP classes that follow `prisma/schema.prisma`.
21
+
22
+ For normal reads, do not assume query results need defensive serializer layers just to become usable in PHP. Prisma ORM is already the source of truth for the requested model shape.
23
+
24
+ Only add a presentation mapper when you intentionally need to:
25
+
26
+ - flatten included relations for the frontend
27
+ - hide sensitive fields before returning data to the browser
28
+ - format dates or values for display
29
+ - produce a custom client-facing response shape
30
+
31
+ Use `PP\Validator` for inbound payload validation, sanitization, casting, and rule-based checks. Do not use output serialization as a substitute for backend validation.
32
+
33
+ ## Backend validation rule
34
+
35
+ For Prisma PHP pages, exposed functions, and route handlers, backend validation should default to `PP\Validator`, which is part of the Prisma PHP core files and lives in:
36
+
37
+ ```txt
38
+ vendor/tsnc/prisma-php/src/Validator.php
39
+ ```
40
+
41
+ `Validator` is the server-side validation layer for user input. It is not the ORM result layer.
42
+
43
+ Use this split:
44
+
45
+ - Prisma ORM for model-shaped query results
46
+ - `PP\Validator` for request validation and normalization
47
+ - optional presentation mapping only when the UI needs a deliberate response shape
48
+
49
+ ## AI agent rule: read the ORM docs first
50
+
51
+ When a task involves any of the following:
52
+
53
+ - `schema.prisma`
54
+ - database provider selection
55
+ - migrations
56
+ - generated Prisma PHP classes
57
+ - `Prisma::getInstance()`
58
+ - `findMany`, `findFirst`, `create`, `update`, `delete`
59
+ - `prisma.config.ts`
60
+ - `npx prisma ...`
61
+ - `npx ppo generate`
62
+
63
+ read the ORM docs first before deciding what command to run or what code to generate.
64
+
65
+ Use this order:
66
+
67
+ 1. Read `prisma-php.json`
68
+ 2. Read the installed Prisma PHP ORM docs
69
+ 3. Read `schema.prisma`
70
+ 4. Confirm the database provider
71
+ 5. Then decide the correct ORM workflow
72
+
73
+ ## Where AI should look
74
+
75
+ For Prisma PHP ORM tasks, AI should read:
76
+
77
+ - `06-prisma-php-orm.md`
78
+ - the official Prisma PHP ORM docs for the installed version
79
+ - `schema.prisma`
80
+ - `prisma.config.ts`
81
+ - `.env` when the datasource uses `env("DATABASE_URL")`
82
+
83
+ Do not use general Prisma TypeScript habits alone. Prisma PHP has a PHP-specific workflow and generated PHP classes that must match the actual database state.
84
+
85
+ ## Important separation of responsibilities
86
+
87
+ There are three different workflows that AI must not confuse.
88
+
89
+ ### 1. Framework or project update workflow
90
+
91
+ Use this only when the task is about updating the full Prisma PHP project, syncing framework files, installing enabled features, or refreshing dependencies:
92
+
93
+ ```bash
94
+ npx pp update project -y
95
+ ```
96
+
97
+ This is a project/framework update command.
98
+
99
+ It is **not** the normal Prisma ORM schema migration workflow.
100
+
101
+ ### 2. Prisma ORM database migration workflow
102
+
103
+ Use this when the database must be initialized or when `schema.prisma` changes and the database structure must be updated.
104
+
105
+ Typical development workflow:
106
+
107
+ ```bash
108
+ npx prisma migrate dev
109
+ ```
110
+
111
+ This is the migration step.
112
+
113
+ ### 3. Prisma PHP class generation workflow
114
+
115
+ Use this after migration succeeds, so the generated PHP ORM classes match the updated schema:
116
+
117
+ ```bash
118
+ npx ppo generate
119
+ ```
120
+
121
+ This is the PHP class generation step.
122
+
123
+ ## Required AI workflow for ORM tasks
124
+
125
+ Whenever a task depends on Prisma ORM, AI should follow this order:
126
+
127
+ 1. Confirm which database provider the project uses.
128
+ 2. Confirm whether the task is working against SQLite, MySQL, PostgreSQL, or another user-requested provider.
129
+ 3. Inspect `schema.prisma`.
130
+ 4. Inspect `prisma.config.ts`.
131
+ 5. If the datasource uses `env("DATABASE_URL")`, inspect `.env`.
132
+ 6. Decide whether migration is required before generation.
133
+ 7. Run migration first when required.
134
+ 8. After migration succeeds, run `npx ppo generate`.
135
+ 9. Only then generate or update PHP code that depends on the Prisma PHP classes.
136
+
137
+ ## Critical rule
138
+
139
+ `npx ppo generate` only generates or refreshes the PHP ORM classes.
140
+
141
+ It does **not** prove that the database migration ran.
142
+
143
+ It does **not** update the database schema by itself.
144
+
145
+ If the migration output is missing, failed, or was never executed, AI must say that clearly.
146
+
147
+ Correct wording:
148
+
149
+ - migration not confirmed
150
+ - generated PHP classes may exist
151
+ - database schema may still be out of sync
152
+
153
+ Incorrect wording:
154
+
155
+ - migration completed, if only `npx ppo generate` ran
156
+ - database is synced, if there is no confirmed migration output
157
+
158
+ ## Confirm the database provider first
159
+
160
+ Before running migration or generation commands, inspect the Prisma schema and determine the active provider.
161
+
162
+ Typical provider examples include:
163
+
164
+ - `sqlite`
165
+ - `mysql`
166
+ - `postgresql`
167
+
168
+ AI should not assume the provider.
169
+
170
+ It should read the datasource block in `schema.prisma` or follow the user’s explicit database request.
171
+
172
+ Example:
173
+
174
+ ```prisma
175
+ // prisma/schema.prisma
176
+ datasource db {
177
+ provider = "sqlite"
178
+ url = env("DATABASE_URL")
179
+ }
180
+ ```
181
+
182
+ ## SQLite workflow
183
+
184
+ When the provider is `sqlite`, AI must do more than just read the provider name.
185
+
186
+ It must also verify the SQLite connection target.
187
+
188
+ Use this flow:
189
+
190
+ 1. read `schema.prisma`
191
+ 2. read `.env` if the datasource URL comes from `env("DATABASE_URL")`
192
+ 3. confirm that `DATABASE_URL` exists
193
+ 4. resolve the SQLite file path from `DATABASE_URL`
194
+ 5. confirm the path is valid for the project
195
+ 6. if the SQLite database file is missing, invalid, or not initialized yet, run:
196
+
197
+ ```bash
198
+ npx prisma migrate dev
199
+ ```
200
+
201
+ 7. after migration succeeds, run:
202
+
203
+ ```bash
204
+ npx ppo generate
205
+ ```
206
+
207
+ Important SQLite rule:
208
+
209
+ - if Prisma PHP reports that the SQLite database file was not found or could not be created, AI must not stop at `npx ppo generate`
210
+ - in that situation, the database initialization or migration step is still required
211
+
212
+ ## MySQL and PostgreSQL workflow
213
+
214
+ When the provider is `mysql` or `postgresql`, use this flow:
215
+
216
+ 1. confirm the provider in `schema.prisma`
217
+ 2. confirm the environment connection values
218
+ 3. run `npx prisma migrate dev` on first setup
219
+ 4. run `npx prisma migrate dev` whenever `schema.prisma` changes
220
+ 5. after migration succeeds, run `npx ppo generate`
221
+
222
+ This keeps the database structure and generated PHP classes aligned.
223
+
224
+ ## `prisma.config.ts`
225
+
226
+ Prisma PHP ORM also uses `prisma.config.ts` at the project root.
227
+
228
+ This file is part of the ORM configuration workflow and should be reviewed when the task involves Prisma ORM setup, migrations, or generation.
229
+
230
+ AI should treat it as part of the ORM source of truth alongside `schema.prisma`.
231
+
232
+ ## Example ORM workflow for AI
233
+
234
+ Use this pattern when the user asks to update models or add ORM-backed features.
235
+
236
+ ### Correct sequence
237
+
238
+ 1. Read `schema.prisma`
239
+ 2. Confirm database provider
240
+ 3. Read `.env` if needed for `DATABASE_URL`
241
+ 4. Decide whether the database must be initialized or migrated
242
+ 5. Run migration
243
+ 6. Run PHP class generation
244
+ 7. Then write route, page, or server logic
245
+
246
+ Example:
247
+
248
+ ```bash
249
+ npx prisma migrate dev
250
+ npx ppo generate
251
+ ```
252
+
253
+ ### Incorrect sequence
254
+
255
+ ```bash
256
+ npx pp update project -y
257
+ npx ppo generate
258
+ ```
259
+
260
+ That sequence may refresh framework files and generate classes, but it does not by itself prove the database schema was migrated.
261
+
262
+ ## Development vs prototype note
263
+
264
+ Prisma CLI also documents `db push` for prototype-style workflows.
265
+
266
+ AI should not treat `db push` as the default migration flow when the intended workflow is migration-based development.
267
+
268
+ For normal tracked schema changes, prefer the documented migration flow first, then class generation.
269
+
270
+ ## First-time generation rule
271
+
272
+ `npx ppo generate` should be executed:
273
+
274
+ - the first time generated PHP ORM classes are needed
275
+ - whenever `schema.prisma` changes
276
+ - after the database migration or initialization step succeeds
277
+
278
+ Do not run generation alone and describe the database as ready unless the migration step was also confirmed.
279
+
280
+ ## Using Prisma PHP in application code
281
+
282
+ After the ORM classes are generated, Prisma PHP code should use the documented PHP access pattern.
283
+
284
+ Example:
285
+
286
+ ```php
287
+ <?php
288
+
289
+ use Lib\Prisma\Classes\Prisma;
290
+
291
+ $prisma = Prisma::getInstance();
292
+
293
+ $users = $prisma->user->findMany();
294
+ ```
295
+
296
+ Do not invent TypeScript-style Prisma usage in PHP files.
297
+
298
+ For normal application code, read ORM results directly as Prisma PHP model-shaped objects. Do not describe a manual serializer as required unless the code is intentionally shaping a frontend-facing response.
299
+
300
+ ## `findMany` example
301
+
302
+ Prisma PHP queries are written with PHP arrays.
303
+
304
+ Example:
305
+
306
+ ```php
307
+ <?php
308
+
309
+ use Lib\Prisma\Classes\Prisma;
310
+
311
+ $prisma = Prisma::getInstance();
312
+
313
+ $users = $prisma->user->findMany([
314
+ 'where' => [
315
+ 'active' => true,
316
+ ],
317
+ 'orderBy' => [
318
+ 'createdAt' => 'desc',
319
+ ],
320
+ 'take' => 10,
321
+ 'skip' => 0,
322
+ ]);
323
+ ```
324
+
325
+ Common query options include:
326
+
327
+ - `where`
328
+ - `select`
329
+ - `include`
330
+ - `orderBy`
331
+ - `take`
332
+ - `skip`
333
+
334
+ ## AI warnings for ORM tasks
335
+
336
+ When working with Prisma PHP ORM, follow these rules:
337
+
338
+ - do not use `npx pp update project -y` as the ORM sync command
339
+ - do not claim migration ran unless command output confirms it
340
+ - do not treat `npx ppo generate` as a migration step
341
+ - do not assume SQLite unless the schema or user request confirms it
342
+ - do not skip `.env` and `DATABASE_URL` checks when SQLite is used
343
+ - do not write raw guessed ORM wrappers if the documented generation workflow should be used
344
+ - do not copy Prisma JavaScript or TypeScript examples directly into PHP
345
+
346
+ ## Best-practice AI wording
347
+
348
+ When migration succeeded and generation succeeded, AI may say:
349
+
350
+ - the database migration completed successfully
351
+ - the Prisma PHP classes were generated successfully
352
+
353
+ When only generation succeeded, AI should say:
354
+
355
+ - `npx ppo generate` completed
356
+ - generated PHP ORM classes are present
357
+ - database migration was not confirmed
358
+
359
+ When SQLite is configured but the file is missing or unusable, AI should say:
360
+
361
+ - SQLite `DATABASE_URL` was checked
362
+ - the SQLite database file is missing, invalid, or not initialized
363
+ - `npx prisma migrate dev` is required before relying on generated PHP ORM classes
364
+
365
+ ## Summary rule
366
+
367
+ For Prisma PHP ORM tasks, the correct mental model is:
368
+
369
+ - confirm provider first
370
+ - inspect `.env` when `DATABASE_URL` is used
371
+ - for SQLite, verify the database file path and initialize or migrate when needed
372
+ - for MySQL and PostgreSQL, migrate on first setup and after schema changes
373
+ - generate PHP classes after migration
374
+ - only use `npx pp update project -y` for full project/framework updates
@@ -0,0 +1,328 @@
1
+ ---
2
+ title: Project structure and organization
3
+ nav_title: Project Structure
4
+ description: Learn the folder and file conventions in Prisma PHP, and how to organize your project.
5
+ ---
6
+
7
+ This page provides an overview of the folder and file conventions in **Prisma PHP**, and recommendations for organizing your project. It follows the Prisma PHP routing model and mirrors the mental model of a Next.js App Router style project structure, adapted to how Prisma PHP actually works.
8
+
9
+ ## Folder and file conventions
10
+
11
+ ### Top-level folders
12
+
13
+ Top-level folders are used to organize your application's source code, configuration, database schema, and public assets.
14
+
15
+ | Folder | Purpose |
16
+ | ---------- | ----------------------------------------------------------------------------- |
17
+ | `src/app` | File-system based routing, pages, layouts, loading states, and route handlers |
18
+ | `src/Lib` | Application libraries, generated Prisma classes, auth, middleware, utilities |
19
+ | `public` | Public web root, static files, CSS, JS, favicon, and public entry point |
20
+ | `prisma` | Prisma schema, migrations, and seed scripts |
21
+ | `settings` | Project configuration such as paths, BrowserSync, and related setup |
22
+
23
+ ### Top-level files
24
+
25
+ These files are typically used to configure the app, manage dependencies, and define environment values.
26
+
27
+ | File | Purpose |
28
+ | ---------------------- | -------------------------------------------------------------- |
29
+ | `composer.json` | PHP dependencies and autoloading |
30
+ | `package.json` | Frontend tooling and development scripts when used |
31
+ | `.env` | Environment variables |
32
+ | `prisma/schema.prisma` | Main Prisma schema file |
33
+ | `public/index.php` | Public entry point |
34
+ | `bootstrap.php` | Application bootstrap and middleware registration when present |
35
+ | `prisma-php.json` | Project capability manifest and local Prisma PHP configuration |
36
+
37
+ ### `prisma-php.json`
38
+
39
+ Prisma PHP projects should place `prisma-php.json` in the **repository root**.
40
+
41
+ This file is the best place to declare enabled project features and local environment metadata because it is easy for tools, scripts, and AI agents to discover next to the rest of the top-level project configuration.
42
+
43
+ Typical values include:
44
+
45
+ - `tailwindcss`
46
+ - `backendOnly`
47
+ - `swaggerDocs`
48
+ - `websocket`
49
+ - `mcp`
50
+ - `prisma`
51
+ - `typescript`
52
+ - BrowserSync target configuration
53
+ - PHP executable path
54
+ - component scan directories
55
+
56
+ If an AI agent is working on the project, it should inspect `prisma-php.json` before deciding whether Tailwind CSS, TypeScript, Prisma ORM, Swagger docs, MCP, or websocket-related code should be generated.
57
+
58
+ ### Full-stack vs backend-only routing decision
59
+
60
+ One of the most important capability flags is `backendOnly`.
61
+
62
+ - When `backendOnly` is `false`, the project is a **full-stack Prisma PHP app**. In that mode, normal route UI should be implemented with `index.php`.
63
+ - When `backendOnly` is `true`, the project is a **backend-only Prisma PHP app**. In that mode, route behavior will usually center on direct handlers such as `route.php`.
64
+ - If a `route.php` file exists at a route segment, it acts as the direct handler entry point for that route and should be treated as the API-style or no-view path for that segment.
65
+ - In full-stack projects, if the user asks for a normal route or page, prefer `index.php`. If the user asks for an API route, JSON endpoint, form-processing endpoint, AJAX endpoint, or direct handler, prefer `route.php`.
66
+
67
+ This helps AI and contributors choose the correct file without guessing based on other frameworks.
68
+
69
+ ### Framework-managed generated files
70
+
71
+ Some files in a Prisma PHP project are framework-managed and should not be manually maintained as part of normal route work.
72
+
73
+ #### `files-list.json`
74
+
75
+ Prisma PHP automatically generates the route list in `files-list.json`.
76
+
77
+ Do **not** create routes by editing this file. Do **not** manually add, remove, reorder, or “sync” entries in it.
78
+
79
+ Instead, create or update the correct folders and route files in `src/app`, then let Prisma PHP regenerate `files-list.json` automatically.
80
+
81
+ When an AI agent is asked to create a route, the correct change is in the route tree itself, not in `files-list.json`.
82
+
83
+ ## Routing files
84
+
85
+ Prisma PHP uses file-system based routing. Folders define route segments, and special files define how those segments behave.
86
+
87
+ Routes are defined by the route tree under `src/app`. Prisma PHP then derives route metadata from those files. Because of that, AI agents should never treat `files-list.json` as the place where routes are declared.
88
+
89
+ | File | Purpose |
90
+ | --------------- | -------------------------------------------------------------------- |
91
+ | `index.php` | Public page entry point for a route and rendered UI |
92
+ | `layout.php` | Shared layout for a route subtree |
93
+ | `loading.php` | Loading UI for a route or subtree |
94
+ | `route.php` | Direct route handler for APIs, JSON, forms, and logic without a view |
95
+ | `not-found.php` | Not found UI |
96
+ | `error.php` | Error handling UI |
97
+
98
+ ## Nested routes
99
+
100
+ Folders define URL segments. Nesting folders nests segments. A route becomes publicly accessible when an `index.php` file exists inside that route folder.
101
+
102
+ | Path | URL pattern | Notes |
103
+ | -------------------------------- | --------------- | ----------------------------------------------------- |
104
+ | `src/app/layout.php` | — | Root layout wraps the application |
105
+ | `src/app/index.php` | `/` | Public home route |
106
+ | `src/app/blog/index.php` | `/blog` | Public nested route |
107
+ | `src/app/blog/authors/index.php` | `/blog/authors` | Public deeply nested route |
108
+ | `src/app/blog/route.php` | `/blog` handler | Direct handler for API-style or programmatic requests |
109
+
110
+ ## Dynamic routes
111
+
112
+ Dynamic segments are created with square brackets and are available through `Request::$dynamicParams` in `layout.php`, `index.php`, and `route.php`.
113
+
114
+ | Path | URL pattern | Notes |
115
+ | ------------------------------------ | -------------------------- | ---------------------- |
116
+ | `src/app/blog/[slug]/index.php` | `/blog/my-first-post` | Single dynamic segment |
117
+ | `src/app/shop/[id]/index.php` | `/shop/42` | Single param by id |
118
+ | `src/app/docs/[...slug]/index.php` | `/docs/a/b/c` | Catch-all route |
119
+ | `src/app/users/[username]/route.php` | `/users/jefferson` handler | Dynamic route handler |
120
+
121
+ ## Route groups and private folders
122
+
123
+ Prisma PHP supports route groups and private folders to help you organize code without exposing everything as a route.
124
+
125
+ | Path | URL pattern | Notes |
126
+ | ------------------------------------- | ----------- | ---------------------------------- |
127
+ | `src/app/(marketing)/about/index.php` | `/about` | Route group omitted from URL |
128
+ | `src/app/(dashboard)/users/index.php` | `/users` | Grouping without changing URL |
129
+ | `src/app/blog/_components/Card.php` | — | Private implementation detail |
130
+ | `src/app/blog/_lib/helpers.php` | — | Non-routable colocated helper code |
131
+
132
+ ## Middleware
133
+
134
+ Middleware in Prisma PHP is convention-based. Middleware classes live in `Lib/Middleware` and are registered in `bootstrap.php`.
135
+
136
+ | Location | Purpose |
137
+ | --------------------------------------- | --------------------------------------------------- |
138
+ | `src/Lib/Middleware/AuthMiddleware.php` | Route protection and auth checks |
139
+ | `bootstrap.php` | Register and invoke middleware |
140
+ | Route matching logic | Apply middleware based on pathname or request rules |
141
+
142
+ ## Redirects
143
+
144
+ Redirects are handled with `Request::redirect()`, which sends an HTTP `Location` header and stops execution.
145
+
146
+ | Pattern | Purpose |
147
+ | ----------------------------- | --------------------------------------------- |
148
+ | `Request::redirect('/home')` | Temporary redirect after an action |
149
+ | `Request::redirect('/login')` | Redirect unauthenticated users |
150
+ | Redirect with 3xx semantics | Standard browser navigation via HTTP redirect |
151
+
152
+ ## Example project structure
153
+
154
+ ```txt
155
+ prisma-php-project/
156
+ ├── prisma/
157
+ │ ├── migrations/
158
+ │ ├── schema.prisma
159
+ │ └── seed.ts
160
+ ├── public/
161
+ │ ├── assets/
162
+ │ ├── css/
163
+ │ ├── js/
164
+ │ ├── favicon.ico
165
+ │ └── index.php
166
+ ├── settings/
167
+ │ ├── bs-config.ts
168
+ │ ├── paths.php
169
+ │ └── restart-websocket.ts
170
+ ├── src/
171
+ │ ├── app/
172
+ │ │ ├── layout.php
173
+ │ │ ├── index.php
174
+ │ │ ├── loading.php
175
+ │ │ ├── not-found.php
176
+ │ │ ├── error.php
177
+ │ │ ├── (marketing)/
178
+ │ │ │ ├── layout.php
179
+ │ │ │ └── about/
180
+ │ │ │ └── index.php
181
+ │ │ ├── dashboard/
182
+ │ │ │ ├── layout.php
183
+ │ │ │ ├── index.php
184
+ │ │ │ ├── users/
185
+ │ │ │ │ ├── index.php
186
+ │ │ │ │ └── [id]/
187
+ │ │ │ │ └── index.php
188
+ │ │ │ ├── reports/
189
+ │ │ │ │ └── route.php
190
+ │ │ │ └── _components/
191
+ │ │ │ └── StatsCard.php
192
+ │ │ └── blog/
193
+ │ │ ├── index.php
194
+ │ │ └── [slug]/
195
+ │ │ └── index.php
196
+ │ └── Lib/
197
+ │ ├── Middleware/
198
+ │ │ └── AuthMiddleware.php
199
+ │ ├── Prisma/
200
+ │ └── Auth/
201
+ ├── bootstrap.php
202
+ ├── composer.json
203
+ ├── package.json
204
+ ├── prisma-php.json
205
+ └── .env
206
+ ```
207
+
208
+ ## Organizing your project
209
+
210
+ Prisma PHP is flexible about how you organize your project files, but its routing system gives you a clear structure for colocating route-specific code.
211
+
212
+ ### Component hierarchy
213
+
214
+ In practice, Prisma PHP route rendering usually follows this hierarchy for a given request:
215
+
216
+ - root `layout.php`
217
+ - nested `layout.php`
218
+ - `loading.php` when applicable
219
+ - `error.php` when applicable
220
+ - `not-found.php` when applicable
221
+ - route `index.php` or `route.php`
222
+
223
+ Nested layouts wrap their child segments, so layouts compose naturally as you go deeper in the route tree.
224
+
225
+ ### Colocation
226
+
227
+ Because routing is based on special files such as `index.php` and `route.php`, you can safely colocate route-specific code inside route folders as long as those files are not themselves routable entry files.
228
+
229
+ This makes it practical to keep related files close together:
230
+
231
+ - components near the route that uses them
232
+ - helpers near the route logic
233
+ - route-specific services or validators in private folders
234
+
235
+ ### Private folders
236
+
237
+ Private folders are prefixed with an underscore, such as `_components` or `_lib`.
238
+
239
+ Use them when you want to:
240
+
241
+ - separate UI logic from route entry files
242
+ - keep helper code close to a route
243
+ - avoid accidental routing
244
+ - keep naming conventions consistent across a project
245
+
246
+ ### Route groups
247
+
248
+ Route groups use parentheses, such as `(marketing)` or `(dashboard)`.
249
+
250
+ Use them when you want to:
251
+
252
+ - organize routes by section, team, or concern
253
+ - apply a layout to a subset of routes
254
+ - keep the URL clean while improving folder organization
255
+
256
+ Be careful not to create two grouped routes that resolve to the same final URL.
257
+
258
+ ### Suggested organization patterns
259
+
260
+ #### Keep routing in `src/app`, shared code in `src/Lib`
261
+
262
+ This is the clearest default for most Prisma PHP applications:
263
+
264
+ - `src/app` handles pages, layouts, route handlers, and route-local files
265
+ - `src/Lib` handles framework-level helpers, auth, middleware, and shared utilities
266
+
267
+ #### Split route-specific code by feature
268
+
269
+ For large applications, keep shared code near the route that owns it:
270
+
271
+ ```txt
272
+ src/app/dashboard/
273
+ ├── layout.php
274
+ ├── index.php
275
+ ├── users/
276
+ │ ├── index.php
277
+ │ ├── [id]/
278
+ │ │ └── index.php
279
+ │ └── _components/
280
+ │ └── UserTable.php
281
+ └── _lib/
282
+ └── dashboard-helpers.php
283
+ ```
284
+
285
+ #### Use groups for multiple application sections
286
+
287
+ This is useful when marketing pages and app pages need different layouts:
288
+
289
+ ```txt
290
+ src/app/
291
+ ├── (marketing)/
292
+ │ ├── layout.php
293
+ │ ├── index.php
294
+ │ └── about/
295
+ │ └── index.php
296
+ └── (app)/
297
+ ├── layout.php
298
+ ├── dashboard/
299
+ │ └── index.php
300
+ └── settings/
301
+ └── index.php
302
+ ```
303
+
304
+ ## Prisma PHP mental model for Next.js App Router users
305
+
306
+ If you are coming from Next.js App Router, this is the closest mapping:
307
+
308
+ | Next.js concept | Prisma PHP concept |
309
+ | --------------- | ------------------ |
310
+ | `app/` | `src/app/` |
311
+ | `page.tsx` | `index.php` |
312
+ | `layout.tsx` | `layout.php` |
313
+ | `loading.tsx` | `loading.php` |
314
+ | `route.ts` | `route.php` |
315
+ | `not-found.tsx` | `not-found.php` |
316
+ | `error.tsx` | `error.php` |
317
+ | `(group)` | `(group)` |
318
+ | `_folder` | `_folder` |
319
+ | `[slug]` | `[slug]` |
320
+ | `[...slug]` | `[...slug]` |
321
+
322
+ The main difference is that Prisma PHP uses PHP entry files and server-rendered route handling instead of React component files, but the route-tree organization model is intentionally very similar.
323
+
324
+ For route choice, remember this practical rule:
325
+
326
+ - use `index.php` for normal full-stack pages and route UI
327
+ - use `route.php` for API-style, JSON, AJAX, webhook, or no-view handlers
328
+ - if a segment has a `route.php`, treat it as the direct handler entry point for that route