agentleFS
AnyOrgNameAnyOrgName/php-skills/skills/codeigniter/query-builder/SKILL.md

query-builder

Skill4 starsChanged 4 months agoMITView on GitHub

Query data safely with the CodeIgniter 4 Query Builder — bound parameters and automatic escaping, fluent select and where clauses, and typed result access. Use when the user wants to build a SELECT, INSERT, UPDATE, or DELETE query in CodeIgniter 4 using the Query Builder; the user needs to fetch and iterate CodeIgniter query results as arrays, objects, or entity instances; the user needs to filter query results by user-supplied values without risking SQL injection. Keywords: codeigniter, query-builder, sql, escaping, input, results, database.

4 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

4 rules. 0 are common, 2 are distinctive, and 2 are very specific to this project.

  • 0

    Common

    Most of the 3 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not force complex window functions or vendor-specific analytical SQL through the builder.

    line 65
  2. Distinctive:

    Do not use this skill for schema changes (CREATE TABLE, ALTER).

    line 66
  3. Very specific:

    Run $rows = $builder->limit(50)->get()->getResultArray() and handle the empty case before using the rows.

    line 82
  4. Very specific:

    Use getResult() for objects, getResultArray() for arrays, and getRow() / getRowArray() for a single row.

    line 89

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- generated: do not edit — source: knowledge/atoms/codeigniter/query-builder/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->

CodeIgniter 4 Query Builder

When to use

  • The user wants to build a SELECT, INSERT, UPDATE, or DELETE query in CodeIgniter 4 using the Query Builder.
  • The user needs to fetch and iterate CodeIgniter query results as arrays, objects, or entity instances.
  • The user needs to filter query results by user-supplied values without risking SQL injection.

When NOT to use

  • Do not force complex window functions or vendor-specific analytical SQL through the builder; use a parameterized raw query.
  • Do not use this skill for schema changes (CREATE TABLE, ALTER); use Forge and migrations instead.

Core guidance

  • Allow-list dynamic column and table names — When a column, table, or sort direction comes from input, validate it against a fixed allow-list before passing it to the builder; escaping does not cover identifiers.
  • Pass values as arguments so the builder escapes them — Pass user values as the second argument to where(), like(), or insert() data arrays so the builder binds and escapes them; never concatenate them into the column or condition string.

Quick recipe

  1. Get a fresh builder with $builder = $db->table('users') and project columns via $builder->select('id, email, role'). (verify: The compiled SQL names only the requested columns)
  2. Filter with $builder->where('role', $role) passing the untrusted value as an argument so the builder binds and escapes it. (verify: The value appears as a bound parameter, not inlined text)
  3. Run $rows = $builder->limit(50)->get()->getResultArray() and handle the empty case before using the rows. (verify: An unmatched filter returns an empty array, not an error)

Best practices

  • Know that terminal calls like get() reset the builder, while getCompiledSelect() keeps state; start a fresh $db->table('t') per logical query to avoid leaked clauses
  • Use getResult() for objects, getResultArray() for arrays, and getRow() / getRowArray() for a single row; call getResult(Entity::class) to hydrate entities
  • Name the columns in select('id, name') instead of relying on SELECT *, and add limit() when the caller only needs a page of rows

Anti-patterns

Anti-patternWhy it failsDo instead
Manually escaping then binding againDouble escaping corrupts the value (extra quotes/backslashes) and signals a misunderstanding of the safe path.Pass raw values to the builder once; let it escape, or use escape() only for hand-written SQL strings.
Interpolating input into db->query()Interpolated input is executed as SQL, the classic injection vulnerability.Use query bindings — $db->query('... WHERE id = ?', [$id]) — or the builder's escaped where().
Selecting all columns and filtering in PHPPulling every column and row wastes memory and bandwidth and pushes work the database should do into the app.Project explicit columns, filter with where(), and page with limit()/offset().

See references/anti-patterns.md.

Common mistakes

  1. getRow returns null on no match — getRow() returns null when no row matches, not an empty object. Fix: Check the result for null and return a 404 or domain error before dereferencing.
  2. Querying inside a loop causes N+1 round trips — Running a builder query for each row of a parent result issues one query per iteration. Fix: Fetch related rows in one query with whereIn() or a join, then group in PHP.
  3. Concatenating input into a where string — Passing a fully-built string like where("email = '$email'") skips escaping. Fix: Use where('email', $email) so the builder binds and escapes the value.

Version notes

  • CI4 Query Builder replaces CI3 Active Record — CodeIgniter 4 renamed the CI3 "Active Record" class to the Query Builder, accessed via $db->table() and the connection service.

Security

  • Bind values and allow-list identifiers at the boundary — Treat every request-sourced value as untrusted: pass values as bound builder arguments (never string-concatenated), and validate any dynamic column, table, or sort identifier against a fixed allow-list.

Testing

  • Activation and decision behavior are verified in eval/scenarios/codeigniter/query-builder.yaml.

Additional resources

  • references/anti-patterns.md
  • references/core.md
  • references/examples.md
  • references/pitfalls.md
  • references/recipes.md
  • references/version-differences.md

Knowledge graph

Prerequisites: codeigniter/controllers
Related: security/sql-injection-prevention

<!-- graph-fragment: graph/fragments/codeigniter/query-builder.yaml -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.