nette/claude-code/nette-database
- community
Checking that the SKILL.md file is still in the repository.
Invoke before writing database queries or working with Selection API, ActiveRow in Nette. Use when creating entity classes, configuring database connections, writing queries, fetching data, using joins, or designing Row classes. Also consult when deciding between Selection API and raw SQL, or setting up database configuration in .neon files.
Install
npx vskill@latest install nette/claude-code/nette-databaseSKILL.md
Database
Uses Nette Database, typically with MySQL, PostgreSQL or SQLite as the backend.
See the Explorer documentation for the full ActiveRow/Selection API. See the SQL way documentation for direct SQL queries.
Database Conventions
- Table names use singular form (e.g.,
usernotusers) - Use TINYINT(1) for booleans
- Use
idfor primary keys - Character encoding:
utf8mb4with appropriate collation (e.g.utf8mb4_0900_ai_ci, orutf8mb4_cs_0900_ai_cifor Czech) - Standard timestamp fields:
created_atDATETIME DEFAULT CURRENT_TIMESTAMP- never use TIMESTAMP for date/time fields
Entity Mapping
Nette Database has a built-in EntityMapping interface (since 3.2) that the Explorer uses to resolve an ActiveRow subclass for each table and (optionally) translate between column names and PHP property names. The default implementation (DefaultEntityMapping) supports:
- Table-to-class map with wildcards. Keys may be exact names (
special_table), wildcard patterns (forum_*) or a bare*catch-all. Class names may contain*, which is replaced with the PascalCase of the captured portion:forum_post+App\Forum\*Row→App\Forum\PostRow. A class without*is a fixed class (log_*: App\Logging\LogRowmaps everylog_*table to the sameLogRow). Schema prefixes likepublic.are stripped before PascalCase conversion. Exact keys take precedence; wildcard entries are tried in declaration order, so put more specific patterns first and the bare*last. - camelCase column ↔ property translation — when enabled, column
author_idis exposed as propertyauthorIdeverywhere: property access, iteration,toArray(),insert(),update(), and column references inwhere()/order().
Activate via the mapping config option (see Database Configuration below).
Entity Design Strategy
All entities in App\Entity with consistent Row suffix (matches the App\Entity\*Row convention):
producttable →ProductRoworder_itemtable →OrderItemRowvariant_expirationtable →VariantExpirationRow
Why flat: Entities are data structures that cross domain boundaries. A ProductRow might be used in catalog, orders, inventory, and reporting contexts. Subdividing entities by domain forces you to either pick one arbitrary "home" domain or duplicate references.
Entity Organization
All entities in single App\Entity namespace - avoid domain subdivision:
Entity Documentation Patterns
Documentation rules:
- Document ALL accessible properties (including inherited id)
- Use nullable types for optional foreign keys
- Include relationship properties for IDE navigation
- Match database schema exactly
Entity Relationships in phpDoc
Foreign key patterns:
@property-read ?CategoryRow $categoryfor optional relationships@property-read UserRow $authorfor required relationships@property-read Selection<OrderItemRow> $order_itemsfor back-references
Naming convention: Follow Nette Database relationship naming (foreign key without _id suffix).
With `camelCase: true` mapping: scalar columns map to camelCase properties ($firstName, $createdAt). Relationship property names ($author, $category) are resolved by Conventions against database columns, so they aren't affected by the camelCase setting.
When to Use Selection API
Use for:
- Simple filtering and sorting
- Standard CRUD operations
- Queries that benefit from lazy loading
- When you need to chain conditions dynamically
When to Use Raw SQL
Use for:
- Complex analytics and reporting
- Recursive queries (WITH RECURSIVE)
- Performance-critical queries
- Complex joins that are awkward in Selection API
Query Building Patterns
Build queries by progressive refinement – start with a base method, then add conditions. Always use generic types for Selection returns:
Relationship Navigation
Use colon notation for efficient joins:
Traps in where() and SQL Fragments
The array KEY is SQL, the value is a bound parameter. where() splits the key on the first space into a column and an operator and emits both into the query, so a key built from user input is an injection hole – and mass-assigning a request array into where() or insert() lets the client choose columns and operators:
Write SQL keywords in UPPERCASE inside fragments. Explorer quotes lowercase words as identifiers, so where('name like ?', $x) compiles to ` name like ? ` and fails; uppercase words are left alone:
An empty array flips the meaning of a condition. where('id', []) becomes IS NULL AND FALSE (matches nothing), while where('id NOT', []) becomes IS NULL OR TRUE (matches everything). Guard empty filter lists explicitly. Mixing operators without parentheses raises Possible SQL query corruption. Add parentheses around operators.
Fetching Strategies by Use Case
Single optional result: ->fetch() All results as array: ->fetchAll() Key-value pairs: ->fetchPairs('key_column', 'value_column') Single scalar value: ->fetchField() (first column of first row) Count only: ->count('*')
Structured data with fetchAssoc:
The path string uses [] for array grouping, | for nested keys, and = to extract a single value.
Schema and Constraints
Use direct SQL migrations rather than ORM-style migrations – store schema in sql/db.sql with manual migration scripts. Rely on database constraints (foreign keys, unique, check) for data integrity and handle constraint violations in services with meaningful business exceptions.
Transactions
Wrap multi-step writes in transactions to ensure consistency:
The callback approach automatically commits on success and rolls back on exception, and it returns whatever the callback returns, so you can produce a value out of it.
Nested transaction() calls are counted, and only the outermost one actually commits. Calling beginTransaction(), commit() or rollBack() manually inside the callback throws LogicException – pick one style per code path and stay with it.
Anti-Patterns to Avoid
Don't create separate Repository classes – in Nette, services combine data access with business logic. A separate repository layer adds indirection without benefit because Nette Database Explorer already provides a clean query API. The service IS the repository.
Error Handling
Transform database errors to business exceptions:
Handle at service boundary – presenters should receive business exceptions, not database exceptions. This keeps the UI layer independent of the storage layer and produces meaningful error messages.
Database Configuration
Full mapping form when you need explicit overrides or camelCase properties:
Multiple connections:
Reference non-autowired connection:
Documentation
The full Nette documentation for this topic is bundled with the plugin. Read a page when you need details beyond this skill:
- Nette Database – overview and choosing between SQL and Explorer
- Configuration – connections in NEON
- SQL Way – queries, placeholders, fetching
- Database Explorer – the Selection and ActiveRow API
- Transactions – transaction handling
- Type Conversion – how column values are converted
- Structure Reflection – reading tables, columns, keys
- Exceptions – the exception hierarchy
- Security Risks – what is and is not escaped
- Supported Databases – the list of drivers
- Pagination – paginating results with Paginator
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/nette/skills/nette-database/SKILL.md
Popularity
- Repository stars
- 37
- Repository forks
- 4
- 7-day trend score
- 18
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 21 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/nette/claude-code/nette-database)