Earlier commit captured a partial 196-record file because the background
research agent was still writing when the commit landed. The agent has
since completed with 323 high-quality records.
New distribution by kind:
121 code-recall · 97 workflow · 29 inikey · 26 comparison
16 gotcha · 16 debug · 15 edge-case · 3 refactor
All 323 lines are valid JSON, all carry instruction/input/output plus
metadata.{language, source, section, kind, citations}. Every answer has
a real file:line citation or quoted code from framework-reference-v2.md
(no hedging language allowed in agent output).
Effect on en-language corpus:
before: 1264 records per format
after: ~1545 records per format (+281 from augmentation × ~1)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
324 lines
223 KiB
JSON
324 lines
223 KiB
JSON
{"instruction":"What is the namespace prefix for autogenerated models in Nibiru and how does it map to disk?","input":"","output":"Autogenerated models live under `\\Nibiru\\Model\\<FolderName>\\<TableName>`. The folder name is derived from the database `basename` (PascalCased after splitting on `-` or `_`), and the file path is `application/model/<FolderName>/<TableName>.php`. Example: `\\Nibiru\\Model\\WarehouseLoach\\Timeanddate` lives at `/application/model/WarehouseLoach/timeanddate.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["framework-reference-v2.md §1","core/c/table.php:63","core/c/table.php:111"]}}
|
|
{"instruction":"Quick question: where does the `\\Nibiru\\Factory\\*` namespace map to on disk?","input":"","output":"`\\Nibiru\\Factory\\*` maps to `core/f/*.php`. These are the static factories — call signature is `ClassName::staticMethod()`. Example: `Db::loadModel('WarehouseLoach\\\\Timeanddate')` returns an `IDb`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["framework-reference-v2.md §1"]}}
|
|
{"instruction":"Where do module interfaces live and how do they get loaded?","input":"","output":"Module interfaces live at `application/module/[NAME]/interfaces/` and are registered as `\\Nibiru\\Module\\[Name]\\Interfaces\\*`. They are loaded by `Auto::loader()->loadModules()` if listed in the INI under `[AUTOLOADER] iface.pos[]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"workflow","citations":["framework-reference-v2.md §1","framework-reference-v2.md §4.2"]}}
|
|
{"instruction":"I'm trying to figure out which adapter namespace MySQL models extend — what is it?","input":"","output":"MySQL-driver models extend `\\Nibiru\\Adapter\\MySQL\\Db`, which lives at `core/a/mysql.db.php`. The generated model has `use Nibiru\\Adapter\\MySQL\\Db;` and `class <ClassName> extends Db`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["core/a/mysql.db.php:15","framework-reference-v2.md §1"]}}
|
|
{"instruction":"What interface guarantees model methods like `loadTableAsArray()` exist?","input":"","output":"`\\Nibiru\\Adapter\\IDb`, defined at `core/i/IDb.php`. It is implemented by all generated models and guarantees `loadTableAsArray()`, `updateRowById()`, `insertArrayIntoTable()`, `selectRowsetById()`, `selectDatasetByFieldWhere()`, `selectRowByFieldWhere()`, `lastInsertId()`, `deleteRowById()`, `updateRowByFieldWhere()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §1"]}}
|
|
{"instruction":"Are module plugin classes loaded before or after traits?","input":"","output":"Plugins are loaded last. The order is: interfaces (`iface.pos[]`), then traits (`trait.pos[]`), then modules (`class.pos[]`), then plugins (`class.plugin.pos[]`). Loaded by `Auto::loader()->loadModules()` and the order inside each array is significant.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["framework-reference-v2.md §4.3","framework-reference-v2.md §1"]}}
|
|
{"instruction":"Show me the signature of `Config::getInstance()`.","input":"","output":"```php\npublic static function getInstance(): Settings\n```\nDefined at `core/c/config.php:12`. It reads the environment via `getenv('APPLICATION_ENV')` (or the `APPLICATION_ENV` constant), calls `parent::setConfig(self::getEnv())` which parses the INI for that environment, and returns a singleton holding the entire application config array.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"code-recall","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"How does Nibiru pick which INI file to parse?","input":"","output":"It uses the template `settings.ENV.ini`, where `ENV` comes from `getenv('APPLICATION_ENV')` or the `APPLICATION_ENV` constant. Real filenames seen in production: `settings.development.ini`, `settings.production.ini`, `settings.cli.ini`, `settings.preproduction.ini`. The file is parsed with `parse_ini_file(..., true)` so each section becomes an associative array keyed by section name.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"workflow","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"How do I read a single INI value in code? Give me an example.","input":"","output":"```php\nConfig::getInstance()->getConfig()['DATABASE']['username']\nConfig::getInstance()->getConfig()['ENGINE']['templates']\nConfig::getInstance()->getConfig()['AUTOLOADER']['class.pos']\n```\nThe returned value is whatever `parse_ini_file(..., true)` produced for that section/key.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"code-recall","citations":["framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"What happens if I call `Config::getInstance()->getConfig()['MISSING_SECTION']['key']`?","input":"","output":"It returns `NULL` and emits no error. Then if you pipe that NULL into something like `array_key_exists($null_value, $array)` you'll get a warning about the wrong number of arguments. Always wrap nested INI accesses with `array_key_exists()` checks before reading.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.6 Missing INI Keys","kind":"gotcha","citations":["framework-reference-v2.md §11.6"]}}
|
|
{"instruction":"Show me the two static methods Pdo exposes for switching databases.","input":"","output":"```php\npublic static function settingsSection( $section = IOdbc::SETTINGS_DATABASE )\npublic static function getInstance( $section = false ): Mysql\n```\nDefined at `core/c/pdo.php:12`. `settingsSection()` writes to the static `Pdo::$section` variable (line 14); `getInstance()` returns the connection for that section.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:12","core/c/pdo.php:14","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"What happens if I call `Pdo::settingsSection('DATABASE_X')` and that section doesn't exist in the INI?","input":"","output":"`Mysql::__construct()` at `core/c/pdo.php` line 32 reads `$settings = Config::getInstance()->getConfig()[$section];`. If `DATABASE_X` is missing, the access yields `NULL`, so `$settings['username']`, `$settings['password']`, etc. are all NULL — connection construction will fail when PDO actually tries to connect with empty credentials. There is no defensive check inside the framework: missing INI section means a runtime error in PDO.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"edge-case","citations":["core/c/pdo.php:32","framework-reference-v2.md §2.2","framework-reference-v2.md §11.6"]}}
|
|
{"instruction":"Why do all my Pdo queries suddenly hit a different database after I instantiate one model?","input":"","output":"Because `Pdo::$section` is a **static** variable (`core/c/pdo.php:14`) and every model's `__construct()` writes to it. Last write wins per request. Example:\n```php\n$userModel = Db::loadModel('App\\User'); // Pdo::$section = 'DATABASE'\n$logs = Pdo::queryString('SELECT ...'); // queries DATABASE\n$adminModel = Db::loadModel('App\\Admin'); // Pdo::$section = 'DATABASE_ADMIN'\n$logs = Pdo::queryString('SELECT ...'); // queries DATABASE_ADMIN now\n```\nMitigation: explicitly call `Pdo::settingsSection('DATABASE')` before raw Pdo queries, or instantiate a model bound to that section.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.1 Pdo last-write-wins","kind":"gotcha","citations":["core/c/pdo.php:14","framework-reference-v2.md §11.1"]}}
|
|
{"instruction":"Show me the exact `__construct()` body the autogenerator produces for a MySQL model.","input":"","output":"```php\npublic function __construct()\n{\n Pdo::settingsSection('DATABASE');\n self::initTable( self::TABLE );\n}\n```\nFrom `loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php:30-34`. The first line writes the static `Pdo::$section`; the second registers the table schema with the adapter's static `$table` array.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php:30-34","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"Walk me through what happens when I call `Pdo::queryString('SELECT 1')` directly without instantiating a model first.","input":"","output":"`queryString()` routes through `parent::getInstance(self::getSettingsSection())->getConn()`. `getSettingsSection()` returns the static `Pdo::$section`. If no model has been instantiated yet, `Pdo::$section` still holds whatever it was last set to — typically the default `IOdbc::SETTINGS_DATABASE` (the string `\"DATABASE\"`). So a fresh request will query the `[DATABASE]` section unless a previous call mutated `Pdo::$section`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"workflow","citations":["core/c/pdo.php:14","core/c/pdo.php:19","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"What's the difference between `Db::loadModel('Acl')` and `new \\Nibiru\\Model\\Acl()`?","input":"","output":"`Db::loadModel('Acl')` runs the factory chain at `core/f/db.php:11`: `_setModel(\"Acl\")` builds `$fmodel = \"\\\\Nibiru\\\\Model\\\\\".$model` and does `self::$_model = new $fmodel;`, which fires the model's `__construct()` — and that constructor calls `Pdo::settingsSection('DATABASE')` (or whichever DBSECTION was baked in by the autogenerator). The factory returns the instance via `IDb`.\n\nDirect `new \\Nibiru\\Model\\Acl()` ALSO fires the same constructor (the `Pdo::settingsSection()` call still runs), but you skip the static `Db::$_model` registration and you don't get the IDb-typed return path. In practice: same DB-switch side effect; different return-type contract.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"comparison","citations":["core/f/db.php:11","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"Show me the `Db::loadModel()` pipeline step by step.","input":"","output":"From `core/f/db.php:11`:\n1. Call `Db::loadModel('WarehouseLoach\\\\Timeanddate')`.\n2. Internally: `_setModel(\"WarehouseLoach\\\\Timeanddate\")`.\n3. Constructs namespace: `$fmodel = \"\\\\Nibiru\\\\Model\\\\\".$model` → `\\Nibiru\\Model\\WarehouseLoach\\Timeanddate`.\n4. Instantiates: `self::$_model = new $fmodel;`.\n5. Returns: `self::getModel()`, the static `$_model`, typed as `IDb`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/f/db.php:11","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"Give me a real production usage of Db::loadModel for an insert.","input":"","output":"From `loach.mssql.database-connection/application/module/pdf/plugins/pdf.php`:\n```php\nuse Nibiru\\Factory\\Db;\n// ...\nDb::loadModel('WarehouseLoach\\Timeanddate')->insertArrayIntoTable([...]);\n$timeanddate_id = Db::loadModel('WarehouseLoach\\Timeanddate')->lastInsertId();\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["loach.mssql.database-connection/application/module/pdf/plugins/pdf.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"What return type does `Db::loadModel()` declare?","input":"","output":"```php\npublic static function loadModel( $modelName = \"\"): IDb\n```\nDefined at `core/f/db.php:11`. The `IDb` interface guarantees `loadTableAsArray()`, `selectRowsetById($id)`, `updateRowById(array, int, string)`, `insertArrayIntoTable($dataset)`, `selectDatasetByFieldWhere($fieldWhere, $sortOrder)`, `selectRowByFieldWhere($field)`, `lastInsertId()`, `deleteRowById(int)`, `updateRowByFieldWhere($wherefield, $wherevalue, $rowfield, $rowvalue)`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/f/db.php:11","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"I want to get the auto-increment ID right after an insert. How?","input":"","output":"Call `lastInsertId()` on a freshly loaded model. Real example:\n```php\nDb::loadModel('WarehouseLoach\\Timeanddate')->insertArrayIntoTable([...]);\n$timeanddate_id = Db::loadModel('WarehouseLoach\\Timeanddate')->lastInsertId();\n```\nNote both calls go through `Db::loadModel()` — each instantiation re-runs the model's `__construct()` and re-asserts `Pdo::settingsSection('DATABASE')`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"workflow","citations":["framework-reference-v2.md §2.3","loach.mssql.database-connection/application/module/pdf/plugins/pdf.php"]}}
|
|
{"instruction":"What does `Form::create()` actually do under the hood?","input":"","output":"It clears the static buffer `self::$form` so the form factory starts with an empty assembly state. Subsequent calls to `addInputType*`, `addType*`, `addSelect`, etc. each append HTML to that buffer; the final `addForm()` wraps the buffer in `<form>` tags via the `FIELDS` placeholder. From `core/f/form.php:41`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.4 Form Factory","kind":"code-recall","citations":["core/f/form.php:41","framework-reference-v2.md §2.4","framework-reference-v2.md §5.8"]}}
|
|
{"instruction":"Why does my form not save? I see `value` in the input but the controller gets nothing.","input":"","output":"Most likely cause: you used uppercase keys (`['VALUE' => 'x']`) where the framework expects lowercase, or vice versa. The form factory's substitution engine at `core/c/formattributes.php:48-58` does `str_replace(strtoupper($key), $entry, $this->getElement())` — so user keys must be **lowercase**, and the engine uppercases them internally to match template tokens. If you supplied `'NAME' => 'foo'` instead of `'name' => 'foo'`, `strtoupper('NAME')` is still `'NAME'` and works, but `'Name' => 'foo'` becomes `'NAME'` too. The deeper trap: only keys present in the Type class's `$_attributes` allowlist are substituted — any unrecognized key is silently dropped.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form substitution","kind":"debug","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"What's the basic usage pattern for the Form factory? Give me the canonical 5-line login form.","input":"","output":"```php\nForm::create();\nForm::addInputTypeText(['NAME' => 'email', 'ID' => 'email_field']);\nForm::addInputTypePassword(['NAME' => 'password']);\nForm::addInputTypeSubmit(['VALUE' => 'Login']);\n$html = Form::addForm(['METHOD' => 'POST', 'ACTION' => '/login']);\necho $html;\n```\nFrom the Quick Reference appendix. Note `addForm()` is the only method that returns HTML; everything else appends to the static `$form` buffer.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.4 Form Factory","kind":"code-recall","citations":["framework-reference-v2.md §2.4","framework-reference-v2.md Appendix Quick Reference"]}}
|
|
{"instruction":"How do I wrap a single input in a div without doing it manually?","input":"","output":"Pass a second `$div` argument — an associative array of attribute=>value pairs. Example:\n```php\nForm::addInputTypeText(['NAME' => 'username', 'ID' => 'user'], ['class' => 'form-group']);\n```\nThis emits:\n```html\n<div class=\"form-group\">\n<input type=\"text\" name=\"username\" id=\"user\">\n</div>\n```\nThe wrapper is single-shot — `assemble()` at `core/f/form.php:86-97` resets `self::$div` to `false` after one use.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div wrapping","kind":"workflow","citations":["core/f/form.php:86-97","core/f/form.php:120-140","framework-reference-v2.md §5.7"]}}
|
|
{"instruction":"What does Controller::getInstance() return?","input":"","output":"```php\npublic static function getInstance(): View|Controller\n```\nDefined at `core/c/controller.php:14`. The Controller class extends View, so the union return type reflects that the same singleton can be accessed as either.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"How do I read POST and GET parameters in a Nibiru controller?","input":"","output":"Use the helper methods on the Controller singleton:\n```php\n$email = $this->getPost('email'); // $_POST\n$page = $this->getGet('page'); // $_GET\n$param = $this->getRequest('param'); // $_REQUEST (POST/GET unified)\n$user = $this->getSession('user');\n$ip = $this->getServer('REMOTE_ADDR');\n$file = $this->getFiles('upload');\n```\nDefined at `core/c/controller.php:14` and following.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"How does `View::assign()` work and how do I use the values in a Smarty template?","input":"","output":"```php\nView::assign(['user_name' => 'John', 'role' => 'admin']);\n```\nIn the Smarty template you reference them with the dollar-prefix: `{$user_name}`, `{$role}`. From `core/c/view.php:11` and the Smarty wrapper.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"How do I do a server-side redirect to a JSON response from a Nibiru controller?","input":"","output":"`View::forwardToJsonHeader(string $encoding = \"\")` sends the JSON content-type headers. The constants `IView::NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\"` and `NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\"` are used in this path. Defined at `core/c/view.php:11`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","core/i/IView.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"Where does the Smarty template directory get configured?","input":"","output":"In `core/c/view.php:66-79` (the `_setEngine()` block). It reads from the INI:\n- Template dir: `core/c/../../{ENGINE[templates]}`\n- Compile dir: `core/c/../../{ENGINE[templates_c]}`\n- Cache dir: `core/c/../../{ENGINE[cache]}`\n- Config dir: `core/c/../../{ENGINE[config_dir]}`\n- Debug template: `{ENGINE[debug_template]}`\n- Caching: if `ENGINE[caching]==true`, set to `CACHING_LIFETIME_CURRENT`","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"code-recall","citations":["core/c/view.php:66-79","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"What `.tpl` constant does the framework use to identify templates?","input":"","output":"`IView::NIBIRU_FILE_END = \".tpl\"`. `View::display($page)` checks if `$page` ends with this constant before handing off to Smarty. Defined in `core/i/IView.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"inikey","citations":["core/i/IView.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"How does Nibiru pick which database driver to use?","input":"","output":"From the INI's `[GENERATOR][driver]` or `[DATABASE*][driver]` field:\n- `driver = \"mysql\"` → uses `Pdo`, adapter is `\\Nibiru\\Adapter\\MySQL\\Db`.\n- `driver = \"psql\"` → uses `Postgres`, adapter is `\\Nibiru\\Adapter\\Postgres\\Db` (UnixODBC path).\n- `driver = \"postgresql\"` → uses `Postgresql`, adapter is `\\Nibiru\\Adapter\\Postgresql\\Db` (libpq path).\nThe choice is consumed by the autogenerator at `core/c/model.php:115-132`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"inikey","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.1","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Show me the abstract base adapter class that all generated MySQL models extend.","input":"","output":"```php\nabstract class Db implements IDb\n{\n private static $table = array();\n\n protected static function initTable( $table = array() )\n protected static function getTable()\n}\n```\nFrom `core/a/mysql.db.php:15`. Generated models call `self::initTable( self::TABLE )` from their `__construct()` to register the schema.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"code-recall","citations":["core/a/mysql.db.php:15","framework-reference-v2.md §3.1"]}}
|
|
{"instruction":"What's the structure of the TABLE constant in a generated model?","input":"","output":"```php\nconst TABLE = array(\n 'table' => 'tablename',\n 'fields' => ['id' => 'id', 'name' => 'name', ...]\n);\n```\nThe `'table'` key holds the raw table name; the `'fields'` array is a `field => field` mapping (key and value identical) used by the adapter's `getTable()` lookups. Built by the generator at `core/c/model.php:80-104`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"code-recall","citations":["core/c/model.php:80-104","framework-reference-v2.md §3.1"]}}
|
|
{"instruction":"Is the autogenerator a CLI tool or does it run on every request?","input":"","output":"It runs on every web request (not a CLI tool). The trigger lives in `core/c/dispatcher.php:35-39`:\n```php\nif(Config::getInstance()->getConfig()[self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE])\n{\n new Model( false );\n}\n```\nWith `[GENERATOR] database = true` in the INI, `new Model(false)` fires on every page load. Production turns it off by setting `[GENERATOR] database = false`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/dispatcher.php:35-39","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Is there a standalone CLI script that runs the autogenerator without booting the dispatcher?","input":"","output":"No. `grep -rn \"new Model(\"` finds only `dispatcher.php:38`. `Table::__construct($argv)` parses argv-style flags (`--table=…`, `--config-section=…`, `--folder-out=…`, `--help`) at `core/c/table.php:48-70`, but the shipped framework only ever calls `new Model(false)` — `false` is passed straight through to `Table::__construct` at `core/c/model.php:18`, so `is_array($argv)` at `table.php:51` is false and no flags are parsed. Dev-mode autogeneration uses INI defaults only.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["core/c/dispatcher.php:38","core/c/model.php:18","core/c/table.php:48-70","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Walk me through the full call chain from `Dispatcher::run()` to a generated model file.","input":"","output":"```\nDispatcher::run() core/c/dispatcher.php:38 -> new Model(false)\n Model::__construct(false) core/c/model.php:14\n early-bail at line 16 if [DATABASE][is.active] != true\n parent::__construct($argv) core/c/model.php:18 -> Table::__construct\n Table::__construct($argv) core/c/table.php:48\n _setParams() reads CLI flags (no-op when $argv === false)\n _setConfigSection() table.php:162 reads --config-section or [GENERATOR][config-section]\n _setDatabaseDriver() table.php:148 $driver = config[$configSection][driver]\n _setDatabase() table.php:194 $dbName = config[$configSection][basename]\n _setDbNamespace() table.php:63 PascalCase the basename\n _setFolderNamespace() table.php:111 split on '-' or '_', ucfirst each segment\n _setFolderOut() table.php:208 --folder-out OR __DIR__ + [GENERATOR][folder-out] + foldernamespace\n _setTable() picks --table flag, or empty (= scan all)\n _setTemplateFile() table.php:67 [GENERATOR][modeltemplate]\n _setModelTemplate() slurps mask file\n _setTables() SHOW TABLES (MySQL) or information_schema (Postgres)\n createOutFolder() core/c/model.php:28 mkdir -p with chmod 0777\n createClassFiles() core/c/model.php:37\n generateClassByTableName($table) core/c/model.php:53\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/dispatcher.php:38","core/c/model.php:14","core/c/table.php:48","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How does the autogenerator turn a table name like `user_to_acl` into a class name?","input":"","output":"From `core/c/model.php:57-69`:\n```php\n$pclassname = explode('_', $table);\n$classname = \"\";\nfor($i=0; count($pclassname)>$i; $i++) {\n if($i!=0) $classname .= ucfirst($pclassname[$i]);\n else $classname = $pclassname[$i];\n}\n```\nThe first underscore-separated segment is kept as-is; subsequent segments are `ucfirst`-ed. Then a final `ucfirst($classname)` is applied at line 111. So `user_to_acl` -> `userToAcl` -> final `UserToAcl`. `time_and_date` -> `timeAndDate` -> `TimeAndDate`. `timeanddate` -> `timeanddate` -> `Timeanddate`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:57-69","core/c/model.php:111","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What happens to my hand-edits to a generated model when `[GENERATOR][database.overwrite] = true`?","input":"","output":"They're destroyed on every request. From `core/c/model.php:70-74`:\n```php\nif(Config::getInstance()->getConfig()[self::CONFIG_SECTION][self::DB_OVERWRITE_MODELS]) {\n unlink($this->getFolderOut() . '/' . $classname . self::PHP_FILE_ENDING);\n}\n```\nThe existing `.php` file is `unlink`ed before regeneration. Mitigation: keep `database.overwrite = false` (the safe default) and only delete the file you want rebuilt.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/model.php:70-74","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"In safe (non-overwrite) mode, how does the generator decide whether to write a file?","input":"","output":"It checks `filesize() == 0` rather than `file_exists()`. Step 2 of `generateClassByTableName()` does `fclose( fopen(..., 'w') )` to create an empty file, then step 6 checks:\n```php\nif(!filesize(...)) {\n file_put_contents(...);\n}\n```\nFrom `core/c/model.php:133-145`. Workflow: delete the model file you want regenerated -> reload the page -> file is recreated with fresh schema.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/model.php:133-145","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What setter name does the autogenerator produce for a column named `user_first_name`?","input":"","output":"`_setUserfirstname` — single capital, no inner caps. The generator uses `str_replace('_', '', ucfirst($field))` which strips ALL underscores first, then `ucfirst` capitalizes only the first letter. So `user_first_name` becomes `_setUserfirstname`, NOT `_setUserFirstName`. From `core/c/model.php:80-104` (§3.2 step 3).","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/model.php:80-104","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"List the eight placeholder substitutions the autogenerator makes in the mask file.","input":"","output":"From `core/c/model.php:106-113`:\n| Placeholder | Source |\n|---|---|\n| `[CLASSPARAMETERS]` | `$parameters` (concatenated `private $field;` lines) |\n| `[FIELDARRAY]` | `$fieldarray` (concatenated `'k' => 'v',` lines) |\n| `[SETTERS]` | `$setters` |\n| `[GETTERS]` | `$getters` |\n| `[TABLE]` | raw table name |\n| `[CLASSNAME]` | `ucfirst($classname)` |\n| `[FOLDERNAME]` | `ucfirst($this->getFolderNamespace())` |\n| `[DBSECTION]` | `$this->getConfigSection()` |\n\nThen step 5 substitutes `[ADAPTER]` and `[CONNECTOR]` based on driver.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:106-113","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What values does the generator substitute into `[ADAPTER]` and `[CONNECTOR]` for a Postgres model with `odbc=true`?","input":"","output":"From `core/c/model.php:115-132`:\n```php\nif($this->getDatabaseDriver()==self::DB_DRIVER_POSTGRESS) {\n if(Config::getInstance()->getConfig()[self::CONFIG_SECTION]['odbc']) {\n $template = str_replace('[ADAPTER]', self::ADAPTER_POSTGRES, $template);\n $template = str_replace('[CONNECTOR]', self::ADAPTER_POSTGRES, $template);\n } else {\n $template = str_replace('[ADAPTER]', self::ADAPTER_POSTGRESQL, $template);\n $template = str_replace('[CONNECTOR]', self::ADAPTER_POSTGRESQL, $template);\n }\n}\n```\nWith `odbc=true`, both placeholders become `Postgres`. With `odbc` falsy/missing, both become `Postgresql`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What does `[CONNECTOR]` resolve to for a `driver = \"mysql\"` model?","input":"","output":"`Pdo`. From `core/c/model.php:115-132`:\n```php\nif($this->getDatabaseDriver()==self::DB_DRIVER_MYSQL) {\n $template = str_replace('[ADAPTER]', self::ADAPTER_MYSQL, $template);\n $template = str_replace('[CONNECTOR]', self::ADAPTER_PDO, $template);\n}\n```\nSo for MySQL, `[ADAPTER]` becomes `MySQL` and `[CONNECTOR]` becomes `Pdo`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"I'm getting `Class 'Nibiru\\Postgres' not found` from a generated Postgres model. What's wrong?","input":"","output":"The Postgres-mode footgun in the mask file. `application/settings/db/db.class.mask` line 4 is:\n```php\nuse Nibiru\\Pdo;\n```\nThat import is hardcoded regardless of driver. For MySQL output it's correct (`[CONNECTOR]` -> `Pdo` matches the import). For Postgres, `[CONNECTOR]` substitutes to `Postgres` or `Postgresql`, but the import line still reads `use Nibiru\\Pdo;`. The unqualified `Postgres::settingsSection(...)` call then resolves against the current namespace (`Nibiru\\Model\\<Folder>\\Postgres`), not `\\Nibiru\\Postgres`, and PHP fatal-errors at request time.\n\nFix: manually patch the generated `use` line to `use Nibiru\\Postgres;` (or `Postgresql`), or change the mask to use a `[CONNECTOR_USE]` placeholder. Confirmed at `core/c/pdo.php:2`, `core/c/postgres.php:3`, `core/c/postgresql.php:2` that all three live in the `\\Nibiru` root namespace.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"debug","citations":["application/settings/db/db.class.mask:4","core/c/pdo.php:2","core/c/postgres.php:3","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Show me the verbatim contents of the model mask file.","input":"","output":"```php\n<?php\nnamespace Nibiru\\Model\\[FOLDERNAME];\nuse Nibiru\\Adapter\\[ADAPTER]\\Db;\nuse Nibiru\\Pdo;\n\nclass [CLASSNAME] extends Db\n{\n\n [CLASSPARAMETERS]\n\n const TABLE = array(\n 'table' => '[TABLE]',\n 'fields' => [FIELDARRAY]\n );\n\n public function __construct()\n {\n [CONNECTOR]::settingsSection('[DBSECTION]');\n self::initTable( self::TABLE );\n }\n\n public function getTableInfo()\n {\n return self::TABLE;\n }\n\n [SETTERS]\n\n [GETTERS]\n}\n```\nFrom `application/settings/db/db.class.mask` (48 lines). Ten distinct placeholders: `[FOLDERNAME]`, `[ADAPTER]`, `[CLASSNAME]`, `[CLASSPARAMETERS]`, `[TABLE]` (x2), `[FIELDARRAY]`, `[CONNECTOR]`, `[DBSECTION]`, `[SETTERS]`, `[GETTERS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["application/settings/db/db.class.mask","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Show me a verified sample of generated model output for a `timeanddate` table.","input":"","output":"For table `timeanddate`, folder namespace `WarehouseLoach`, driver `mysql`, config-section `DATABASE`:\n```php\n<?php\nnamespace Nibiru\\Model\\WarehouseLoach;\nuse Nibiru\\Adapter\\MySQL\\Db;\nuse Nibiru\\Pdo;\n\nclass Timeanddate extends Db\n{\n private $timeanddate_id;\n private $timeanddate_date;\n private $timeanddate_time;\n\n const TABLE = array(\n 'table' => 'timeanddate',\n 'fields' => array(\n 'timeanddate_id' => 'timeanddate_id',\n 'timeanddate_date' => 'timeanddate_date',\n 'timeanddate_time' => 'timeanddate_time'\n )\n );\n\n public function __construct()\n {\n Pdo::settingsSection('DATABASE');\n self::initTable( self::TABLE );\n }\n\n public function getTableInfo() { return self::TABLE; }\n\n public function _setTimeanddateid($timeanddate_id) { $this->timeanddate_id = $timeanddate_id; }\n public function getTimeanddateid() { return $this->timeanddate_id; }\n}\n```\nVerified against `loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["loach.mssql.database-connection/application/model/WarehouseLoach/timeanddate.php","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What value of `[GENERATOR][config-section]` does Nibiru default to?","input":"","output":"`\"DATABASE\"`. From `application/settings/config/settings.development.ini:78-86`:\n```ini\n[GENERATOR]\ndatabase = true\ndatabase.overwrite = false\nconfig-section = \"DATABASE\"\nfolder-out = \"/../../application/model/\"\nmodeltemplate = \"/../../application/settings/db/db.class.mask\"\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["application/settings/config/settings.development.ini:78-86","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Why do `folder-out` and `modeltemplate` in `[GENERATOR]` start with `/../../`?","input":"","output":"Because both are resolved as `__DIR__ . $value` where `__DIR__` is `core/c/`. From `core/c/table.php:217` (folder-out) and `core/c/table.php:67` (modeltemplate). The `/../../` walks up out of `core/c/` to the project root, then into the application path.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["core/c/table.php:217","core/c/table.php:67","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the typo in the Postgres driver constant name?","input":"","output":"`DB_DRIVER_POSTGRESS = \"psql\"` — note the two S's in `POSTGRESS`. Defined at `core/c/table.php:20-26` alongside `DB_DRIVER_MYSQL = \"mysql\"`, `ADAPTER_POSTGRES`, `ADAPTER_POSTGRESQL`, `ADAPTER_MYSQL`, `ADAPTER_PDO`. The INI value is the conventional `psql`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/table.php:20-26","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"I want to talk to two MySQL databases at once. What does the INI look like and how do I generate the models?","input":"","output":"INI:\n```ini\n[DATABASE]\nis.active = true\nbasename = \"warehouse_loach\"\ndriver = \"mysql\"\nhostname = \"db-primary\"\nusername = \"user\"\npassword = \"pass\"\n\n[DATABASE_SECONDARY]\nis.active = true\nbasename = \"other_db\"\ndriver = \"mysql\"\nhostname = \"db-secondary\"\nusername = \"user2\"\npassword = \"pass2\"\n```\nGenerate Model A with `[GENERATOR][config-section] = \"DATABASE\"`, then flip the INI to `\"DATABASE_SECONDARY\"` and reload. Each generated `__construct()` will hard-bake the right `Pdo::settingsSection('DATABASE')` or `Pdo::settingsSection('DATABASE_SECONDARY')` line.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["framework-reference-v2.md §3.3"]}}
|
|
{"instruction":"Quick question: can I switch databases without instantiating a model?","input":"","output":"Yes — call `Pdo::settingsSection()` directly:\n```php\nPdo::settingsSection('DATABASE_SECONDARY');\n$data = Pdo::queryString('SELECT * FROM table_name');\n```\nThe static `Pdo::$section` is what every Pdo query reads via `self::getSettingsSection()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["core/c/pdo.php:14","framework-reference-v2.md §3.3"]}}
|
|
{"instruction":"How would I switch one model in a multi-database setup from `[DATABASE]` to `[DATABASE_REPORTING]` without breaking the others?","input":"","output":"Regenerate just that one model with the autogenerator pointed at the new config section. Workflow:\n1. Add `[DATABASE_REPORTING]` block to the INI alongside `[DATABASE]`.\n2. Temporarily set `[GENERATOR][config-section] = \"DATABASE_REPORTING\"` and `database.overwrite = true`, OR delete the single model file you want rebuilt while keeping `database.overwrite = false`.\n3. Hit any URL — `Dispatcher::run()` regenerates the model. Its `__construct()` will now contain `Pdo::settingsSection('DATABASE_REPORTING')`.\n4. Reset `[GENERATOR][config-section]` back to `\"DATABASE\"` so subsequent regenerations of other models don't get the wrong section.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"refactor","citations":["framework-reference-v2.md §3.3","framework-reference-v2.md §11.1"]}}
|
|
{"instruction":"How expensive is it to instantiate multiple models in a request?","input":"","output":"Effectively free. The framework uses a lazy singleton per-section: `parent::getInstance(self::getSettingsSection())` returns the cached connection for that section. Instantiating a second model that references `'DATABASE_SECONDARY'` opens at most one new connection (the first time), and reusing it is just a static lookup.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["framework-reference-v2.md §3.3","core/c/pdo.php:19"]}}
|
|
{"instruction":"What's the standard module directory layout in Nibiru?","input":"","output":"```\napplication/module/users/\n users.php # Main class\n interfaces/\n users.php # IUsers interface\n progressObserver.php # IProgressObserver interface\n traits/\n users.php # Users trait\n userForm.php # UserForm trait\n plugins/\n user.php # User plugin class\n acl.php # ACL plugin class\n```\nFrom `framework-reference-v2.md §4.1`. The main class file is named after the module folder (lowercase) and lives at the root of the module directory.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.1 Module Structure","kind":"workflow","citations":["framework-reference-v2.md §4.1"]}}
|
|
{"instruction":"Show me a real `[AUTOLOADER]` INI registry from production.","input":"","output":"From `develop.maschinen-stockert.de/application/settings/config/settings.development.ini:10-72`:\n```ini\n[AUTOLOADER]\nclass.pos[] = \"observer\"\nclass.pos[] = \"users\"\nclass.pos[] = \"memcached\"\nclass.pos[] = \"assetmanager\"\nclass.pos[] = \"cms\"\n\niface.pos[] = \"observer\"\niface.pos[] = \"users\"\niface.pos[] = \"cms\"\n\ntrait.pos[] = \"observer\"\ntrait.pos[] = \"users\"\ntrait.pos[] = \"userForm\"\ntrait.pos[] = \"cms\"\n\nclass.plugin.pos[] = \"progressTracker\"\nclass.plugin.pos[] = \"observer\"\nclass.plugin.pos[] = \"user\"\nclass.plugin.pos[] = \"acl\"\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"4.2 Module Registry","kind":"code-recall","citations":["develop.maschinen-stockert.de/application/settings/config/settings.development.ini:10-72","framework-reference-v2.md §4.2"]}}
|
|
{"instruction":"What does each `[AUTOLOADER]` array key control?","input":"","output":"- `class.pos[]` — array of module names to load (order matters).\n- `iface.pos[]` — which interfaces to scan for each module name.\n- `trait.pos[]` — which traits to scan for each module name.\n- `class.plugin.pos[]` — which plugins to scan/load (order matters; loaded last).\nAll consumed by `Auto::loader()->loadModules()` at `core/c/auto.php`. From `framework-reference-v2.md §4.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.2 Module Registry","kind":"inikey","citations":["framework-reference-v2.md §4.2"]}}
|
|
{"instruction":"Walk me through how `Auto::loadModules()` actually loads files.","input":"","output":"From `core/c/auto.php` (by extension of `Dispatcher::run()` line 43):\n1. Read INI `AUTOLOADER[iface.pos]` — array of interface names.\n2. For each interface name, scan `application/module/[modulename]/interfaces/` for matching files.\n3. `require_once` each found file.\n4. Repeat for traits, then modules, then plugins.\n\nThe order in the INI dictates the order of `require_once` calls within each category.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["core/c/auto.php","core/c/dispatcher.php:43","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"What's the minimum requirement for a module main class?","input":"","output":"It must implement `IModule` (from `core/i/IModule.php`). It may optionally implement `SplSubject` (Observer pattern). Real example from `develop.maschinen-stockert.de/application/module/users/users.php:20-32`:\n```php\nclass Users extends Module implements Interfaces\\Users, SplSubject\n{\n use Traits\\Users;\n protected static object $usersRegistry;\n protected SplObjectStorage $observers;\n\n public function __construct()\n {\n $this->setUsersRegistry();\n $this->observers = new SplObjectStorage();\n }\n}\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["develop.maschinen-stockert.de/application/module/users/users.php:20-32","core/i/IModule.php","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"Show me a real plugin class that uses `Db::loadModel`.","input":"","output":"From `loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40`:\n```php\nuse Nibiru\\Factory\\Db;\n\nclass Acl extends User\n{\n public function __construct()\n {\n parent::__construct();\n }\n\n public function init(): void\n {\n if(!$this->validate())\n {\n View::forwardTo('/users/login');\n }\n else\n {\n $this->loadUserRole();\n }\n }\n}\n```\nLater: `$acl = Db::loadModel('WarehouseLoach\\Acl');` — instantiating sets `Pdo::$section = 'DATABASE'` via the model's `__construct()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.4 Plugin Pattern","kind":"code-recall","citations":["loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40","framework-reference-v2.md §4.4"]}}
|
|
{"instruction":"Walk me through the module lifecycle on a request.","input":"","output":"From `framework-reference-v2.md §4.5`:\n1. INI parse: Dispatcher reads `[AUTOLOADER]` section.\n2. Model load: `Auto::loader()->loadModelFiles()` requires all model files.\n3. Module load: `Auto::loader()->loadModules()` scans and requires interfaces, traits, modules, plugins in order.\n4. Controller load: if route matches, require and instantiate the controller.\n5. Action call: if `_action` param exists and a matching `*Action()` method exists, call it.\n\nImplicit hooks: each module class's constructor, each plugin class's constructor, the controller's action method.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.5 Module Lifecycle","kind":"workflow","citations":["framework-reference-v2.md §4.5"]}}
|
|
{"instruction":"My new module isn't loading. What's the most common cause?","input":"","output":"You forgot to register it in the INI's `[AUTOLOADER] class.pos[]`. The autoloader is NOT PSR-4 — it does NOT follow `composer.json` mapping. It scans directories driven by INI keys. Without `class.pos[] = \"yourmodule\"` in the `[AUTOLOADER]` block, `Auto::loader()->loadModules()` never visits the directory. From `framework-reference-v2.md §11.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.7 Autoloader not PSR-4","kind":"debug","citations":["framework-reference-v2.md §11.7"]}}
|
|
{"instruction":"My late-registered module's constructor blows up because it depends on an earlier module. What's wrong?","input":"","output":"Module loading order is dictated by INI array order, not by dependencies. Example:\n```ini\n[AUTOLOADER]\nclass.pos[] = \"late_module\"\nclass.pos[] = \"early_module\"\n```\n`late_module` constructor runs first; if it depends on `early_module` being initialized, you get a silent failure. Mitigation: order INI entries carefully with dependents AFTER dependencies. From `framework-reference-v2.md §11.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.4 Module Loading Order","kind":"gotcha","citations":["framework-reference-v2.md §11.4"]}}
|
|
{"instruction":"What namespace does a trait in module `users` end up under?","input":"","output":"`\\Nibiru\\Module\\Users\\Traits\\<TraitName>` — file at `application/module/users/traits/<traitname>.php`. From `framework-reference-v2.md §8`. Example: trait `UserForm` in module `users` is `\\Nibiru\\Module\\Users\\Traits\\UserForm` at `application/module/users/traits/userForm.php`.","metadata":{"language":"en","source":"framework-reference-v2","section":"8 Namespace Conventions","kind":"workflow","citations":["framework-reference-v2.md §8"]}}
|
|
{"instruction":"What are the four collaborating files in the form system architecture?","input":"","output":"From `framework-reference-v2.md §5.1`:\n| Role | File | Owns |\n|---|---|---|\n| Factory (static buffer + 30 `add*` methods) | `core/f/form.php` | `\\Nibiru\\Factory\\Form` |\n| Per-element template + allowlist | `core/c/type*.php` (28 files) | `\\Nibiru\\Form\\Type<X>` |\n| Substitution engine | `core/c/formattributes.php` | `\\Nibiru\\Form\\FormAttributes` |\n| Constant catalog | `core/i/IForm.php` | 60+ `FORM_*` constants |\n\nThe factory has zero knowledge of HTML — it manages the buffer and dispatches to a Type class. Each Type is an attribute allowlist plus a template string.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/f/form.php","core/c/formattributes.php","core/i/IForm.php","framework-reference-v2.md §5.1"]}}
|
|
{"instruction":"Show me the literal template string `TypeText` uses.","input":"","output":"```php\n$this->_element = '<input type=\"text\" name=\"NAME\" value=\"VALUE\" placeholder=\"PLACEHOLDER\" maxlength=\"MAXLENGTH\" tabindex=\"TABINDEX\" required=\"REQUIRED\" disabled=\"DISABLED\" data-bts-decimals=\"DATA-BTS-DECIMALS\" data-bts-step=\"DATA-BTS-STEP\" SPEECH ID CLASS>';\n```\nFrom `core/c/typetext.php:42`. The UPPERCASE tokens are substituted by `FormAttributes::_setAttributes()` for whatever lowercase key the user passed.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/c/typetext.php:42","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"How does the form substitution engine actually replace attributes?","input":"","output":"From `core/c/formattributes.php:48-58`:\n```php\nforeach( $attributes as $key=>$entry ) {\n switch ($key) {\n case array_key_exists($key, $this->_attributes):\n $this->_element = str_replace(strtoupper($key), $entry, $this->getElement());\n break;\n }\n}\n```\nTwo non-obvious facts:\n1. The `switch ($key) { case array_key_exists(...) }` form works because `case` compares its expression to `$key` and `array_key_exists()` returns a boolean. So only allowlisted keys substitute — unknown keys are silently dropped.\n2. `strtoupper($key)` is plain ASCII; user keys must be lowercase (`name`, `data-bts-decimals`).","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"How does the form factory clean up unused placeholders so I don't get `required=\"REQUIRED\"` in my output?","input":"","output":"After the substitution loop, `core/c/formattributes.php:59-102` runs ~50 hard-coded `str_replace()` calls that strip unused placeholders. Example at line 84:\n```php\n$this->_element = str_replace(' required=\"REQUIRED\"', '', $this->_element);\n```\nIf the user didn't pass `required`, the literal `REQUIRED` was never substituted, so this line removes the whole ` required=\"REQUIRED\"` fragment. The leading space matters — it prevents collapsing two attributes. There's also `str_replace(' ', ' ', ...)` at line 87 to fold double-spaces.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/c/formattributes.php:59-102","core/c/formattributes.php:84","core/c/formattributes.php:87","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"Why does `id`, `class`, `form` work differently from other form attributes?","input":"","output":"They're bare-word tokens in the templates (`ID`, `CLASS`, `FORM`), not `id=\"ID\"`. The trait at `core/t/form.php:14` rewrites the user's value into `' id=\"x\"'` before substitution, so the final HTML reads `<input id=\"user_email\">` rather than `<input id=\" id=\\\"user_email\\\"\">`. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"code-recall","citations":["core/t/form.php:14","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"I passed `'checked' => true` to a checkbox and got `checked=\"CHECKED\"` in the HTML. Why?","input":"","output":"Because the substitution engine literally swaps `CHECKED` for whatever you passed. There is no path that emits a clean bare `checked` (without the `=\"CHECKED\"` value). The strip rule at `core/c/formattributes.php:63-67` only removes `checked=\"CHECKED\"` when the user did NOT pass `checked` (i.e. passed `false`/empty). Production code accepts the `checked=\"CHECKED\"` rendering — browsers treat it as a truthy attribute. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"gotcha","citations":["core/c/formattributes.php:63-67","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"What's the four-step recipe every Type class follows?","input":"","output":"`__construct` (register allowlist) -> `_setElement` (load template) -> `loadAttributeValues` (pre-format `id`/`class`/`form`) -> `_setAttributes` (substitute + strip). Identical across all 28 Type classes — only the contents of `$_attributes` and `$_element` vary. Code from `core/c/typetext.php`:\n```php\npublic function loadElement( $attributes )\n{\n parent::__construct( $this->_attributes );\n $this->_setElement();\n $this->_setAttributes( self::loadAttributeValues( $attributes ) );\n return $this->getElement();\n}\n```\nFrom `framework-reference-v2.md §5.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.3 Type Class Anatomy","kind":"code-recall","citations":["core/c/typetext.php","framework-reference-v2.md §5.3"]}}
|
|
{"instruction":"What does TypeText's allowlist look like?","input":"","output":"```php\nprivate $_attributes = array(\n self::FORM_NAME => '',\n self::FORM_VALUE => '',\n self::FORM_ATTRIBUTE_SPEECH => '',\n self::FORM_ATTRIBUTE_ID => '',\n self::FORM_ATTRIBUTE_CLASS => '',\n self::FORM_ATTRIBUTE_PLACEHOLDER => '',\n self::FORM_ATTRIBUTE_REQUIRED => '',\n self::FORM_ATTRIBUTE_MAXLENGTH => '',\n self::FORM_ATTRIBUTE_TABINDEX => '',\n self::FORM_ATTRIBUTE_DISABLED => '',\n self::FORM_ATTRIBUTE_TS_DECIMALS => '',\n self::FORM_ATTRIBUTE_TS_STEPS => ''\n);\n```\nFrom `core/c/typetext.php`. Any key not in this array is silently dropped by the substitution engine.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.3 Type Class Anatomy","kind":"code-recall","citations":["core/c/typetext.php","framework-reference-v2.md §5.3"]}}
|
|
{"instruction":"What's the difference between `addInputType*`, `addType*`, and `add*` in the Form factory?","input":"","output":"Three different naming patterns with no semantic justification — historical drift:\n- `addInputType*` for: Text, Submit, Textarea, Radio, Checkbox, Switch, Password, Date, Email, Color, Datetime.\n- `addType*` for: FileUpload, Hidden, ImageSubmit, Number, Range, Reset, Search, Telefon, Url, Button, Label.\n- `add*` (no Type prefix) for: Form, Select, SelectOption, OpenDiv, CloseDiv, OpenAny, CloseAny.\n\nDon't normalize them — callers expect the literal names. From `framework-reference-v2.md §5.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.5 Naming Inconsistency","kind":"comparison","citations":["framework-reference-v2.md §5.5"]}}
|
|
{"instruction":"What does TypeOption's template string look like?","input":"","output":"```\n<option value=\"VALUE\" ID CLASS SELECTED>CONTEXT</option>\n```\nFrom `core/c/typeoption.php:35`. The `CONTEXT` placeholder holds the visible text (e.g. `'context' => 'Admin'`); `VALUE` is the form-submitted value.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeoption.php:35","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What does TypeSelect's template look like?","input":"","output":"```\n<select name=\"NAME\" onchange=\"ONCHANGE\" onblur=\"ONBLUR\" onfocus=\"ONFOCUS\" required=\"REQUIRED\" ID CLASS SELECTED>\nOPTIONS\n</select>\n```\nFrom `core/c/typeselect.php:37`. The `OPTIONS` token is what `Form::displaySelect()` (`core/f/form.php:71`) replaces with the accumulated option HTML.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeselect.php:37","core/f/form.php:71","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"My `<select>` is rendering empty. I'm calling addSelect first, then addSelectOption — what's wrong?","input":"","output":"Order matters: options must be added BEFORE the select. The buffer flow at `core/f/form.php:493-497`:\n```php\npublic static function addSelectOption( $attributes ) {\n self::setElement( new TypeOption() );\n self::assembleOptions( self::getElement()->loadElement( $attributes ) );\n}\n```\nappends to a separate `self::$option` buffer. Then `addSelect` at lines 463-472 renders the select template with `OPTIONS` token replaced by that buffer, and clears it for the next select via `assembleOptions(false)`. Reverse the order and `OPTIONS` is empty. From `framework-reference-v2.md §5.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.6 Select/Option Ordering","kind":"debug","citations":["core/f/form.php:493-497","core/f/form.php:463-472","framework-reference-v2.md §5.6"]}}
|
|
{"instruction":"Show me the addSelect implementation.","input":"","output":"```php\npublic static function addSelect( $attributes, $div = false ) {\n if($div!=false) self::setDiv( $div );\n self::setElement( new TypeSelect() );\n self::assemble( self::displaySelect( self::getElement()->loadElement( $attributes ) ) );\n self::assembleOptions( false ); // reset for the next select\n}\n```\nFrom `core/f/form.php:463-472`. `displaySelect()` at line 71: `return str_replace( 'OPTIONS', self::$option, $select );`","metadata":{"language":"en","source":"framework-reference-v2","section":"5.6 Select/Option Ordering","kind":"code-recall","citations":["core/f/form.php:463-472","core/f/form.php:71","framework-reference-v2.md §5.6"]}}
|
|
{"instruction":"How is the per-element div wrapper implemented?","input":"","output":"From `core/f/form.php:120-140`:\n```php\nprivate static function setDiv( $div = false ) {\n if($div != false) {\n if( is_array( $div ) ) {\n foreach ( $div as $key=>$selector ) {\n self::$div = '<div ' . $key . '=\"' . $selector . '\">' . \"\\n\" . 'ELEMENT</div>' . \"\\n\";\n }\n }\n }\n}\n```\nThen `assemble()` at lines 86-97 substitutes the rendered HTML for `ELEMENT`:\n```php\nprivate static function assemble( $element ) {\n if( self::getDiv() ) {\n if(is_string(self::getDiv())) {\n $element = str_replace('ELEMENT', $element, self::getDiv());\n self::setDiv(false); // one-shot\n }\n }\n self::$form .= $element;\n}\n```\nThe wrapper is single-shot — resets to `false` after one use.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div Wrapping","kind":"code-recall","citations":["core/f/form.php:120-140","core/f/form.php:86-97","framework-reference-v2.md §5.7"]}}
|
|
{"instruction":"What are the three placeholder layers in the form assembly pipeline?","input":"","output":"From `framework-reference-v2.md §5.8`:\n| Token | Scope | Replaced by |\n|---|---|---|\n| `OPTIONS` | inside one `<select>` | `assembleOptions()` buffer at `core/f/form.php:60` |\n| `ELEMENT` | one element only (single-shot div wrapper) | `assemble()` at `core/f/form.php:92` |\n| `FIELDS` | inside the `<form>` wrapper | `display()` at `core/f/form.php:106` |\n\nThree replace targets, three different scopes. Plus the per-attribute UPPERCASE-token substitution inside each Type class.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.8 Assembly Pipeline","kind":"code-recall","citations":["core/f/form.php:60","core/f/form.php:92","core/f/form.php:106","framework-reference-v2.md §5.8"]}}
|
|
{"instruction":"How does TypeButton's template render the inner content?","input":"","output":"It uses `value` for the inner HTML, not the `value` attribute. From `framework-reference-v2.md §5.4`: `<button>VALUE</button>`. Production code passes things like `'value' => '<i class=\"ti-save\"></i> Speichern'` to embed an icon plus text. The substitution engine does no HTML escaping — embedded markup is rendered as-is.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"My file upload form isn't submitting the file. What's wrong?","input":"","output":"The parent `<form>` tag needs `enctype=\"multipart/form-data\"`. Add it via `Form::addForm`:\n```php\nForm::addForm([\n 'method' => 'POST',\n 'action' => '/upload',\n 'enctype' => 'multipart/form-data',\n]);\n```\nFrom `framework-reference-v2.md §5.4` (TypeFileUpload row). Without this, browsers send the filename only, not the file contents.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"debug","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What is the `addOpenAny` method for and what template does it use?","input":"","output":"It emits a generic open tag whose name comes from the `'any'` attribute. Template from `core/c/typeopenany.php`:\n```\n<ANY ID CLASS>VALUE\n```\nThe caller passes `'any' => 'span'` (or any tag name) and `ANY` becomes `span`. Used for icon spans inside input groups. The leftover-`ANY` strip at `core/c/formattributes.php:100` removes any unused bare `ANY` from final output. From `framework-reference-v2.md §5.4` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeopenany.php","core/c/formattributes.php:100","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What does the addForm wrapper template look like?","input":"","output":"```\n<form name=\"NAME\" action=\"ACTION\" method=\"METHOD\" target=\"TARGET\" enctype=\"ENCTYPE\" onsubmit=\"ONSUBMIT\" ID CLASS>FIELDS</form>\n```\nFrom `framework-reference-v2.md §5.4`. The `FIELDS` token is replaced at the end of `Form::addForm()` via `display()` at `core/f/form.php:106` — `str_replace('FIELDS', self::$form, $template)`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/f/form.php:106","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"I'm trying to understand the production user-edit form. What's the high-level shape?","input":"","output":"From `nibiru-modules/application/module/users/traits/userForm.php` lines 12, 19, 22-89:\n```php\nuse Nibiru\\Factory\\Form;\n\ntrait UserForm {\n public static function userForm(string $action = '', array $user = []) {\n Form::create();\n self::openHalfWidthElement('Benutzer Informationen');\n self::openInnerHalfWithElement();\n foreach(self::FORM_CREATE_USER as $entry) {\n self::addTextElement($entry['visibleName'], $entry['valueName'], $entry['icon'], $user[$entry['valueName']] ?? '');\n }\n self::addSelectDropdown($acl->loadAclRoles(), 'lock', $user['user_role_id']);\n self::closeHalfWidthElement();\n self::addSubmitFormButton('Speichern', 'save-alt');\n return Form::addForm([\n 'name' => 'userForm',\n 'action' => $action,\n 'class' => 'row',\n 'method' => 'post',\n 'target' => '_self',\n ]);\n }\n}\n```\n`Form::addForm()` is the only call that returns HTML — every other `add*` appends to the buffer.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"code-recall","citations":["nibiru-modules/application/module/users/traits/userForm.php:12-89","framework-reference-v2.md §5.9"]}}
|
|
{"instruction":"Why doesn't `Form::addInputTypeText()` echo HTML directly — what does it return?","input":"","output":"Most `add*` methods return `void`. They append the rendered Type-class HTML to the static buffer `self::$form`. Only `Form::addForm()` returns the final HTML string (the caller assigns it and either `echo`s or hands it to Smarty). From `framework-reference-v2.md §5.9`. Calling `Form::addForm()` is also what closes out the buffer — it substitutes `FIELDS` with `self::$form`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"workflow","citations":["framework-reference-v2.md §5.9","framework-reference-v2.md §5.8"]}}
|
|
{"instruction":"My form is missing the password field — what did I do wrong?","input":"","output":"You called `Form::addForm()` before all the field calls. The factory builds statefully:\n```php\nForm::create();\nForm::addInputTypeText(...);\n$html = Form::addForm(...); // BUG: password not added yet\n```\nMitigation: always add ALL fields BEFORE calling `addForm()`. Once `addForm()` runs, it substitutes `FIELDS` with the current `self::$form` buffer; later `addInputType*` calls just dirty the buffer for the next `addForm()`. From `framework-reference-v2.md §11.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.2 Form Statefulness","kind":"gotcha","citations":["framework-reference-v2.md §11.2"]}}
|
|
{"instruction":"What's the typo in the form factory's `addTypeImageSubmit` parameter name?","input":"","output":"It's misspelled `$attrbutes` (missing the `i`) at `core/f/form.php:363`. It works fine — PHP doesn't care about the parameter variable name — but the framework hasn't fixed it. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"gotcha","citations":["core/f/form.php:363","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"Why is the phone-input type class spelled `TypeTelefon`?","input":"","output":"German spelling. `core/c/typetelefon.php` exposes `addTypeTelefon($attributes)` which renders `<input type=\"tel\" …>`. The class name reflects the German `Telefon` rather than English `Telephone`. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"gotcha","citations":["core/c/typetelefon.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What does the front controller look like? Where does Nibiru bootstrap?","input":"","output":"`index.php` at the application root requires `core/framework.php`:\n```php\nrequire_once 'core/framework.php'; // loads Dispatcher::run() at end\n```\n`framework.php` at line 119 calls `Nibiru\\Dispatcher::getInstance()->run()`. From `framework-reference-v2.md §6.1` and §12.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.1 Front Controller","kind":"workflow","citations":["framework-reference-v2.md §6.1","framework-reference-v2.md §12"]}}
|
|
{"instruction":"Walk me through the full Dispatcher::run() flow.","input":"","output":"From `core/c/dispatcher.php:33`:\n1. Set timezone from INI `[SETTINGS][timezone]`.\n2. If `[GENERATOR][database]==true`, run autogenerator: `new Model(false)`.\n3. Call `Router::getInstance()->route()` — parses URL, extracts controller/action.\n4. Call `Auto::loader()->loadModelFiles()` — requires all model files.\n5. Call `Auto::loader()->loadModules()` — requires modules (interfaces -> traits -> modules -> plugins).\n6. Check `application/controller/{ControllerName}Controller.php` exists.\n7. If yes: require, instantiate, call `navigationAction()` (line 52), then `{_action}Action()` if `$_REQUEST['_action']` is set, then `pageAction()` (line 60).\n8. If no controller file: route to error controller (lines 75-80).\n9. Finally: `Debug::getInstance()` and `Display::getInstance()->display()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["core/c/dispatcher.php:33","core/c/dispatcher.php:52","core/c/dispatcher.php:60","framework-reference-v2.md §6.2"]}}
|
|
{"instruction":"What's the controller method order: navigationAction, pageAction, or my custom action?","input":"","output":"Order in `Dispatcher::run()`:\n1. `navigationAction()` — line 52, called BEFORE custom action.\n2. `{_action}Action()` — your method, if `$_REQUEST['_action']` is set and the method exists.\n3. `pageAction()` — line 60, called LAST.\n\nSo `navigationAction()` is the place to load nav JSON or breadcrumbs that the page template depends on; `pageAction()` is the place to render the main template. From `framework-reference-v2.md §6.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.3 Controller Lifecycle","kind":"workflow","citations":["core/c/dispatcher.php:52","core/c/dispatcher.php:60","framework-reference-v2.md §6.3"]}}
|
|
{"instruction":"How does Nibiru render the final HTML to the browser?","input":"","output":"At the end of `Dispatcher::run()`:\n```php\nDebug::getInstance(); // add debug info if enabled\nDisplay::getInstance()->display(); // render via Smarty\n```\nThe `Display` class calls `View::getInstance()->display($template_name)`, which calls Smarty's `display()`. From `framework-reference-v2.md §6.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.4 View Rendering","kind":"workflow","citations":["framework-reference-v2.md §6.4"]}}
|
|
{"instruction":"Trace a request to `/users/login` end to end.","input":"","output":"From `framework-reference-v2.md §12`:\n1. Browser: `GET /users/login`.\n2. Web server routes to `index.php`.\n3. `index.php` requires `core/framework.php`.\n4. `framework.php:119` calls `Nibiru\\Dispatcher::getInstance()->run()`.\n5. `Dispatcher::run()`:\n - `Router::getInstance()->route()` parses URL, sets `$_REQUEST['_action'] = 'login'`.\n - `Auto::loader()->loadModelFiles()` requires all model files.\n - `Auto::loader()->loadModules()` requires all module files.\n - Checks `application/controller/usersController.php` exists.\n - Requires and instantiates: `$controller = new usersController()`.\n - Calls `$controller->navigationAction()` (before action).\n - Checks `$_REQUEST['_action'] == 'login'` -> calls `$controller->loginAction()` if exists.\n - Calls `$controller->pageAction()` (after action).\n - Calls `Debug::getInstance()`.\n - Calls `Display::getInstance()->display()`.\n6. Controller methods run, View renders template via Smarty.","metadata":{"language":"en","source":"framework-reference-v2","section":"12 Request Trace","kind":"workflow","citations":["framework-reference-v2.md §12"]}}
|
|
{"instruction":"Which INI key sets the Smarty cache directory?","input":"","output":"`[ENGINE][cache]`. Default `/../../application/view/cache/`. Read by `View::_setEngine()` at `core/c/view.php:66-79`. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}}
|
|
{"instruction":"Which INI key controls the soft-404 error controller?","input":"","output":"`[ENGINE][error_controller]`. Read by `Dispatcher::run()`. There's no built-in default — if missing, soft-404 handling fails. Pair with `[ENGINE][error_template]` for the matching template path. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What `[ENGINE]` keys does `View::_setEngine()` read?","input":"","output":"From `core/c/view.php:66-79` and `framework-reference-v2.md §7`:\n- `cache` (path) — Smarty cache dir, default `/../../application/view/cache/`.\n- `templates` (path) — Smarty template dir.\n- `templates_c` (path) — Smarty compile dir.\n- `config_dir` (path) — Smarty config dir.\n- `debug_template` (path) — debugbar template.\n- `debugbar` (bool) — enable Smarty debugbar (default false).\n- `caching` (bool) — enable Smarty caching (default false).\n- `error_controller` (string) — controller for 404s.\n- `error_template` (string) — template for 404s.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}}
|
|
{"instruction":"Which INI key does `Table::__construct` read for the database driver?","input":"","output":"`[GENERATOR][driver]` (or `[DATABASE*][driver]`). Read by `Table::_setDatabaseDriver()` at `core/c/table.php:148`: `$driver = config[$configSection][driver]`. Valid values: `mysql`, `psql`, `postgresql`. From `framework-reference-v2.md §7 [GENERATOR]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["core/c/table.php:148","framework-reference-v2.md §7"]}}
|
|
{"instruction":"What's the master switch INI key to enable model autogeneration?","input":"","output":"`[GENERATOR][database] = true`. Read by `Dispatcher::run()`. Defaults to `false`. When true, `new Model(false)` fires on every request. Production should keep this `false`. From `framework-reference-v2.md §7 [GENERATOR]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What does the `[GENERATOR][odbc]` key do?","input":"","output":"For Postgres only: when truthy, the autogenerator picks the UnixODBC adapter (`Postgres`); when falsy or missing, it picks the libpq adapter (`Postgresql`). Read by `Table::_setTables()` and used in `core/c/model.php:115-132`. Has no effect for `driver = \"mysql\"`. From `framework-reference-v2.md §7 [GENERATOR]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["core/c/model.php:115-132","framework-reference-v2.md §7"]}}
|
|
{"instruction":"What INI keys are required in a `[DATABASE]` section?","input":"","output":"From `framework-reference-v2.md §7 [DATABASE]`:\n- `is.active` (bool) — enable this connection.\n- `username`, `password`, `hostname`, `basename`, `driver` — all required.\n- `port` (string) — default `3306`.\n- `encoding` (string) — default `utf8`.\n- `db_info_print` (bool) — optional debug flag, not core.\n\nReal example:\n```ini\n[DATABASE]\nis.active = true\nusername = \"loach\"\npassword = \"08mj7hchqegtjf7znc6978d\"\nhostname = \"sto-loach-production-mariadb-1\"\nbasename = \"warehouse_loach\"\ndriver = \"mysql\"\nport = \"3306\"\nencoding = \"UTF8\"\ndb_info_print = 0\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"inikey","citations":["loach.mssql.database-connection/application/settings/config/settings.production.ini","framework-reference-v2.md §7"]}}
|
|
{"instruction":"Which INI key sets the PHP timezone?","input":"","output":"`[SETTINGS][timezone]`. Read by `Dispatcher::run()`. Defaults to `UTC`. From `framework-reference-v2.md §7 [SETTINGS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What `[SETTINGS]` paths does the autoloader rely on?","input":"","output":"From `framework-reference-v2.md §7 [SETTINGS]`:\n- `dbmodel` — model folder, default `/../../application/model/`.\n- `module` — module folder template, default `/../../application/module/[NAME]` (with `[NAME]` placeholder).\n- `interfaces` — `/../../application/module/[NAME]/interfaces/`.\n- `traits` — `/../../application/module/[NAME]/traits/`.\n- `plugins` — `/../../application/module/[NAME]/plugins/`.\n\nAll consumed by `Auto::loader()`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"How is the home/index route configured?","input":"","output":"`[ROUTING][route[index]]`. Default `/`. Read by `Router::getInstance()`. Pair with `[ROUTING][route[controller]]` (default `/controller`) for the controller route prefix. From `framework-reference-v2.md §7 [ROUTING]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ROUTING]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"Where does the autoloader look for module names?","input":"","output":"`[AUTOLOADER][class.pos[]]` is the array of module names to load (in order). Paired with `iface.pos[]`, `trait.pos[]`, and `class.plugin.pos[]` to scan interfaces, traits, and plugins respectively. All read by `Auto::loader()->loadModules()`. From `framework-reference-v2.md §7 [AUTOLOADER]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [AUTOLOADER]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"How does the basename `warehouse_loach` become the namespace folder `WarehouseLoach`?","input":"","output":"`Table::_setFolderNamespace()` at `core/c/table.php:111` splits on `-` or `_` and runs `ucfirst` on each segment. So `warehouse_loach` -> split into `[\"warehouse\", \"loach\"]` -> `[\"Warehouse\", \"Loach\"]` -> joined `WarehouseLoach`. The full namespace becomes `\\Nibiru\\Model\\WarehouseLoach\\<TableName>`. From `framework-reference-v2.md §8`.","metadata":{"language":"en","source":"framework-reference-v2","section":"8 Namespace Conventions","kind":"workflow","citations":["core/c/table.php:111","framework-reference-v2.md §8"]}}
|
|
{"instruction":"Show me the exact constants from IMysql.","input":"","output":"From `core/i/IMysql.php`:\n```php\nconst SETTINGS_DATABASE = \"DATABASE\";\nconst PLACE_NO_QUERY = \"NO QUERY\";\nconst NO_ID = false;\nconst PLACE_TABLE_NAME = \"NO TABLENAME\";\nconst PLACE_ARRAY_NAME = \"NO ARRAY\";\nconst PLACE_QUERY_LIMIT = \"NO LIMIT\";\nconst PLACE_SORT_ORDER = \"NO ORDER\";\nconst PLACE_DSN = \"NO CONNECTION STRING\";\nconst PLACE_IS_ACTIVE = \"is.active\";\nconst PLACE_USERNAME = \"username\";\nconst PLACE_PASSWORD = \"password\";\nconst PLACE_HOSTNAME = \"hostname\";\nconst PLACE_DRIVER = \"driver\";\nconst PLACE_DATABASE = \"basename\";\nconst PLACE_PORT = \"port\";\nconst PLACE_ENCODING = \"encoding\";\nconst PLACE_PRIMARY_KEY = \"PRI\";\nconst PLACE_COLUMN_NAME = \"NO COLUMN NAME\";\nconst PLACE_SEARCH_TERM = \"NO SEARCH PARAMETER\";\nconst PLACE_FIELD_NAME = \"NO FIELD NAME\";\nconst PLACE_WHERE_VALUE = \"NO WHERE VALUE\";\nconst PLACE_DES_ENCRYPT = false;\nconst PLACE_SQL_UPDATE = \"UPDATE\";\nconst PLACE_SQL_INSERT = \"INSERT\";\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What does `IMysql::PLACE_DATABASE` actually equal?","input":"","output":"The literal string `\"basename\"`. The constant is the INI key name used when reading `Config::getInstance()->getConfig()[SETTINGS_DATABASE][PLACE_DATABASE]` to get the database name. From `core/i/IMysql.php`. So `[DATABASE][basename]` is the conventional INI path for the DB name.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What's the value of `IMysql::PLACE_PRIMARY_KEY`?","input":"","output":"The string `\"PRI\"` — the value MySQL's `SHOW COLUMNS` returns in the `Key` column for primary-key columns. The framework matches against this constant when introspecting tables. From `core/i/IMysql.php` and `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What does the framework set `Content-Type` to for JSON responses?","input":"","output":"`IView::NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\"`. Used by `View::forwardToJsonHeader()`. Paired with `IView::NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\"`. From `core/i/IView.php` and `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IView.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"List the IView header constants.","input":"","output":"From `core/i/IView.php`:\n```php\nconst NIBIRU_SETTINGS = \"SETTINGS\";\nconst NIBIRU_ROUTING = \"ROUTING\";\nconst NIBIRU_SECURITY = \"SECURITY\";\nconst NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\";\nconst NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\";\nconst NIBIRU_CONTENT_ENCODING = \"Content-Encoding: gzip\";\nconst NIBIRU_CONTENT_TRANSFER_ENCODING = \"Content-Transfer-Encoding: {transfer}\";\nconst NIBIRU_FILE_END = \".tpl\";\n```","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IView.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What do IOdbc constants look like?","input":"","output":"From `core/i/IOdbc.php`:\n```php\nconst SETTINGS_DATABASE = \"DATABASE\";\nconst PLACE_READONLY = \"readonly\";\nconst FILTER_COLUMN_NAME = \"COLUMN_NAME\";\n```\nUsed by the Odbc adapter and Postgres drivers. The default section name `\"DATABASE\"` mirrors `IMysql::SETTINGS_DATABASE`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IOdbc.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"Is the CMS module part of Nibiru core?","input":"","output":"No. The CMS module at `application/module/cms/` is a downstream production pattern from `develop.maschinen-stockert.de/`. It models pages, blocks, templates, and text content separately. Nibiru core has no CMS abstraction — the module is a complete sub-framework built on top of Nibiru's module system. From `framework-reference-v2.md §10.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.1 CMS Module","kind":"comparison","citations":["framework-reference-v2.md §10.1"]}}
|
|
{"instruction":"What's the production pattern for chaining plugin `init()` calls?","input":"","output":"```php\nuse Nibiru\\Module\\Cms\\Plugins\\Cms;\nuse Nibiru\\Module\\Assetmanager\\Plugins\\Assetmanager;\n\n$cms = Cms::init(Assetmanager::init()->loadTemplate());\n$cms->loadPageTemplate();\n```\nNot a framework requirement — just a downstream pattern from `develop.maschinen-stockert.de`. The `init()` method is conventional for plugin classes that need explicit initialization. From `framework-reference-v2.md §10.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.2 Plugin init Pattern","kind":"workflow","citations":["framework-reference-v2.md §10.2"]}}
|
|
{"instruction":"Is the Observer pattern built into Nibiru core?","input":"","output":"No. Several production modules implement `SplSubject` (PHP's built-in interface) and support `attach()`, `detach()`, `notify()` for observer registration. This is a convention used in `develop.maschinen-stockert.de/application/module/users/users.php` (see `class Users extends Module implements Interfaces\\Users, SplSubject`), but Nibiru core has no observer abstraction. From `framework-reference-v2.md §10.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.3 Observer Pattern","kind":"comparison","citations":["develop.maschinen-stockert.de/application/module/users/users.php:20-32","framework-reference-v2.md §10.3"]}}
|
|
{"instruction":"I keep getting weird database connection mismatches between two parts of my code. What's the cause?","input":"","output":"`Pdo::$section` is a static (last-write-wins) variable at `core/c/pdo.php:14`. Any model instantiation or `Pdo::settingsSection()` call mutates it. So if your code does:\n```php\n$userModel = Db::loadModel('App\\User'); // Pdo::$section = 'DATABASE'\n$logs = Pdo::queryString('SELECT ...'); // queries DATABASE\n$adminModel = Db::loadModel('App\\Admin'); // Pdo::$section = 'DATABASE_ADMIN'\n$logs = Pdo::queryString('SELECT ...'); // now queries DATABASE_ADMIN!\n```\nthe second raw `Pdo::queryString()` hits a different database than the first. Mitigation: explicitly call `Pdo::settingsSection('DATABASE')` immediately before any raw Pdo query, or always use `Db::loadModel()` and method calls on the returned model. From `framework-reference-v2.md §11.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.1 Pdo last-write-wins","kind":"debug","citations":["core/c/pdo.php:14","framework-reference-v2.md §11.1"]}}
|
|
{"instruction":"Schema field `user_ID` (uppercase) — what setter does the autogenerator produce?","input":"","output":"`_setUserID()` — `str_replace('_', '', ucfirst('user_ID'))` produces `UserID` (the upper-case `ID` is preserved because `ucfirst` only touches the first letter). So the generated method is `_setUserID($user_ID)`. Mitigation: enforce lowercase-with-underscores in your DB schema. From `framework-reference-v2.md §11.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.5 Field Casing","kind":"gotcha","citations":["framework-reference-v2.md §11.5"]}}
|
|
{"instruction":"How do I do a soft 404 in Nibiru?","input":"","output":"The Dispatcher routes to the configured error controller when no controller file matches. Configure in INI:\n```ini\n[ENGINE]\nerror_controller = \"errorController\"\nerror_template = \"error.tpl\"\n```\nThe Dispatcher line 75-80 path is taken if `application/controller/{ControllerName}Controller.php` doesn't exist. From `framework-reference-v2.md §6.2` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher 404","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md §7"]}}
|
|
{"instruction":"Show me the canonical insert + lastInsertId pattern.","input":"","output":"```php\nDb::loadModel('App\\Logs')->insertArrayIntoTable([\n 'log_message' => 'User logged in',\n 'log_timestamp' => date('Y-m-d H:i:s')\n]);\n$newId = Db::loadModel('App\\Logs')->lastInsertId();\n```\nFrom `framework-reference-v2.md` Quick Reference. Each `Db::loadModel()` call re-instantiates the model and re-asserts `Pdo::settingsSection()` from its `__construct()`. Both calls hit the same lazy connection.","metadata":{"language":"en","source":"framework-reference-v2","section":"Quick Reference","kind":"code-recall","citations":["framework-reference-v2.md Quick Reference"]}}
|
|
{"instruction":"Show me the canonical select-by-where pattern.","input":"","output":"```php\nuse Nibiru\\Factory\\Db;\n\n$model = Db::loadModel('App\\Users');\n$users = $model->loadTableAsArray();\n$user = $model->selectRowsetById(5);\n$admins = $model->selectDatasetByFieldWhere(['field' => 'role', 'value' => 'admin']);\n```\nFrom `framework-reference-v2.md` Quick Reference. The `IDb` interface guarantees these methods on every generated model.","metadata":{"language":"en","source":"framework-reference-v2","section":"Quick Reference","kind":"code-recall","citations":["framework-reference-v2.md Quick Reference","core/i/IDb.php"]}}
|
|
{"instruction":"Where do controller files live?","input":"","output":"`application/controller/*Controller.php`. The Dispatcher checks `application/controller/{ControllerName}Controller.php` exists at line 75-80; if so, requires and instantiates `new {ControllerName}Controller()`. Naming convention: lowercase first letter of the URL segment, `Controller` suffix. From `framework-reference-v2.md §6.2` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What core file is the entry point for Nibiru's bootstrapping?","input":"","output":"`core/framework.php`. It includes all core files and at line 119 calls `Nibiru\\Dispatcher::getInstance()->run()`. The application root's `index.php` does `require_once 'core/framework.php';`. From `framework-reference-v2.md §6.1` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"workflow","citations":["framework-reference-v2.md §6.1","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What's the purpose of `core/c/auto.php`?","input":"","output":"It hosts `Auto::loader()`, the modern autoloader. Replaces the legacy `core/c/autoloader.php`. Drives `loadModelFiles()` and `loadModules()` (which scans interfaces, traits, modules, plugins per INI registry). From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["core/c/auto.php","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What's the difference between `core/c/auto.php` and `core/c/autoloader.php`?","input":"","output":"`core/c/auto.php` is the modern autoloader (`Auto::loader()`); `core/c/autoloader.php` is the deprecated legacy one. New code should use `Auto::loader()`. From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"comparison","citations":["framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"List the database-related files in core.","input":"","output":"From `framework-reference-v2.md` Appendix:\n- `core/c/pdo.php` — `Pdo`, database switcher singleton.\n- `core/c/mysql.php` — `Mysql`, base connection class.\n- `core/c/table.php` — `Table`, autogenerator CLI parser.\n- `core/c/model.php` — `Model`, autogenerator executor.\n- `core/f/db.php` — `Db::loadModel()` static factory.\n- `core/a/mysql.db.php` — `\\Nibiru\\Adapter\\MySQL\\Db` base class.\n- `core/i/IMysql.php`, `core/i/IOdbc.php`, `core/i/IDb.php` — interfaces.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"List the form-related files in core.","input":"","output":"From `framework-reference-v2.md` Appendix:\n- `core/f/form.php` — `Form::create()` static factory.\n- `core/c/type*.php` (28 files) — form type classes (TypeText, TypeEmail, etc.).\n- `core/c/formattributes.php` — substitution engine `FormAttributes`.\n- `core/i/IForm.php` — 60+ `FORM_*` constants.\n- `core/t/form.php` — helper trait for `loadAttributeValues`.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix","framework-reference-v2.md §5.1"]}}
|
|
{"instruction":"I want to build a new module that records user actions. Walk me through the steps.","input":"","output":"1. Create directory `application/module/audit/` (lowercase).\n2. Create main class file `application/module/audit/audit.php` with namespace `\\Nibiru\\Module\\Audit\\Audit` extending `Module` and implementing `IModule` (or your local `Interfaces\\Audit`).\n3. Optional sub-folders: `interfaces/`, `traits/`, `plugins/` — files inside use namespaces `\\Nibiru\\Module\\Audit\\Interfaces\\*`, `\\Nibiru\\Module\\Audit\\Traits\\*`, `\\Nibiru\\Module\\Audit\\Plugins\\*`.\n4. Register in INI:\n```ini\n[AUTOLOADER]\nclass.pos[] = \"audit\"\niface.pos[] = \"audit\" ; if you have interfaces\ntrait.pos[] = \"audit\" ; if you have traits\nclass.plugin.pos[] = \"audit\" ; if you have plugins\n```\n5. Plugins access models via `use Nibiru\\Factory\\Db;` then `Db::loadModel('Folder\\Audit')->insertArrayIntoTable([...])`.\n\nFrom `framework-reference-v2.md §4.1`, §4.2, §4.4, §11.7.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §4.1","framework-reference-v2.md §4.2","framework-reference-v2.md §4.4","framework-reference-v2.md §11.7"]}}
|
|
{"instruction":"I want to add a new database table and use it in a controller. Walk me through it.","input":"","output":"1. Create the table in your database (e.g. via SQL migration in `application/settings/config/database/`).\n2. Ensure dev INI has `[GENERATOR][database] = true` and `database.overwrite = false`.\n3. Visit any URL — `Dispatcher::run()` fires `new Model(false)` which scans `SHOW TABLES` (MySQL) or `information_schema` (Postgres) and writes the new model file at `application/model/<FolderName>/<TableName>.php`.\n4. In your controller, `use Nibiru\\Factory\\Db;` and call `$rows = Db::loadModel('FolderName\\TableName')->loadTableAsArray();`.\n5. `View::assign(['rows' => $rows]);` — render in template via `{$rows}`.\n\nFrom `framework-reference-v2.md §3.2`, §6.3, §2.6.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md §6.3","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"I'm getting `Class 'Nibiru\\Model\\Foo\\Bar' not found` after creating a new database table. What's wrong?","input":"","output":"Either:\n1. The autogenerator isn't enabled — check `[GENERATOR][database] = true` in your INI.\n2. The model file at `application/model/Foo/Bar.php` exists but is empty (size 0). The non-overwrite generator only writes to a zero-byte file. If a previous failed run left a non-zero-byte stub, delete it and reload.\n3. Your folder namespace is wrong: `_setFolderNamespace()` PascalCases the basename. If `[DATABASE][basename] = \"foo\"`, the namespace is `\\Nibiru\\Model\\Foo`, not `\\Nibiru\\Model\\foo`.\n4. Autoloader hasn't run on the model — `Auto::loader()->loadModelFiles()` needs to require the file. If the directory exists but the file isn't there, regenerate.\n\nFrom `framework-reference-v2.md §3.2`, §8, §11.7.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Debug","kind":"debug","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md §8","framework-reference-v2.md §11.7"]}}
|
|
{"instruction":"Walk me through accepting form input in a Nibiru controller and saving it to the DB.","input":"","output":"1. Build the form via the `Form::*` factory in a trait or controller method:\n```php\nForm::create();\nForm::addInputTypeText(['name' => 'email']);\nForm::addInputTypeSubmit(['value' => 'Save']);\n$html = Form::addForm(['method' => 'POST', 'action' => '/users/save']);\n```\n2. Render the `$html` in a Smarty template via `View::assign(['form' => $html])` then `{$form nofilter}`.\n3. The form posts to `/users/save` -> Dispatcher routes to `usersController.php`, calls `saveAction()` (since `$_REQUEST['_action'] === 'save'`).\n4. In `saveAction()`:\n```php\n$email = $this->getPost('email');\nDb::loadModel('App\\Users')->insertArrayIntoTable(['email' => $email]);\n$id = Db::loadModel('App\\Users')->lastInsertId();\n```\n5. `View::forwardTo('/users/list')` to redirect.\n\nFrom `framework-reference-v2.md §2.4`, §2.5, §2.6, §6.3, Quick Reference.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §2.4","framework-reference-v2.md §2.5","framework-reference-v2.md §6.3","framework-reference-v2.md Quick Reference"]}}
|
|
{"instruction":"My production deployment shows a fresh model file getting overwritten between requests. What's happening?","input":"","output":"Two likely causes:\n1. `[GENERATOR][database] = true` is enabled in production — every request fires `new Model(false)` from `Dispatcher::run()` at `core/c/dispatcher.php:38`. Set it to `false` in `settings.production.ini`.\n2. `[GENERATOR][database.overwrite] = true` is enabled — every request `unlink`s the model file before regenerating from `core/c/model.php:70-74`. Set it to `false`.\n\nProduction should have BOTH off: `database = false` (master switch) and `database.overwrite = false` (safety net). From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Debug","kind":"debug","citations":["core/c/dispatcher.php:38","core/c/model.php:70-74","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What happens if `[DATABASE][is.active] = false` but the autogenerator is enabled?","input":"","output":"`Model::__construct()` early-bails at line 16 of `core/c/model.php` before reaching `Table::__construct`. So no autogeneration happens, and no file scans run. The trade-off: if you disable a DB section temporarily but leave autogen enabled, you don't get models for that section but the rest of the app continues fine. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["core/c/model.php:14","core/c/model.php:16","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How do I redirect after a POST in Nibiru?","input":"","output":"`View::forwardTo($page)` is a static helper on `\\Nibiru\\View` (singleton). Defined at `core/c/view.php:11`. Real plugin example from `loach.mssql.database-connection/application/module/users/plugins/acl.php`:\n```php\nView::forwardTo('/users/login');\n```\nIt sends an HTTP redirect to the specified path. From `framework-reference-v2.md §2.6` and §4.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","loach.mssql.database-connection/application/module/users/plugins/acl.php","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"What's the right way to assign multiple variables to a Smarty template?","input":"","output":"Pass an associative array to `View::assign`:\n```php\nView::assign([\n 'page_title' => 'Home',\n 'user_name' => 'John',\n 'role' => 'admin'\n]);\n```\nIn the Smarty template, reference them with `{$page_title}`, `{$user_name}`, `{$role}`. Defined at `core/c/view.php:11`. From `framework-reference-v2.md §2.6` and Quick Reference.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"code-recall","citations":["core/c/view.php:11","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"How do I check if there's an active session before reading a session value?","input":"","output":"`Controller::getSession()` accepts a third parameter:\n```php\n$user = $this->getSession('user', false, true);\n// parameter params checkForActiveSession\n```\nThe full signature from `core/c/controller.php:14`:\n```php\ngetSession($param, bool $params = false, bool $checkForActiveSession = false)\n```\nWith the third argument true, the helper checks session-active state before accessing.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"What does `getController()` return inside a Controller method?","input":"","output":"The current controller name, extracted from URL segment 1. From `core/c/controller.php:14`. Useful for navigation/breadcrumbs that need to know which controller is active. Different from class introspection — it returns the URL-derived name, not the PHP class name.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"What core methods does Pdo expose for building queries?","input":"","output":"From `framework-reference-v2.md §2.2`:\n- `query($string)` — exec or fetch; routes via `parent::getInstance(self::getSettingsSection())`.\n- `queryString($string, $associative)` — fetch all.\n- `fetchTableAsArray($tablename, $limit, $order)` — table dump with pagination.\n- `selectDatasetByFieldAndValue($tablename, $fieldAndValue, $sortOrder)` — WHERE clause.\n- `fetchRowInArrayById($tablename, $id)` — single row by PK.\n- `fetchRowInArrayByWhere($tablename, $column_name, $parameter_name)` — single row by column.\n- `insertArrayIntoTable($tablename, $array_name, $encrypted)` — insert with optional `DES_ENCRYPT()`.\n- `updateRowById($tablename, $columnNames, $data, $id, $encrypted)` — update by PK.\n\nAll routed through `self::getSettingsSection()` so they respect the current `Pdo::$section`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"How does Pdo's optional encryption work?","input":"","output":"`Pdo::insertArrayIntoTable($tablename, $array_name, $encrypted)` and `Pdo::updateRowById($tablename, $columnNames, $data, $id, $encrypted)` accept an `$encrypted` flag. When set, MySQL `DES_ENCRYPT()` is applied to the relevant columns. The default `IMysql::PLACE_DES_ENCRYPT = false` means no encryption. From `framework-reference-v2.md §2.2` and §9.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"How do I do a fetch-all SELECT with associative results?","input":"","output":"```php\n$rows = Pdo::queryString('SELECT * FROM my_table', true);\n```\nThe second argument controls associative-vs-numeric fetch. Routes through `self::getSettingsSection()` so the active `Pdo::$section` decides which DB connection. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"What constants are listed under IForm and where are they used?","input":"","output":"`IForm` (at `core/i/IForm.php`) declares 60+ `FORM_*` constants — every legal attribute key (`name`, `value`, `class`, `id`, `placeholder`, `required`, `onchange`, `onblur`, `onfocus`, `selected`, `context`, `multiple`, `tabindex`, `pattern`, `data-bts-decimals`, `data-bts-step`, `any`, etc.). The constants are lowercase strings; the substitution engine uppercases them at replace time. Each Type class's `$_attributes` allowlist references these constants by name. From `framework-reference-v2.md §5.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/i/IForm.php","framework-reference-v2.md §5.1"]}}
|
|
{"instruction":"What's the difference between TypeText and TypeEmail?","input":"","output":"Different template strings and slightly different allowlists. `TypeText` (`core/c/typetext.php:42`) renders `<input type=\"text\" …>` with attributes including `data-bts-decimals`, `data-bts-step`, `maxlength`, `disabled`, `speech`. `TypeEmail` (`core/c/typeemail.php`) renders `<input type=\"email\" …>` with attributes `name, value, id, class, placeholder, required, pattern`. Both follow the same four-step recipe (`__construct` -> `_setElement` -> `loadAttributeValues` -> `_setAttributes`); only the template and allowlist differ. From `framework-reference-v2.md §5.3` and §5.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"comparison","citations":["core/c/typetext.php:42","core/c/typeemail.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What's the difference between TypeSelect and TypeOpenAny?","input":"","output":"`TypeSelect` (`core/c/typeselect.php:37`) is a self-closing element template `<select …>OPTIONS</select>` — fully formed, no manual close. `TypeOpenAny` (`core/c/typeopenany.php`) is just an open tag `<ANY ID CLASS>VALUE` where `ANY` is replaced by the user's `'any' => 'span'` value; the matching close requires `Form::addCloseAny(['any' => 'span'])`. Use `TypeSelect` for dropdowns; use the OpenAny/CloseAny pair to wrap arbitrary children inside whatever HTML element you need. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"comparison","citations":["core/c/typeselect.php:37","core/c/typeopenany.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How do I register a new option to a `<select>` programmatically?","input":"","output":"```php\nForm::addSelectOption(['value' => '1', 'context' => 'Admin']);\nForm::addSelectOption(['value' => '2', 'context' => 'User']);\nForm::addSelect(['name' => 'role']); // flushes options into the select\n```\n`addSelectOption` appends a `<option …>CONTEXT</option>` to the static `self::$option` buffer; `addSelect` then renders the `<select>` template with `OPTIONS` replaced by that buffer and clears it. From `framework-reference-v2.md §5.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.6 Select/Option Ordering","kind":"workflow","citations":["framework-reference-v2.md §5.6"]}}
|
|
{"instruction":"Walk me through how the Form factory pre-formats `id` and `class`.","input":"","output":"The trait `\\Nibiru\\Attributes\\Form` at `core/t/form.php:14` exposes `loadAttributeValues($attributes)`. It iterates the user's attribute array and rewrites the `id`, `class`, and `form` values into pre-quoted attribute snippets like `' id=\"x\"'`. So when the substitution engine later does `str_replace('ID', $value, $template)`, the bare `ID` token becomes `' id=\"x\"'` — and if the user didn't supply `id`, the strip pass at `core/c/formattributes.php:59-102` removes any leftover bare `ID` token. From `framework-reference-v2.md §5.1` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"workflow","citations":["core/t/form.php:14","core/c/formattributes.php:59-102","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"I need to render text inside a `<span>` next to my input. What method do I use?","input":"","output":"Use the OpenAny/CloseAny pair:\n```php\nForm::addOpenAny(['any' => 'span', 'class' => 'input-group-addon']);\nForm::addInputTypeText(['name' => 'email']);\nForm::addCloseAny(['any' => 'span']);\n```\n`addOpenAny` emits `<span class=\"input-group-addon\">` (the `ANY` template token becomes `span`); `addCloseAny` emits `</span>`. The leftover-`ANY` strip at `core/c/formattributes.php:100` ensures clean output. From `framework-reference-v2.md §5.4` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["core/c/formattributes.php:100","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"I need a labelled input with an icon. What's the canonical structure?","input":"","output":"Label + OpenDiv (input-group) + OpenAny (span for icon) + CloseAny + InputTypeText + CloseDiv. This is the production `addTextElement` pattern in `nibiru-modules/application/module/users/traits/userForm.php` lines 137-175. The factory call sequence:\n```php\nForm::addTypeLabel(['for' => 'email', 'value' => 'Email']);\nForm::addOpenDiv(['class' => 'input-group']);\nForm::addOpenAny(['any' => 'span', 'class' => 'input-group-addon']);\n// (icon HTML inside)\nForm::addCloseAny(['any' => 'span']);\nForm::addInputTypeText(['name' => 'email']);\nForm::addCloseDiv();\n```\nFrom `framework-reference-v2.md §5.9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"workflow","citations":["nibiru-modules/application/module/users/traits/userForm.php:137-175","framework-reference-v2.md §5.9"]}}
|
|
{"instruction":"My form HTML has weird double spaces. Why?","input":"","output":"That's an artifact of the substitution engine when several attributes are stripped consecutively. After the strip pass at `core/c/formattributes.php:59-102`, line 87 runs `str_replace(' ', ' ', ...)` to fold double spaces. If you still see them, you might have leftover unrecognized tokens that the engine never substituted AND never has a strip rule for — usually because you used a key not in the Type's allowlist. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"debug","citations":["core/c/formattributes.php:87","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"What happens when I call `Pdo::settingsSection()` with no arguments?","input":"","output":"It defaults to `IOdbc::SETTINGS_DATABASE`, which is the literal string `\"DATABASE\"`. From `core/c/pdo.php:19`:\n```php\npublic static function settingsSection( $section = IOdbc::SETTINGS_DATABASE )\n```\nSo a bare `Pdo::settingsSection()` resets `Pdo::$section` to `'DATABASE'` — the canonical primary connection.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"edge-case","citations":["core/c/pdo.php:19","core/i/IOdbc.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"Quick question: where is `Pdo::$section` declared?","input":"","output":"`core/c/pdo.php:14`, as a static property on the `Pdo` class. It's the single source of truth for which `[DATABASE*]` INI section the next query will use. Last write wins per request. From `framework-reference-v2.md §2.2` and §11.1.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:14","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"What's the relationship between Pdo and Mysql in core?","input":"","output":"`Pdo extends Mysql`. `Pdo` is the singleton/static-section interface; `Mysql` is the underlying connection class. `Pdo::getInstance(...)` calls `parent::getInstance(self::getSettingsSection())` which gives back a `Mysql` connection. From `framework-reference-v2.md §3.1` (file index) and §2.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"comparison","citations":["core/c/pdo.php","core/c/mysql.php","framework-reference-v2.md §3.1"]}}
|
|
{"instruction":"My logs show the wrong timezone in timestamps. What INI key fixes that?","input":"","output":"`[SETTINGS][timezone]`. The Dispatcher reads it on every request and calls PHP's timezone setter. Default is `UTC`. Set to e.g. `\"Europe/Berlin\"` and reload — all subsequent `date()` and `DateTime` calls reflect the new zone. From `framework-reference-v2.md §7 [SETTINGS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"debug","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What does the autoloader do if a model file is missing?","input":"","output":"`Auto::loader()->loadModelFiles()` calls `require_once` on each file it scans inside the model folder. If the file is missing from disk, it isn't required. The runtime error happens later when something actually does `new \\Nibiru\\Model\\Foo\\Bar()` — PHP throws a fatal `Class … not found`. The autoloader is NOT PSR-4 — it scans directories driven by INI keys, so it can only require what's on disk. From `framework-reference-v2.md §11.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.7 Autoloader not PSR-4","kind":"edge-case","citations":["framework-reference-v2.md §11.7"]}}
|
|
{"instruction":"Show me the `addCloseDiv` invocation pattern.","input":"","output":"```php\nForm::addCloseDiv();\n```\nNo arguments needed. Emits `</div>`. Companion to `addOpenDiv($attributes)`. Useful for nesting structural sections in production form code. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How do I assign a value to a hidden form field?","input":"","output":"```php\nForm::addTypeHidden(['name' => '_action', 'value' => 'save']);\n```\nRenders `<input type=\"hidden\" name=\"_action\" value=\"save\">`. The factory method is `addTypeHidden` (note: `addType*` without `Input`), per `framework-reference-v2.md §5.5`'s naming-pattern table.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4","framework-reference-v2.md §5.5"]}}
|
|
{"instruction":"How do I include `_action` in a route?","input":"","output":"Route to a path matching the controller, and pass `_action` as a POST/GET param. Example: posting to `/users/save` sets `$_REQUEST['_action'] = 'save'`. The Dispatcher then calls `$controller->saveAction()`. You can put `_action` in form data:\n```html\n<input type=\"hidden\" name=\"_action\" value=\"save\">\n```\nFrom `framework-reference-v2.md §6.2` and §12.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md §12"]}}
|
|
{"instruction":"What happens if `_action` is set but the controller has no matching `*Action()` method?","input":"","output":"The Dispatcher only calls `{_action}Action()` if it exists on the controller. If the method is missing, the call is skipped — `navigationAction()` and `pageAction()` still run. There's no fatal error. From `framework-reference-v2.md §6.2` step 7.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"edge-case","citations":["framework-reference-v2.md §6.2"]}}
|
|
{"instruction":"Quick: which files comprise the View/Controller layer?","input":"","output":"From `framework-reference-v2.md` Appendix:\n- `core/c/view.php` — `View::getInstance()`, Smarty wrapper.\n- `core/c/controller.php` — `Controller::getInstance()`, request access.\n- `core/c/display.php` — final rendering.\n- `core/c/engine.php` — template engine setup.\n- `core/c/debug.php` — debug output.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What does `core/l/autoload.php` do?","input":"","output":"It hosts a PSR-4 autoloader hook. Distinct from `core/c/auto.php` (which is `Auto::loader()`, scanning directories driven by INI). The PSR-4 hook handles class loading via standard Composer-style namespace mapping. From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"How do I render a JSON response from a Nibiru controller action?","input":"","output":"Call `View::forwardToJsonHeader()` to set the JSON content-type headers, then echo the JSON-encoded payload. `forwardToJsonHeader(string $encoding = \"\")` is defined at `core/c/view.php:11`. The headers it emits use `IView::NIBIRU_CONTENT_TYPE_JSON = \"Content-Type: application/json\"` and `IView::NIBIRU_CONTENT_TYPE_CONNECTION = \"Connection: close\"`. From `framework-reference-v2.md §2.6` and §9.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:11","core/i/IView.php","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"What's the constant `NIBIRU_CONTENT_TRANSFER_ENCODING`?","input":"","output":"`\"Content-Transfer-Encoding: {transfer}\"` — a header template with a `{transfer}` placeholder for the actual encoding value. Defined in `core/i/IView.php` as `IView::NIBIRU_CONTENT_TRANSFER_ENCODING`. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IView.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"Walk me through writing a plugin that validates ACL on every request.","input":"","output":"1. Create `application/module/users/plugins/acl.php`.\n2. Use the framework imports and the canonical pattern:\n```php\nuse Nibiru\\Factory\\Db;\nuse Nibiru\\View;\n\nclass Acl extends User\n{\n public function __construct() { parent::__construct(); }\n\n public function init(): void\n {\n if(!$this->validate()) {\n View::forwardTo('/users/login');\n } else {\n $this->loadUserRole();\n }\n }\n}\n```\n3. Register in INI: `[AUTOLOADER] class.plugin.pos[] = \"acl\"`. Plugins load LAST per `Auto::loader()` order.\n4. Inside the plugin, `Db::loadModel('Folder\\Acl')` triggers the model's `Pdo::settingsSection('DATABASE')`.\n\nReal example: `loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40`. From `framework-reference-v2.md §4.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["loach.mssql.database-connection/application/module/users/plugins/acl.php:14-40","framework-reference-v2.md §4.4"]}}
|
|
{"instruction":"How are interfaces, traits, modules, and plugins loaded in order?","input":"","output":"`Auto::loader()->loadModules()` processes them in this fixed order: interfaces (`iface.pos[]`), traits (`trait.pos[]`), modules (`class.pos[]`), plugins (`class.plugin.pos[]`). Within each category, the array order from the INI is preserved. So plugins always load last; interfaces always first. From `framework-reference-v2.md §4.3` and §1 (namespace map row).","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["framework-reference-v2.md §4.3","framework-reference-v2.md §1"]}}
|
|
{"instruction":"Explain the IDb interface methods.","input":"","output":"From `core/i/IDb.php`, every generated model implements:\n- `loadTableAsArray()` — returns the entire table as a PHP array.\n- `selectRowsetById($id)` — returns the row whose PK matches `$id`.\n- `updateRowById(array $rowData, int $id, string $encrypted = \"\")` — UPDATE by PK with optional `DES_ENCRYPT()`.\n- `insertArrayIntoTable($dataset = array())` — INSERT row.\n- `selectDatasetByFieldWhere($fieldWhere = array(), $sortOrder = false)` — SELECT … WHERE.\n- `selectRowByFieldWhere($field = array())` — SELECT single row by column.\n- `lastInsertId()` — return last AUTO_INCREMENT value.\n- `deleteRowById(int $id = 0)` — DELETE by PK.\n- `updateRowByFieldWhere($wherefield, $wherevalue, $rowfield, $rowvalue)` — UPDATE … WHERE.\n\nFrom `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"What does `selectDatasetByFieldWhere(['field' => 'role', 'value' => 'admin'])` actually do?","input":"","output":"It builds a `SELECT * FROM <table> WHERE role = 'admin'` query against the model's table. The `$fieldWhere` parameter is an associative array with `'field'` (column name) and `'value'` (filter value). The optional second arg `$sortOrder` controls `ORDER BY`. From `framework-reference-v2.md` Quick Reference and §2.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["framework-reference-v2.md §2.3","framework-reference-v2.md Quick Reference"]}}
|
|
{"instruction":"Quick: when does `Auto::loader()->loadModelFiles()` run vs `loadModules()`?","input":"","output":"`Dispatcher::run()` calls `loadModelFiles()` at line 42, THEN `loadModules()` at line 43. So all model files are required first, modules second. This guarantees that a module's plugin can `Db::loadModel('Folder\\Foo')` and the class is already require'd. From `framework-reference-v2.md §4.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/c/dispatcher.php:42","core/c/dispatcher.php:43","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"How do I create a single-shot wrapping div around a select?","input":"","output":"Pass the wrapper as the second arg to `addSelect`:\n```php\nForm::addSelectOption(['value' => 'a', 'context' => 'A']);\nForm::addSelectOption(['value' => 'b', 'context' => 'B']);\nForm::addSelect(['name' => 'choice'], ['class' => 'form-group']);\n```\nThe `$div` argument is one-shot — only the next assembled element is wrapped. From `framework-reference-v2.md §5.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div Wrapping","kind":"workflow","citations":["framework-reference-v2.md §5.7"]}}
|
|
{"instruction":"What's an example multi-attribute div wrapper with class and id?","input":"","output":"The `setDiv` implementation iterates each `$key=>$selector` pair, but it OVERWRITES `self::$div` on each iteration:\n```php\nforeach ( $div as $key=>$selector ) {\n self::$div = '<div ' . $key . '=\"' . $selector . '\">' . \"\\n\" . 'ELEMENT</div>' . \"\\n\";\n}\n```\nFrom `core/f/form.php:120-140`. So the LAST entry in the `$div` array wins — passing `['class' => 'a', 'id' => 'b']` results in only `id=\"b\"` ending up in the wrapper. To get both, pre-build a single attribute string in the value or use a different mechanism. This is a footgun.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div Wrapping","kind":"gotcha","citations":["core/f/form.php:120-140","framework-reference-v2.md §5.7"]}}
|
|
{"instruction":"What's the typical INI structure for a development environment?","input":"","output":"Sections seen in real Nibiru INI files (per `framework-reference-v2.md §7`):\n- `[ENGINE]` — Smarty paths, caching, error controller/template.\n- `[AUTOLOADER]` — `class.pos[]`, `iface.pos[]`, `trait.pos[]`, `class.plugin.pos[]` arrays.\n- `[GENERATOR]` — `database`, `database.overwrite`, `config-section`, `folder-out`, `modeltemplate`, `odbc`.\n- `[DATABASE]` (and optional `[DATABASE_*]`) — `is.active`, `username`, `password`, `hostname`, `basename`, `driver`, `port`, `encoding`.\n- `[SETTINGS]` — `timezone`, `pageurl`, `dbmodel`, `module`, `interfaces`, `traits`, `plugins`.\n- `[ROUTING]` — `route[index]`, `route[controller]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI Reference","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"I want to talk to MSSQL through Nibiru. How does the framework support that?","input":"","output":"There's no native MSSQL driver in the v2 reference — Nibiru ships MySQL/MariaDB (`driver = \"mysql\"`), PostgreSQL via libpq (`driver = \"postgresql\"`), and PostgreSQL via UnixODBC (`driver = \"psql\"` + `[GENERATOR][odbc] = true`). For MSSQL you'd typically route through ODBC by writing a custom driver class or wrapping queries through PHP's PDO ODBC layer. The `loach.mssql.database-connection` project name suggests this was the pattern, but the v2 reference does not document an MSSQL driver. From `framework-reference-v2.md §3.1` and §3.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.1 Drivers & Adapters","kind":"edge-case","citations":["framework-reference-v2.md §3.1","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What runs when I do `Db::loadModel('App\\Logs')->insertArrayIntoTable([...])`?","input":"","output":"1. `Db::loadModel('App\\Logs')` instantiates `\\Nibiru\\Model\\App\\Logs` via the factory at `core/f/db.php:11`.\n2. The model's `__construct()` runs: `Pdo::settingsSection('DATABASE')` mutates `Pdo::$section`; `self::initTable( self::TABLE )` registers the schema with the static `$table` array on the base adapter (`core/a/mysql.db.php:15`).\n3. `Db::loadModel()` returns the model typed as `IDb`.\n4. `->insertArrayIntoTable([...])` (from `IDb`) invokes the adapter's INSERT, which routes through `Pdo::insertArrayIntoTable($tablename, $array_name, $encrypted)` using `self::getSettingsSection()` to pick the connection.\n5. MySQL receives `INSERT INTO logs (...) VALUES (...)`.\n\nFrom `framework-reference-v2.md §2.3`, §3.1, §2.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["core/f/db.php:11","core/a/mysql.db.php:15","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"How do I disable Smarty caching for development?","input":"","output":"Set `[ENGINE][caching] = false` in `settings.development.ini`. The `_setEngine()` block at `core/c/view.php:66-79` only enables `CACHING_LIFETIME_CURRENT` when `ENGINE[caching]==true`. From `framework-reference-v2.md §2.6` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"How do I turn on the Smarty debugbar?","input":"","output":"`[ENGINE][debugbar] = true` in your INI. Read by `View::_setEngine()` at `core/c/view.php:66-79`. Pair it with `[ENGINE][debug_template]` pointing at the debugbar template path. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}}
|
|
{"instruction":"What does the `db_info_print` INI key do?","input":"","output":"Optional debug flag in `[DATABASE]`, default `0`. Not consumed by core — it's a downstream convention for printing connection diagnostics. The framework's `Mysql::__construct()` does not read it. From `framework-reference-v2.md §7 [DATABASE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"Why does PHP raise `Class 'Nibiru\\Adapter\\Postgresql\\Db' not found` from a generated model?","input":"","output":"The autogenerator emitted `use Nibiru\\Adapter\\Postgresql\\Db;` because `[GENERATOR][odbc]` was falsy at generation time. If `core/a/postgresql.db.php` (or its `\\Nibiru\\Adapter\\Postgresql` namespace) is missing or wasn't loaded by the autoloader, PHP fatals. Check that:\n1. `core/a/postgresql.db.php` exists in the framework directory.\n2. The PSR-4 hook at `core/l/autoload.php` is active.\n3. The `core/framework.php` boot includes the relevant adapter file.\n\nFrom `framework-reference-v2.md §3.2` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"debug","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What's the difference between `selectRowByFieldWhere` and `fetchRowInArrayByWhere`?","input":"","output":"`selectRowByFieldWhere($field = array())` is a method on the `IDb`-typed model (from `core/i/IDb.php`) — used via `Db::loadModel(...)->selectRowByFieldWhere([...])`.\n`fetchRowInArrayByWhere($tablename, $column_name, $parameter_name)` is on `Pdo` directly — used via `Pdo::fetchRowInArrayByWhere(...)`.\n\nFunctionally similar (both fetch a single row by column/value), but the IDb version takes an array argument and is bound to the model's table; the Pdo version takes raw `$tablename`/`$column`/`$value` strings and lets you query any table. From `framework-reference-v2.md §2.2` and §2.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Comparison","kind":"comparison","citations":["core/i/IDb.php","core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"How do I register an interface for a module?","input":"","output":"1. Place the interface file at `application/module/<name>/interfaces/<filename>.php` with namespace `\\Nibiru\\Module\\<Name>\\Interfaces\\<InterfaceName>`.\n2. Add to INI: `[AUTOLOADER] iface.pos[] = \"<name>\"`.\n3. Reload — `Auto::loader()->loadModules()` will scan the interfaces directory and `require_once` matching files.\n\nFrom `framework-reference-v2.md §4.2` and §8.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.2 Module Registry","kind":"workflow","citations":["framework-reference-v2.md §4.2","framework-reference-v2.md §8"]}}
|
|
{"instruction":"Explain the difference between `getRequest`, `getPost`, and `getGet`.","input":"","output":"From `core/c/controller.php:14`:\n- `getPost($param)` — reads `$_POST` only.\n- `getGet($param)` — reads `$_GET` only.\n- `getRequest($param, bool $params = false)` — reads `$_REQUEST` (POST/GET unified).\n\nUse `getPost`/`getGet` when the source matters (security or method-specific behavior); use `getRequest` when you just want the value regardless of how it arrived. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"comparison","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"Where does `$controller->getServer($param)` map to?","input":"","output":"`$_SERVER`. So `$this->getServer('REMOTE_ADDR')` returns the client IP, `$this->getServer('HTTP_USER_AGENT')` the user agent. Defined at `core/c/controller.php:14`. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"How do I access uploaded files in a Nibiru controller?","input":"","output":"`$this->getFiles($param)` — reads `$_FILES`. Defined at `core/c/controller.php:14`. Combine with `<form enctype=\"multipart/form-data\">` and `Form::addTypeFileUpload(['name' => 'upload'])`. From `framework-reference-v2.md §2.5` and §5.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"Show me the IMysql `PLACE_*` constants for INI keys.","input":"","output":"From `core/i/IMysql.php`:\n```php\nconst PLACE_IS_ACTIVE = \"is.active\";\nconst PLACE_USERNAME = \"username\";\nconst PLACE_PASSWORD = \"password\";\nconst PLACE_HOSTNAME = \"hostname\";\nconst PLACE_DRIVER = \"driver\";\nconst PLACE_DATABASE = \"basename\";\nconst PLACE_PORT = \"port\";\nconst PLACE_ENCODING = \"encoding\";\n```\nThese are the literal INI key names used when reading `[DATABASE*]` sections via `Config::getInstance()->getConfig()`. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"Quick question: where is the model autogeneration master switch read?","input":"","output":"`Dispatcher::run()` at `core/c/dispatcher.php:35-39` reads `Config::getInstance()->getConfig()[self::CONFIG_GENERATOR_SECTION][self::GENERATOR_DATABASE]`. The constants resolve to the INI path `[GENERATOR][database]`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["core/c/dispatcher.php:35-39","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the production-safe combination of `[GENERATOR]` flags?","input":"","output":"```ini\n[GENERATOR]\ndatabase = false ; off in production\ndatabase.overwrite = false ; safety net (already off)\n```\nWith `database = false`, `Dispatcher::run()` skips the `new Model(false)` branch entirely. With `database.overwrite = false`, even if you flip the master switch back on for a moment, existing model files aren't `unlink`ed. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"inikey","citations":["framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the structure of an IForm constant entry?","input":"","output":"All `FORM_*` constants in `core/i/IForm.php` are public lowercase strings. Example shape:\n```php\nconst FORM_NAME = 'name';\nconst FORM_VALUE = 'value';\nconst FORM_ATTRIBUTE_PLACEHOLDER = 'placeholder';\nconst FORM_ATTRIBUTE_REQUIRED = 'required';\nconst FORM_ATTRIBUTE_ID = 'id';\nconst FORM_ATTRIBUTE_CLASS = 'class';\n```\nThe Type classes reference these constants in their `$_attributes` allowlists; the substitution engine uppercases them at replace time. From `framework-reference-v2.md §5.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/i/IForm.php","framework-reference-v2.md §5.1"]}}
|
|
{"instruction":"What's the entry point line that calls `Dispatcher::run()`?","input":"","output":"`core/framework.php` at line 119:\n```php\nNibiru\\Dispatcher::getInstance()->run();\n```\nThis is the line that fires after all core files are required, kicking off the entire request lifecycle. From `framework-reference-v2.md §12` step 4.","metadata":{"language":"en","source":"framework-reference-v2","section":"12 Request Trace","kind":"code-recall","citations":["core/framework.php:119","framework-reference-v2.md §12"]}}
|
|
{"instruction":"What does Nibiru's `Module` base class give me?","input":"","output":"It's at `core/c/module.php` (and `core/a/module.php` for the adapter base). Provides the common base for all module main classes. Production module example extends `Module`:\n```php\nclass Users extends Module implements Interfaces\\Users, SplSubject\n```\nFrom `framework-reference-v2.md §4.3` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/c/module.php","core/a/module.php","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"How does the `IModule` interface interact with the Module base class?","input":"","output":"`IModule` (from `core/i/IModule.php`) is the contract every module main class must implement. The base `Module` class at `core/c/module.php` provides default behavior; concrete modules extend `Module` AND implement `IModule` (sometimes via a module-local `Interfaces\\Users` interface that itself extends `IModule`). From `framework-reference-v2.md §4.3` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/i/IModule.php","core/c/module.php","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"How does the autogenerator know which tables to scan?","input":"","output":"`Table::_setTables()` runs `SHOW TABLES` for MySQL or queries `information_schema` for Postgres. The result populates `$tables`, which `Model::createClassFiles()` (at `core/c/model.php:37`) loops over to call `generateClassByTableName()`. If `--table=foo` was passed (CLI flag, not used by dispatcher), only `foo` is generated. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/table.php","core/c/model.php:37","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Why does the generator chmod files to 0777?","input":"","output":"`Model::createOutFolder()` at `core/c/model.php:28` does `mkdir -p` with `chmod 0777`. `generateClassByTableName()` ends with `chmod(..., 0777)` at `core/c/model.php:133-145`. The aggressive permission is so the web server user (which created the file) doesn't lock developers out of editing or removing it on shared dev machines. In production, since the generator should be off, this chmod doesn't run. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:28","core/c/model.php:133-145","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Show me the field-array indentation pattern in the generated TABLE constant.","input":"","output":"The generator hard-codes tabs/newlines (`\\t\\t\\t\\t\\t\\t\\t\\t`) at `core/c/model.php:86, 94, 101` when concatenating `$fieldarray`. So generated output looks like:\n```php\n'fields' => array(\n 'timeanddate_id' => 'timeanddate_id',\n 'timeanddate_date' => 'timeanddate_date'\n)\n```\nThe indentation is baked into the generator and won't match any other code style — don't try to lint your generated models. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"gotcha","citations":["core/c/model.php:86","core/c/model.php:94","core/c/model.php:101","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How do I share data between `navigationAction()` and `pageAction()`?","input":"","output":"Use instance properties on the controller class:\n```php\nclass UsersController extends Controller {\n private array $userData = [];\n\n public function navigationAction() {\n $this->userData = Db::loadModel('App\\Users')->loadTableAsArray();\n }\n\n public function pageAction() {\n View::assign(['users' => $this->userData]);\n }\n}\n```\nBoth methods run on the same `$controller` instance per the Dispatcher flow at `core/c/dispatcher.php:52` (navigation) and `:60` (page). From `framework-reference-v2.md §6.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.3 Controller Lifecycle","kind":"workflow","citations":["core/c/dispatcher.php:52","core/c/dispatcher.php:60","framework-reference-v2.md §6.3"]}}
|
|
{"instruction":"Quick: which singletons follow `getInstance()` in Nibiru?","input":"","output":"All core singletons: `Config`, `Controller`, `View`, `Pdo`, `Router`, `Dispatcher`, `Engine`. All live under `\\Nibiru\\` (root namespace) at `core/c/*.php`. From `framework-reference-v2.md §1` (namespace map row).","metadata":{"language":"en","source":"framework-reference-v2","section":"1 Namespace Map","kind":"code-recall","citations":["framework-reference-v2.md §1"]}}
|
|
{"instruction":"What's the difference between the `Db` factory and the `Pdo` singleton?","input":"","output":"`Db` is a static factory (`\\Nibiru\\Factory\\Db` at `core/f/db.php:11`) — `Db::loadModel($name)` returns an `IDb` instance, hiding the namespace assembly and `new` call.\n\n`Pdo` is a connection-switcher singleton (`\\Nibiru\\Pdo` at `core/c/pdo.php:12`) — used directly for raw queries (`Pdo::queryString(...)`) or to swap connections (`Pdo::settingsSection('OTHER')`).\n\nUse `Db` when you want to work with a specific table via its model. Use `Pdo` when you want raw SQL or to control which DB section subsequent calls use. From `framework-reference-v2.md §2.2` and §2.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Comparison","kind":"comparison","citations":["core/f/db.php:11","core/c/pdo.php:12","framework-reference-v2.md §2.2","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"How do I use `selectDatasetByFieldAndValue` from Pdo directly?","input":"","output":"```php\nPdo::selectDatasetByFieldAndValue(\n $tablename = 'users',\n $fieldAndValue = ['role' => 'admin'],\n $sortOrder = 'created_at DESC'\n);\n```\nBuilds a `SELECT * FROM users WHERE role = 'admin' ORDER BY created_at DESC`. Routed through `self::getSettingsSection()` so it respects the active `Pdo::$section`. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"What does `Pdo::fetchTableAsArray($tablename, $limit, $order)` do?","input":"","output":"Returns the entire table as a PHP array, with optional pagination via `$limit` and ordering via `$order`. Routes through `self::getSettingsSection()` for connection selection. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"How does `_setFolderOut` decide where to write generated models?","input":"","output":"From `core/c/table.php:208`:\n- If `--folder-out=` was passed via CLI flags, that wins.\n- Otherwise, it concatenates `__DIR__ . config[GENERATOR][folder-out] . $foldernamespace`.\n- `__DIR__` is `core/c/`, so the leading `/../../` in `[GENERATOR][folder-out] = \"/../../application/model/\"` walks back to the project root.\n- `$foldernamespace` is the PascalCased basename (e.g. `WarehouseLoach`).\n\nResult: `core/c/../../application/model/WarehouseLoach/` -> `application/model/WarehouseLoach/`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/table.php:208","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How do I read `pageurl` from the INI inside controller code?","input":"","output":"```php\n$url = Config::getInstance()->getConfig()['SETTINGS']['pageurl'];\n```\nThe key is custom (no core consumer). The framework only documents it — you read it manually. From `framework-reference-v2.md §7 [SETTINGS]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What does `entriesperpage` do in the INI?","input":"","output":"It's a custom-use INI key in `[SETTINGS]` with no core consumer — application code reads it for pagination size. The framework documents it in `framework-reference-v2.md §7 [SETTINGS]` but doesn't act on it.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"My module's trait has a public method but the IDE says it's undefined when used in another module's class. Why?","input":"","output":"Module-specific traits live under `\\Nibiru\\Module\\<Name>\\Traits\\<TraitName>`. To use a trait from module `users` (`\\Nibiru\\Module\\Users\\Traits\\UserForm`) inside another class, you must `use \\Nibiru\\Module\\Users\\Traits\\UserForm;` AND ensure the autoloader has loaded the trait file. The autoloader only scans the trait if `[AUTOLOADER] trait.pos[] = \"users\"` is in the INI. If you reference the trait from a class in a different module that loads BEFORE `users`, the trait won't be available yet. From `framework-reference-v2.md §1`, §4.2, §11.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Debug","kind":"debug","citations":["framework-reference-v2.md §1","framework-reference-v2.md §4.2","framework-reference-v2.md §11.4"]}}
|
|
{"instruction":"What does the autogenerator's early-bail check at `core/c/model.php:16` look at?","input":"","output":"`Model::__construct()` early-bails if `[DATABASE][is.active]` is not truthy — the connection is disabled. Even if `[GENERATOR][database] = true`, no autogeneration happens for that section. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/model.php:16","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What value should I pass for `$argv` when instantiating Model from CLI?","input":"","output":"An array of CLI flag strings, e.g. `['--table=foo', '--config-section=DATABASE_REPORTING', '--folder-out=/path/']`. `Table::__construct($argv)` at `core/c/table.php:48-70` parses argv. The shipped `Dispatcher::run()` always passes `false`, so flags are skipped — but a custom CLI wrapper could write `new Model($argv)` and use the flag mechanism. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/table.php:48-70","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What CLI flags does `Table` parse?","input":"","output":"From `core/c/table.php:48-70`: `--table=…`, `--config-section=…`, `--folder-out=…`, and `--help`. Parsed only when `is_array($argv)` returns true (line 51). The shipped framework passes `false` from `Dispatcher::run()`, so flags are inert in normal web requests. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/table.php:48-70","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the relationship between `Model` and `Table` classes?","input":"","output":"`Model extends Table`. `Model::__construct($argv)` at `core/c/model.php:14` calls `parent::__construct($argv)` at line 18, which is `Table::__construct`. `Table` parses CLI flags / INI defaults and gathers metadata; `Model` does the actual file generation via `createOutFolder()` (line 28) and `createClassFiles()` (line 37). From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"comparison","citations":["core/c/model.php:14","core/c/model.php:18","core/c/table.php:48","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What controllers does Nibiru ship in core?","input":"","output":"None. Controllers live in `application/controller/*Controller.php` per the Appendix file index. The framework provides only the base `Controller` singleton at `core/c/controller.php`. Application controllers extend `Controller` and define `*Action()` methods. From `framework-reference-v2.md` Appendix and §6.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"comparison","citations":["framework-reference-v2.md Appendix","framework-reference-v2.md §6.3"]}}
|
|
{"instruction":"How does `Display` differ from `View`?","input":"","output":"`View::getInstance()` is the Smarty wrapper at `core/c/view.php:11` — call `View::assign()` and `View::display($page)` to render templates. `Display::getInstance()->display()` is called at the very end of `Dispatcher::run()` to perform the final rendering pass (sending output to the browser). From `framework-reference-v2.md §6.4` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.4 View Rendering","kind":"comparison","citations":["framework-reference-v2.md §6.4","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What's a TypeRange template good for?","input":"","output":"`TypeRange` (at `core/c/typerange.php`, factory `addTypeRange`) renders an HTML5 `<input type=\"range\">` slider. Use it for numeric ranges with min/max/step. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typerange.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"Explain how the form factory's `$option` static buffer works.","input":"","output":"`self::$option` accumulates option HTML between `addSelectOption()` calls. Each call:\n```php\npublic static function addSelectOption( $attributes ) {\n self::setElement( new TypeOption() );\n self::assembleOptions( self::getElement()->loadElement( $attributes ) );\n}\n```\nappends the rendered `<option>...` to `self::$option`. Then `addSelect()` substitutes that buffer into the `OPTIONS` token of the select template via `displaySelect()` and clears the buffer with `assembleOptions(false)`. From `core/f/form.php:493-497` and `framework-reference-v2.md §5.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.6 Select/Option Ordering","kind":"code-recall","citations":["core/f/form.php:493-497","core/f/form.php:71","framework-reference-v2.md §5.6"]}}
|
|
{"instruction":"My second `<select>` ends up containing the options from the first. What's wrong?","input":"","output":"Most likely you didn't follow the option-then-select sequence for the SECOND select, OR `addSelect()` failed and didn't reach `assembleOptions(false)`. Each `addSelect()` clears the option buffer for the next select via `assembleOptions(false)` (`core/f/form.php:471`). If you accidentally called `addSelectOption` for the second dropdown BEFORE flushing the first via `addSelect`, both sets of options end up in the first select. The fix is to always pair option calls with the matching select call before starting the next group. From `framework-reference-v2.md §5.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.6 Select/Option Ordering","kind":"debug","citations":["core/f/form.php:471","framework-reference-v2.md §5.6"]}}
|
|
{"instruction":"What's the namespace of `TypeText`?","input":"","output":"`\\Nibiru\\Form\\TypeText`. All Type classes live under `\\Nibiru\\Form\\Type<X>` in `core/c/type<x>.php`. Note: this is `\\Nibiru\\Form\\` not `\\Nibiru\\Factory\\Form\\` — the factory and the Type classes are in different namespaces. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typetext.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What's the namespace of `Form` factory vs `Form` Type wrapper?","input":"","output":"Two different `Form` classes:\n- `\\Nibiru\\Factory\\Form` at `core/f/form.php` — the static factory (`Form::create()`, `Form::addInputType*()`).\n- `\\Nibiru\\Form\\Form` (inline class) — the `<form>` Type wrapper used internally by `Form::addForm()`.\n\nDon't confuse them. The factory is what callers use; the Type is internal. From `framework-reference-v2.md §5.1` and §5.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"comparison","citations":["core/f/form.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What happens at line 14 of `core/c/pdo.php`?","input":"","output":"That line declares the static `$section` property on the `Pdo` class. It is the single piece of state that determines which `[DATABASE*]` connection subsequent queries use. Mutated by `Pdo::settingsSection($section)`. Read by `Pdo::getSettingsSection()` and consumed in `parent::getInstance(self::getSettingsSection())`. From `framework-reference-v2.md §2.2` and §11.1.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:14","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"What happens at line 19 of `core/c/pdo.php`?","input":"","output":"That's the public signature of `settingsSection`:\n```php\npublic static function settingsSection( $section = IOdbc::SETTINGS_DATABASE )\n```\nDefault argument is `IOdbc::SETTINGS_DATABASE`, which is the literal `\"DATABASE\"`. Calling with no argument resets the static section back to the default primary connection. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:19","core/i/IOdbc.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"Quick: where's the literal model template file path resolved?","input":"","output":"`Table::_setTemplateFile()` at `core/c/table.php:67`. It resolves to `__DIR__ . config[GENERATOR][modeltemplate]`, where `__DIR__` is `core/c/` and the INI value is typically `\"/../../application/settings/db/db.class.mask\"`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/table.php:67","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Where does `_setDatabase` look up the database name?","input":"","output":"`Table::_setDatabase()` at `core/c/table.php:194`: `$dbName = config[$configSection][basename]`. `$configSection` defaults to `[GENERATOR][config-section]` (typically `\"DATABASE\"`), and the actual DB name comes from the matching `[DATABASE*][basename]` INI value. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/table.php:194","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What does `Table::_setDbNamespace()` actually do?","input":"","output":"`core/c/table.php:63` — PascalCases the basename to produce a DB-level namespace fragment. Distinct from `_setFolderNamespace` which produces the folder-name fragment used in `\\Nibiru\\Model\\<FolderName>\\`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/table.php:63","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How is `_setConfigSection()` populated?","input":"","output":"`Table::_setConfigSection()` at `core/c/table.php:162` reads `--config-section=` if a CLI flag was passed, otherwise falls back to `[GENERATOR][config-section]` from the INI. The default INI value is `\"DATABASE\"`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["core/c/table.php:162","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Show me the IDb method for updating a row by primary key.","input":"","output":"```php\npublic function updateRowById(array $rowData, int $id, string $encrypted = \"\")\n```\nFrom `core/i/IDb.php`. Usage:\n```php\nDb::loadModel('App\\Users')->updateRowById(\n ['email' => 'new@example.com'],\n 42\n);\n```\nThe optional third parameter applies `DES_ENCRYPT()` to the listed columns. From `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"How do I update by a non-PK column with the IDb interface?","input":"","output":"`updateRowByFieldWhere($wherefield, $wherevalue, $rowfield, $rowvalue)`:\n```php\nDb::loadModel('App\\Users')->updateRowByFieldWhere('email', 'old@example.com', 'email', 'new@example.com');\n```\nBuilds `UPDATE users SET email='new@example.com' WHERE email='old@example.com'`. From `core/i/IDb.php` and `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"How do I delete a row by ID?","input":"","output":"```php\nDb::loadModel('App\\Users')->deleteRowById(42);\n```\nThe IDb signature is `deleteRowById(int $id = 0)`. The default `0` would target a row with PK=0 if any exists; always pass an explicit ID. From `core/i/IDb.php` and `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"workflow","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"What's `IDb::selectRowsetById($id)` vs `IDb::selectRowByFieldWhere($field)`?","input":"","output":"`selectRowsetById($id)` returns the single row whose PK equals `$id` (uses the model's TABLE constant for PK). `selectRowByFieldWhere($field = array())` returns the single row whose column matches `$field['field'] => $field['value']` — useful for non-PK lookups (e.g. `email`). Both fetch one row; only the WHERE clause shape differs. From `core/i/IDb.php` and `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"comparison","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"What does the framework do with `[ENGINE][debug_template]`?","input":"","output":"`View::_setEngine()` at `core/c/view.php:66-79` reads it as the path to the Smarty debugbar template (default-relative path resolved from `core/c/../..`). Pair with `[ENGINE][debugbar] = true` to actually render the bar. From `framework-reference-v2.md §7 [ENGINE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [ENGINE]","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}}
|
|
{"instruction":"What runs at line 119 of `core/framework.php`?","input":"","output":"```php\nNibiru\\Dispatcher::getInstance()->run();\n```\nThis is the boot statement that fires the entire request lifecycle: routing, model loading, module loading, controller instantiation, action calls, and final rendering. From `framework-reference-v2.md §12` step 4.","metadata":{"language":"en","source":"framework-reference-v2","section":"12 Request Trace","kind":"code-recall","citations":["core/framework.php:119","framework-reference-v2.md §12"]}}
|
|
{"instruction":"How does the autogenerator handle a brand-new application with zero existing model files?","input":"","output":"`Model::createOutFolder()` at `core/c/model.php:28` does `mkdir -p` (chmod 0777) for the target folder, then `createClassFiles()` at line 37 loops through scanned tables (or one table if `--table=` was passed) and calls `generateClassByTableName($table)` for each. For each class file:\n1. If overwrite mode, `unlink` existing.\n2. Otherwise `fopen('w'); fclose()` to create an empty stub.\n3. Build template, do all 8 placeholder substitutions plus driver/odbc switching.\n4. Write file and chmod 0777.\n\nSo zero existing files becomes a full set of generated models on the first request. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/model.php:28","core/c/model.php:37","core/c/model.php:53","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Quick: what's the sequence for rendering a page in Nibiru?","input":"","output":"From `framework-reference-v2.md §6.2` end-of-flow:\n1. `navigationAction()` runs.\n2. `{_action}Action()` runs (if applicable).\n3. `pageAction()` runs.\n4. `Debug::getInstance()` (debug info if enabled).\n5. `Display::getInstance()->display()` (actual Smarty render to browser).","metadata":{"language":"en","source":"framework-reference-v2","section":"6.4 View Rendering","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md §6.4"]}}
|
|
{"instruction":"What does `Mysql::__construct()` do at line 32?","input":"","output":"From `core/c/pdo.php` line 32 (inherited via `Pdo extends Mysql`):\n```php\nif($section)\n{\n $settings = Config::getInstance()->getConfig()[$section];\n}\nelse\n{\n $settings = Config::getInstance()->getConfig()[self::SETTINGS_DATABASE]; // defaults to [DATABASE]\n}\n```\nIt reads the appropriate `[DATABASE*]` block based on the `$section` argument, which originated from `Pdo::$section` via `getSettingsSection()`. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php:32","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"How can I tell at a glance which DB section a generated model targets?","input":"","output":"Look at the `__construct()` body — the `[CONNECTOR]::settingsSection('[DBSECTION]')` line is hard-baked at generation time. Example:\n```php\npublic function __construct()\n{\n Pdo::settingsSection('DATABASE_REPORTING');\n self::initTable( self::TABLE );\n}\n```\nThe argument literal is exactly the INI section name. From `framework-reference-v2.md §3.2` mask file.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["application/settings/db/db.class.mask","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What does `IDb::selectDatasetByFieldWhere($fieldWhere = array(), $sortOrder = false)` do?","input":"","output":"Returns the rowset matching the given column/value pair, optionally ordered. `$fieldWhere` is `['field' => 'col', 'value' => 'foo']`; `$sortOrder` is a SQL `ORDER BY` snippet. Default `$sortOrder = false` means no explicit ordering. From `core/i/IDb.php` and `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"What's IModule supposed to declare?","input":"","output":"The interface is at `core/i/IModule.php`. The v2 reference doesn't enumerate its methods, only that every module main class must implement it. The base `Module` class at `core/c/module.php` provides default behavior; subclasses fulfill the contract. From `framework-reference-v2.md §4.3` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"code-recall","citations":["core/i/IModule.php","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"Why use `Db::loadModel('Folder\\Acl')` instead of `Db::loadModel('Acl')`?","input":"","output":"Because the autoloader uses PSR-4-style folder layout: `\\Nibiru\\Model\\Folder\\Acl` corresponds to `application/model/Folder/Acl.php`. If you call `Db::loadModel('Acl')`, the factory builds `\\Nibiru\\Model\\Acl`, which would map to `application/model/Acl.php` — likely a different file (or none at all). The folder fragment matches the database basename's PascalCased namespace (e.g. `WarehouseLoach` for basename `warehouse_loach`). From `framework-reference-v2.md §1`, §2.3, §8.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"workflow","citations":["framework-reference-v2.md §1","framework-reference-v2.md §2.3","framework-reference-v2.md §8"]}}
|
|
{"instruction":"What if I want to manually write a model class instead of using the autogenerator?","input":"","output":"Place the file at `application/model/<FolderName>/<ClassName>.php` matching the namespace `\\Nibiru\\Model\\<FolderName>\\<ClassName>`. Extend the appropriate adapter (`\\Nibiru\\Adapter\\MySQL\\Db`, `Postgres\\Db`, or `Postgresql\\Db`). Provide the `TABLE` constant, the `__construct()` that calls `Pdo::settingsSection('DBSECTION')` and `self::initTable( self::TABLE )`, plus `getTableInfo()`, setters, and getters. Keep `[GENERATOR][database] = false` in your INI so a future generator run doesn't overwrite the file (or set `database.overwrite = false` and ensure the file is not zero bytes). From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the constant `IMysql::PLACE_NO_QUERY` used for?","input":"","output":"`PLACE_NO_QUERY = \"NO QUERY\"` — a placeholder string the framework returns or compares against when no SQL was supplied. Sentinel pattern: instead of empty string or null, the framework uses recognizable string sentinels. From `core/i/IMysql.php` and `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What other `PLACE_*` sentinels does IMysql declare?","input":"","output":"From `core/i/IMysql.php`:\n```php\nconst PLACE_NO_QUERY = \"NO QUERY\";\nconst PLACE_TABLE_NAME = \"NO TABLENAME\";\nconst PLACE_ARRAY_NAME = \"NO ARRAY\";\nconst PLACE_QUERY_LIMIT = \"NO LIMIT\";\nconst PLACE_SORT_ORDER = \"NO ORDER\";\nconst PLACE_DSN = \"NO CONNECTION STRING\";\nconst PLACE_COLUMN_NAME = \"NO COLUMN NAME\";\nconst PLACE_SEARCH_TERM = \"NO SEARCH PARAMETER\";\nconst PLACE_FIELD_NAME = \"NO FIELD NAME\";\nconst PLACE_WHERE_VALUE = \"NO WHERE VALUE\";\n```\nAll string sentinels for missing arguments. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What's the framework's pattern for PSR-4 autoloading the core itself?","input":"","output":"`core/l/autoload.php` is the PSR-4 autoloader hook. It maps namespace prefixes like `\\Nibiru\\Factory\\`, `\\Nibiru\\Adapter\\`, `\\Nibiru\\Form\\`, `\\Nibiru\\` (root) to their corresponding `core/f/`, `core/a/`, `core/c/`, `core/c/` directories. Distinct from `core/c/auto.php` (`Auto::loader()`) which scans application module/model directories driven by INI keys. From `framework-reference-v2.md` Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"workflow","citations":["core/l/autoload.php","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"Why do generated models import `use Nibiru\\Adapter\\<Adapter>\\Db;` and `use Nibiru\\Pdo;` together?","input":"","output":"Two different concerns:\n- `use Nibiru\\Adapter\\<Adapter>\\Db;` brings in the base adapter the model EXTENDS. For MySQL: `\\Nibiru\\Adapter\\MySQL\\Db`. For Postgres: `\\Nibiru\\Adapter\\Postgres\\Db` or `\\Nibiru\\Adapter\\Postgresql\\Db`.\n- `use Nibiru\\Pdo;` brings in the connection-switcher singleton called from the model's `__construct()` via `Pdo::settingsSection('DBSECTION')`.\n\nThe second import is hardcoded in the mask — which is the Postgres footgun, since for Postgres models the `__construct()` actually calls `Postgres::settingsSection(...)`, not `Pdo::settingsSection(...)`. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"comparison","citations":["application/settings/db/db.class.mask","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How do I handle an HTTP 404 properly in Nibiru?","input":"","output":"Configure `[ENGINE][error_controller]` and `[ENGINE][error_template]` in your INI. When the Dispatcher fails to find `application/controller/{ControllerName}Controller.php`, lines 75-80 of `core/c/dispatcher.php` route to that error controller, which renders the matching template. Without these INI keys, the soft-404 path fails — the framework has no built-in default. From `framework-reference-v2.md §6.2` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["core/c/dispatcher.php:75-80","framework-reference-v2.md §6.2","framework-reference-v2.md §7"]}}
|
|
{"instruction":"How do I switch to a single `[DATABASE_LOG]` connection and execute a one-off raw query?","input":"","output":"```php\nuse Nibiru\\Pdo;\nPdo::settingsSection('DATABASE_LOG');\n$rows = Pdo::queryString('SELECT * FROM event_log WHERE level = \"warn\"', true);\n// remember to restore if subsequent code expects the default:\nPdo::settingsSection(); // resets to IOdbc::SETTINGS_DATABASE = \"DATABASE\"\n```\nFrom `framework-reference-v2.md §2.2` and §11.1.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["core/c/pdo.php:14","framework-reference-v2.md §3.3"]}}
|
|
{"instruction":"Why does `Pdo::settingsSection()` not return the previous section?","input":"","output":"It's a setter, not a getter. From `core/c/pdo.php:19`, the signature returns void (or whatever the parent does — but it's a write operation). To capture the previous section, read `Pdo::getSettingsSection()` BEFORE calling the setter:\n```php\n$prev = Pdo::getSettingsSection();\nPdo::settingsSection('DATABASE_LOG');\n// ...do work...\nPdo::settingsSection($prev);\n```\nFrom `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"workflow","citations":["core/c/pdo.php:19","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"Quick: what does the framework's `Engine` singleton do?","input":"","output":"`core/c/engine.php` provides the template engine setup (Smarty configuration). Listed in the namespace map at `framework-reference-v2.md §1` as one of the core singletons under `\\Nibiru\\` root namespace alongside `Config`, `Controller`, `View`, `Pdo`, `Router`, `Dispatcher`. From `framework-reference-v2.md §1` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["core/c/engine.php","framework-reference-v2.md §1"]}}
|
|
{"instruction":"What's the role of the Router singleton?","input":"","output":"`\\Nibiru\\Router` at `core/c/router.php` parses the URL into controller/action segments. Called by `Dispatcher::run()` step 3 — `Router::getInstance()->route()`. It populates `$_REQUEST['_action']` and exposes the controller name. INI keys `[ROUTING][route[index]]` and `[ROUTING][route[controller]]` configure prefixes. From `framework-reference-v2.md §6.2` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"code-recall","citations":["core/c/router.php","framework-reference-v2.md §6.2","framework-reference-v2.md §7"]}}
|
|
{"instruction":"How do I know which controller is currently active mid-request?","input":"","output":"Call `Controller::getInstance()->getController()` — returns the URL-derived controller name (segment 1 of the URL). Defined at `core/c/controller.php:14`. Useful for breadcrumb/navigation rendering in `navigationAction()`. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"What does `Form::addOpenSpan` do?","input":"","output":"`TypeOpenSpan` at `core/c/typeopenspan.php` renders `<span ID CLASS>`. It has no direct factory method (legacy) — use `Form::addOpenAny(['any' => 'span'])` instead, which is the actively maintained path. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeopenspan.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"Show me a complete user-edit form example using the canonical helpers.","input":"","output":"From `nibiru-modules/application/module/users/traits/userForm.php:22-89`:\n```php\nForm::create();\nself::openHalfWidthElement('Benutzer Informationen');\nself::openInnerHalfWithElement();\nforeach(self::FORM_CREATE_USER as $entry) {\n self::addTextElement($entry['visibleName'], $entry['valueName'], $entry['icon'], $user[$entry['valueName']] ?? '');\n}\nself::addSelectDropdown($acl->loadAclRoles(), 'lock', $user['user_role_id']);\nself::closeHalfWidthElement();\nself::addSubmitFormButton('Speichern', 'save-alt');\nreturn Form::addForm([\n 'name' => 'userForm',\n 'action' => $action,\n 'class' => 'row',\n 'method' => 'post',\n 'target' => '_self',\n]);\n```\nThe trait composes higher-level helpers (`addTextElement`, `addSelectDropdown`, `addSubmitFormButton`) on top of the framework's `Form::add*` primitives. From `framework-reference-v2.md §5.9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"code-recall","citations":["nibiru-modules/application/module/users/traits/userForm.php:22-89","framework-reference-v2.md §5.9"]}}
|
|
{"instruction":"My TypeText doesn't render the `placeholder` attribute even though I passed it. What's wrong?","input":"","output":"Either the key isn't in `TypeText`'s `$_attributes` allowlist (`core/c/typetext.php`) — which it should be — or you used the wrong case. Pass `'placeholder'` (lowercase). The substitution engine at `core/c/formattributes.php:48-58` does:\n```php\ncase array_key_exists($key, $this->_attributes):\n $this->_element = str_replace(strtoupper($key), $entry, $this->getElement());\n```\nIf `$key` doesn't match anything in `$_attributes`, the substitution is silently skipped — and the strip pass at line 84 will erase the unfilled `placeholder=\"PLACEHOLDER\"` fragment from the output. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"debug","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"What's a clean way to read INI values without crashing if a key is missing?","input":"","output":"Wrap with `array_key_exists`:\n```php\n$cfg = Config::getInstance()->getConfig();\n$value = array_key_exists('SECTION', $cfg) && array_key_exists('key', $cfg['SECTION'])\n ? $cfg['SECTION']['key']\n : 'fallback';\n```\nWithout the check, `Config::getInstance()->getConfig()['MISSING']['key']` returns `NULL` silently (per `framework-reference-v2.md §11.6`), and downstream code that depends on a string/int will misbehave.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.6 Missing INI Keys","kind":"workflow","citations":["framework-reference-v2.md §11.6"]}}
|
|
{"instruction":"What's the difference between Pdo's `query` and `queryString`?","input":"","output":"From `framework-reference-v2.md §2.2`:\n- `query($string)` — generic execute or fetch; routes via `parent::getInstance(self::getSettingsSection())`. Used for INSERT/UPDATE/DELETE or single-fetch.\n- `queryString($string, $associative)` — fetch all rows into a PHP array. The second flag controls associative-vs-numeric result keys.\n\nUse `query` for write operations or one-row fetches; use `queryString` for `SELECT * FROM ...` style retrieval. Both respect the active `Pdo::$section`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"comparison","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"Quick question: is `addSelectOption` the same as `addOption`?","input":"","output":"It's only `addSelectOption`. The factory does NOT expose `addOption`. From `framework-reference-v2.md §5.4` (Select/option row). The factory is at `core/f/form.php:493-497`. Calling `Form::addOption(...)` would result in a method-not-found error.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"gotcha","citations":["core/f/form.php:493-497","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How do I include the framework config in my own custom singleton?","input":"","output":"```php\n$cfg = \\Nibiru\\Config::getInstance()->getConfig();\n$dbName = $cfg['DATABASE']['basename'];\n$timezone = $cfg['SETTINGS']['timezone'];\n```\n`Config::getInstance()` is the entry point at `core/c/config.php:12`; the returned `Settings` object exposes `getConfig()` which yields the parsed INI as a nested associative array. From `framework-reference-v2.md §2.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"workflow","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"How does Nibiru detect the current environment?","input":"","output":"`Config::getInstance()` at `core/c/config.php:12` reads `getenv('APPLICATION_ENV')` first, then falls back to a defined `APPLICATION_ENV` constant. The result selects `settings.<ENV>.ini`. So `APPLICATION_ENV=production` -> `settings.production.ini`. Set the env var at the web server (Apache `SetEnv`, nginx `fastcgi_param`) or define the constant before the framework boots. From `framework-reference-v2.md §2.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"workflow","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"What's the namespace of `Settings` returned by `Config::getInstance()`?","input":"","output":"`\\Nibiru\\Settings` at `core/c/settings.php`. The signature `Config::getInstance(): Settings` returns a `\\Nibiru\\Settings` instance that wraps the parsed INI. Use `->getConfig()` to access the array. From `core/c/config.php:12` and Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"code-recall","citations":["core/c/config.php:12","core/c/settings.php","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"What does the `[DATABASE][port]` default to when omitted?","input":"","output":"`3306` (the MySQL default). Read by `Mysql::__construct()`. The framework will use `3306` if the INI omits the `port` key. From `framework-reference-v2.md §7 [DATABASE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What's the default encoding if `[DATABASE][encoding]` is omitted?","input":"","output":"`utf8`. Real example uses `\"UTF8\"` (production) which is the same. The framework applies it to the connection charset. From `framework-reference-v2.md §7 [DATABASE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"inikey","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"How do I run a SELECT and feed the results to a Smarty template?","input":"","output":"```php\nuse Nibiru\\Factory\\Db;\nuse Nibiru\\View;\n\n$users = Db::loadModel('App\\Users')->loadTableAsArray();\nView::assign(['users' => $users]);\n```\nIn `users.tpl`:\n```\n{foreach from=$users item=u}\n <li>{$u.email}</li>\n{/foreach}\n```\nFrom `framework-reference-v2.md §2.6`, §2.3, Quick Reference.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §2.3","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"Quick: which Smarty tag prefix does Nibiru's `View::assign` use?","input":"","output":"Standard Smarty `$` syntax. After `View::assign(['user_name' => 'John'])`, the template references it as `{$user_name}`. There's no Nibiru-specific prefix — Smarty's defaults apply. From `framework-reference-v2.md §2.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"Where does Smarty look for templates by default?","input":"","output":"At `core/c/../../{ENGINE[templates]}` — i.e. relative to `core/c/`, walking up two levels. The INI key `[ENGINE][templates]` defaults to `/../../application/view/templates/`, so the absolute path resolves to `application/view/templates/`. Set in `View::_setEngine()` at `core/c/view.php:66-79`. From `framework-reference-v2.md §2.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"inikey","citations":["core/c/view.php:66-79","framework-reference-v2.md §7"]}}
|
|
{"instruction":"How do I rename a module from `users` to `accounts` without breaking module loading?","input":"","output":"1. Rename directory: `application/module/users/` -> `application/module/accounts/`.\n2. Rename main class file: `accounts.php` (lowercase, matching dir name).\n3. Rename class itself: `class Users` -> `class Accounts`, namespace `\\Nibiru\\Module\\Users` -> `\\Nibiru\\Module\\Accounts`.\n4. Update INI: change `class.pos[] = \"users\"` to `\"accounts\"`. Same for `iface.pos[]`, `trait.pos[]`, `class.plugin.pos[]` if applicable.\n5. Update consumers: `use Nibiru\\Module\\Users\\Traits\\UserForm` -> `use Nibiru\\Module\\Accounts\\Traits\\AccountForm`.\n\nThe autoloader scans by directory name, so the disk path and the INI registry name must match. From `framework-reference-v2.md §1`, §4.2, §11.7.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Refactor","kind":"refactor","citations":["framework-reference-v2.md §1","framework-reference-v2.md §4.2","framework-reference-v2.md §11.7"]}}
|
|
{"instruction":"Quick question: can I use composer's PSR-4 autoloader for application code in Nibiru?","input":"","output":"You can layer it on top, but Nibiru's own autoloading is INI-driven (`Auto::loader()` at `core/c/auto.php`) and NOT PSR-4. New modules must be registered in `[AUTOLOADER] class.pos[]`; the framework won't pick them up via composer.json mappings alone. The PSR-4 hook at `core/l/autoload.php` handles framework-internal classes. From `framework-reference-v2.md §11.7` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.7 Autoloader not PSR-4","kind":"comparison","citations":["framework-reference-v2.md §11.7","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"Show me a real production INI database section.","input":"","output":"From `loach.mssql.database-connection/application/settings/config/settings.production.ini`:\n```ini\n[DATABASE]\nis.active = true\nusername = \"loach\"\npassword = \"08mj7hchqegtjf7znc6978d\"\nhostname = \"sto-loach-production-mariadb-1\"\nbasename = \"warehouse_loach\"\ndriver = \"mysql\"\nport = \"3306\"\nencoding = \"UTF8\"\ndb_info_print = 0\n```\nDocker-style hostname (`sto-loach-production-mariadb-1`) — Nibiru speaks to MariaDB through the standard MySQL driver. From `framework-reference-v2.md §7 [DATABASE]`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [DATABASE]","kind":"code-recall","citations":["loach.mssql.database-connection/application/settings/config/settings.production.ini","framework-reference-v2.md §7"]}}
|
|
{"instruction":"What happens when I instantiate a generated Postgres model that references `Postgres::settingsSection`?","input":"","output":"PHP looks up `Postgres` in the model's current namespace (`\\Nibiru\\Model\\<Folder>`) and the imported `use` statements. The mask hardcodes `use Nibiru\\Pdo;` — NOT `use Nibiru\\Postgres;` — so the unqualified `Postgres::settingsSection(...)` call resolves to `\\Nibiru\\Model\\<Folder>\\Postgres`, which doesn't exist. PHP fatals with `Class 'Nibiru\\Model\\<Folder>\\Postgres' not found`.\n\nFix: edit the generated file to add `use Nibiru\\Postgres;` (or `use Nibiru\\Postgresql;`). From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["application/settings/db/db.class.mask:4","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How do I add a new `[DATABASE_X]` section without touching anything else?","input":"","output":"1. Add the block to your INI:\n```ini\n[DATABASE_X]\nis.active = true\nusername = \"...\"\npassword = \"...\"\nhostname = \"...\"\nbasename = \"...\"\ndriver = \"mysql\"\nport = \"3306\"\nencoding = \"utf8\"\n```\n2. In code, switch with `Pdo::settingsSection('DATABASE_X')` before queries, OR generate models for that section by setting `[GENERATOR][config-section] = \"DATABASE_X\"` temporarily and reloading. Reset `[GENERATOR][config-section]` after. From `framework-reference-v2.md §3.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.3 Multi-Database","kind":"workflow","citations":["framework-reference-v2.md §3.3"]}}
|
|
{"instruction":"What's `Form::addTypeButton` good for?","input":"","output":"It renders `<button>VALUE</button>`. The `value` attribute is used as the inner HTML — you can embed icon markup. Production callsite (per `framework-reference-v2.md §5.4`): `'value' => '<i class=\"ti-save\"></i> Speichern'`. The substitution engine does no escaping, so embedded HTML renders as-is. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How do I set an autocomplete pattern on an email input?","input":"","output":"```php\nForm::addInputTypeEmail([\n 'name' => 'email',\n 'pattern' => '[a-z0-9._%+-]+@[a-z0-9.-]+',\n 'required'=> 'required',\n]);\n```\n`TypeEmail`'s allowlist includes `pattern`. The substitution engine substitutes `PATTERN` -> the value. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What does the framework do with `Module` adapter at `core/a/module.php`?","input":"","output":"It's the adapter base class for modules — `\\Nibiru\\Adapter\\Module`. Listed in the Appendix file index alongside `core/c/module.php` (the concrete `Module` base class). Modules typically extend `Module` (from `core/c/module.php`) which itself may extend or use the adapter base. From `framework-reference-v2.md` Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["core/a/module.php","core/c/module.php","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"Where do I put SQL migration files in a Nibiru project?","input":"","output":"By convention, `application/settings/config/database/`. Filenames are numeric-prefixed for ordering (e.g. `001-acl.sql`, `002-account.sql`, `012-add-unique-key-user.sql`). The framework v2 reference doesn't document a built-in migration runner — these are typically applied manually or via an external tool. From the project structure visible in the repo and `framework-reference-v2.md` Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"workflow","citations":["framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"How does the framework handle `getRequest($param, $params = false)`?","input":"","output":"From `core/c/controller.php:14`: `getRequest($param, bool $params = false)`. The first arg is the parameter name; the second flag controls whether the helper expects `$param` to be an array of names (returning multiple values at once) versus a single name. Default `false` means single-name mode. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"code-recall","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"How do I get all `_action` candidates without hardcoding the method names?","input":"","output":"The Dispatcher uses `$_REQUEST['_action']` and dynamically calls `$controller->{$_action}Action()` if the method exists. To enumerate available actions on a given controller, use PHP reflection — `(new ReflectionClass($controller))->getMethods(ReflectionMethod::IS_PUBLIC)` and filter by `Action` suffix. The framework itself doesn't expose a registry. From `framework-reference-v2.md §6.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["framework-reference-v2.md §6.2"]}}
|
|
{"instruction":"What's the safe way to add an unrecognized HTML5 attribute to a form input?","input":"","output":"You can't, with the standard Type classes. The substitution engine at `core/c/formattributes.php:48-58` only substitutes keys that the Type's `$_attributes` allowlist recognizes — unknown keys are silently dropped. To add a new attribute (say `inputmode`), edit the Type class: add `self::FORM_ATTRIBUTE_INPUTMODE` (or define a new constant in `IForm`) to `$_attributes`, and add an `inputmode=\"INPUTMODE\"` token to `$_element`. From `framework-reference-v2.md §5.2` and §5.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"refactor","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"How does `addForm` actually return HTML?","input":"","output":"`Form::addForm($attributes)` instantiates the inline `\\Nibiru\\Form\\Form` Type, calls `loadElement($attributes)` on it (which substitutes the `<form …>` template attributes), then `display()` at `core/f/form.php:106` does `str_replace('FIELDS', self::$form, $template)` to inject the accumulated buffer, and returns the resulting HTML string. From `framework-reference-v2.md §5.8`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.8 Assembly Pipeline","kind":"code-recall","citations":["core/f/form.php:106","framework-reference-v2.md §5.8"]}}
|
|
{"instruction":"What if I call `Form::addForm()` twice — does the second call get the same buffer?","input":"","output":"Yes, unless you call `Form::create()` between them. `addForm()` doesn't reset the buffer; it just substitutes `FIELDS` with the current `self::$form`. So a second `addForm()` would render the same fields wrapped in a different `<form>` tag. To start a fresh form, call `Form::create()` to clear the buffer. From `framework-reference-v2.md §2.4` and §5.8.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.8 Assembly Pipeline","kind":"edge-case","citations":["core/f/form.php:41","framework-reference-v2.md §5.8"]}}
|
|
{"instruction":"What's the right way to access a session value with safety?","input":"","output":"```php\n$user = $this->getSession('user', false, true);\n```\nThe third argument `$checkForActiveSession = true` makes the helper verify session-active state before accessing `$_SESSION`. Without it, you may read from a not-yet-started session. From `core/c/controller.php:14` and `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"What's `IDb::insertArrayIntoTable` signature?","input":"","output":"```php\npublic function insertArrayIntoTable($dataset = array())\n```\nFrom `core/i/IDb.php`. Pass an associative array of column => value:\n```php\nDb::loadModel('App\\Logs')->insertArrayIntoTable([\n 'log_message' => 'something happened',\n 'log_timestamp' => date('Y-m-d H:i:s'),\n]);\n```\nFrom `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"Quick: what files would I need to read to truly understand the autogenerator?","input":"","output":"In order:\n1. `core/c/dispatcher.php:35-39` — the trigger.\n2. `core/c/model.php:14, 18, 28, 37, 53-148` — the executor and `generateClassByTableName` substitution engine.\n3. `core/c/table.php:48-70, 63, 67, 111, 148, 162, 194, 208, 217` — the metadata gatherer.\n4. `application/settings/db/db.class.mask` — the substitution template.\n5. `core/a/mysql.db.php:15` — the base adapter.\n6. `core/c/pdo.php:14, 19, 32` — the connection switcher.\n\nFrom `framework-reference-v2.md §3.2` (the entire section is the trace).","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the cleanest way to test that the autogenerator regenerated my file?","input":"","output":"1. Delete the file: `rm application/model/<Folder>/<Class>.php`.\n2. Ensure `[GENERATOR][database] = true` and `database.overwrite = false` in dev INI.\n3. Hit any URL.\n4. Confirm the file reappears with current schema.\n\nThe `filesize() == 0` check at `core/c/model.php:133-145` means a deleted file (not present) hits the `fopen('w')` path that creates the empty stub, then writes the full template. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/model.php:133-145","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What's the trade-off between `database.overwrite = true` and `database.overwrite = false`?","input":"","output":"With `true`: every request `unlink`s and rewrites every model file. Schema changes are picked up immediately, but ANY hand-edits are destroyed. Use ONLY in CI or one-off bulk regeneration.\n\nWith `false` (default): only zero-byte files are written. Existing model files are preserved across requests. Schema additions show up only when you delete the model file and reload. Safe for daily development.\n\nProduction should always be `false`, AND the master switch `[GENERATOR][database] = false` to skip the whole branch. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"comparison","citations":["framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What does `IMysql::SETTINGS_DATABASE` evaluate to at runtime?","input":"","output":"The literal string `\"DATABASE\"`. Used as the default INI section name for `[DATABASE]`-keyed lookups across the framework. From `core/i/IMysql.php` and `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"What's the namespace of `Auto::loader()`?","input":"","output":"`\\Nibiru\\Auto` at `core/c/auto.php`. `Auto::loader()` returns the autoloader instance, on which `loadModelFiles()`, `loadModules()`, and (by extension) module-component scanning are called. Distinct from the PSR-4 hook at `core/l/autoload.php`. From `framework-reference-v2.md` Appendix and §4.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["core/c/auto.php","framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"How does Nibiru handle a controller with an `_action` of `pageAction`?","input":"","output":"The Dispatcher would call `$controller->pageActionAction()` (concatenating `Action` to whatever `_action` value was set). Since that doesn't exist, the action call is skipped — but `pageAction()` still runs as the Dispatcher's mandatory final call at line 60. So the URL `?_action=pageAction` is essentially a no-op for the action layer. From `framework-reference-v2.md §6.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"edge-case","citations":["framework-reference-v2.md §6.2"]}}
|
|
{"instruction":"What's `addInputTypeColor` for?","input":"","output":"`TypeColor` (factory `addInputTypeColor`) renders `<input type=\"color\">` for color picker inputs. Browser provides the native picker UI. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typecolor.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What's `addInputTypeDatetime` for?","input":"","output":"`TypeDatetime` (factory `addInputTypeDatetime`) renders `<input type=\"datetime-local\">`. Combined date+time picker. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typedatetime.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How would I rebuild only one specific model after schema change?","input":"","output":"Easiest: delete the file `rm application/model/<Folder>/<Class>.php`, ensure `[GENERATOR][database] = true` and `database.overwrite = false`, hit any URL. The generator scans all tables but only writes files where `filesize() == 0` (or non-existent), so deleted files get rewritten and untouched files stay intact. Other models are unaffected. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"workflow","citations":["core/c/model.php:133-145","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How do I integrate a navigation JSON file with the controller?","input":"","output":"The framework's `[SETTINGS][navigation]` INI key is a custom-use path with no core consumer. Application code typically reads it in `navigationAction()`:\n```php\n$navPath = Config::getInstance()->getConfig()['SETTINGS']['navigation'];\n$nav = json_decode(file_get_contents($navPath), true);\nView::assign(['nav' => $nav]);\n```\nThe Dispatcher calls `navigationAction()` before any custom action, so navigation is always loaded. From `framework-reference-v2.md §7 [SETTINGS]` and §6.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [SETTINGS]","kind":"workflow","citations":["framework-reference-v2.md §7","framework-reference-v2.md §6.3"]}}
|
|
{"instruction":"What's the consequence of forgetting to call `Form::create()` between two forms?","input":"","output":"The static `self::$form` buffer carries fields from the first form into the second. So calling `Form::addForm(...)` a second time produces HTML that includes ALL previously added fields PLUS any new ones. The second form's `<form>` wrapper then contains everything. Mitigation: always call `Form::create()` to reset before starting a new form. From `framework-reference-v2.md §2.4` and §11.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.4 Form Factory","kind":"gotcha","citations":["core/f/form.php:41","framework-reference-v2.md §11.2"]}}
|
|
{"instruction":"How do I tell at a glance whether two models share a database connection?","input":"","output":"Look at their `__construct()` bodies. Both must call `Pdo::settingsSection('DATABASE')` (or the same section name) for them to share a connection at the time of instantiation. If they target different sections, instantiating either one will mutate `Pdo::$section` — last-write-wins. From `framework-reference-v2.md §11.1` and §3.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"11.1 Pdo last-write-wins","kind":"workflow","citations":["framework-reference-v2.md §11.1","framework-reference-v2.md §3.3"]}}
|
|
{"instruction":"What's the right way to mark a field as required in a Nibiru form?","input":"","output":"Pass `'required' => 'required'` (the value can be any non-empty string, but conventionally `'required'`):\n```php\nForm::addInputTypeEmail([\n 'name' => 'email',\n 'required' => 'required',\n]);\n```\nThe substitution engine swaps `REQUIRED` -> `'required'`, so the rendered HTML reads `required=\"required\"`. The strip rule at `core/c/formattributes.php:84` only fires when the user did NOT pass `required`. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"workflow","citations":["core/c/formattributes.php:84","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"What's the framework's convention for naming controller files?","input":"","output":"Lowercase first letter, camelCase, `Controller` suffix. Example: URL `/users/login` -> `application/controller/usersController.php` -> `class usersController extends Controller`. The Dispatcher checks `application/controller/{ControllerName}Controller.php` exists at line 75-80 of `core/c/dispatcher.php`. From `framework-reference-v2.md §6.2` and §12.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"workflow","citations":["framework-reference-v2.md §6.2","framework-reference-v2.md §12"]}}
|
|
{"instruction":"Can controller class names contain capitals?","input":"","output":"The Dispatcher concatenates `{ControllerName}Controller.php` from the URL segment. The case-handling depends on Router behavior — based on the `usersController` example in §12, the convention is lowercase-first. Capitalized names like `UsersController` would map to a URL segment `Users`, which most web servers normalize to lowercase. Stick with lowercase-first to avoid case-sensitivity issues across platforms. From `framework-reference-v2.md §6.2` and §12.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.2 Dispatcher::run","kind":"edge-case","citations":["framework-reference-v2.md §12"]}}
|
|
{"instruction":"What's Nibiru's MMVC pattern (mentioned in v1)?","input":"","output":"Modular MVC — Module + Model + View + Controller. The v2 reference clarifies that Module is the additional layer alongside MVC: each Module bundles its own Interfaces, Traits, Plugins, and a main class, registered in `[AUTOLOADER]`. Models are autogenerated; Views are Smarty templates; Controllers handle requests. From `framework-reference-v2.md §0` and §4.","metadata":{"language":"en","source":"framework-reference-v2","section":"0 Executive Summary","kind":"comparison","citations":["framework-reference-v2.md §0","framework-reference-v2.md §4"]}}
|
|
{"instruction":"Where does Pdo's `query()` method route through?","input":"","output":"Through `parent::getInstance(self::getSettingsSection())->getConn()`. `parent::` is `Mysql`, `getSettingsSection()` returns the static `Pdo::$section`, `getInstance($section)` returns the lazy singleton connection for that section, and `->getConn()` exposes the underlying PDO/connection handle. From `framework-reference-v2.md §2.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.2 Pdo","kind":"code-recall","citations":["core/c/pdo.php","framework-reference-v2.md §2.2"]}}
|
|
{"instruction":"How do I add a hidden token to a Nibiru form for CSRF protection?","input":"","output":"```php\nForm::addTypeHidden(['name' => 'csrf_token', 'value' => $token]);\n```\n`TypeHidden` accepts `name` and `value`. Place this call BEFORE `Form::addForm(...)` so the field ends up inside the rendered `<form>` via the FIELDS placeholder. From `framework-reference-v2.md §5.4` and §5.8.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"Show me the exact wrapper pattern for a single input with a single-shot div.","input":"","output":"```php\nForm::addInputTypeText(['name' => 'username'], ['class' => 'form-group']);\n```\nProduces:\n```html\n<div class=\"form-group\">\n<input type=\"text\" name=\"username\">\n</div>\n```\nThe `assemble()` method at `core/f/form.php:86-97` substitutes `ELEMENT` -> the rendered input, then resets `self::$div` to `false`. From `framework-reference-v2.md §5.7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.7 div Wrapping","kind":"code-recall","citations":["core/f/form.php:86-97","framework-reference-v2.md §5.7"]}}
|
|
{"instruction":"Quick question: where's `self::$form` actually appended?","input":"","output":"In `assemble()` at `core/f/form.php:86-97`, after the optional `ELEMENT` substitution:\n```php\nself::$form .= $element;\n```\nEvery `add*` method that emits a field calls `assemble()` to append. The buffer accumulates until `Form::addForm()` substitutes it into the `FIELDS` placeholder of the `<form>` wrapper. From `framework-reference-v2.md §5.8`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.8 Assembly Pipeline","kind":"code-recall","citations":["core/f/form.php:86-97","framework-reference-v2.md §5.8"]}}
|
|
{"instruction":"What's the production-ready way to store API keys in INI?","input":"","output":"Add a custom section, e.g.:\n```ini\n[API_KEYS]\nstripe = \"sk_test_...\"\nmailgun = \"key-...\"\n```\nRead via `Config::getInstance()->getConfig()['API_KEYS']['stripe']`. The framework doesn't restrict section names — any block parsed by `parse_ini_file(..., true)` is accessible. From `framework-reference-v2.md §2.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"workflow","citations":["framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"What are the 28 form Type classes' common parent?","input":"","output":"`FormAttributes` at `core/c/formattributes.php`. All Type classes extend it and inherit the `_setAttributes()` method (the substitution engine) plus the static `$_element` storage. They also implement `IForm` to access the 60+ `FORM_*` constants. From `framework-reference-v2.md §5.1` and §5.3.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.1 Form Architecture","kind":"code-recall","citations":["core/c/formattributes.php","framework-reference-v2.md §5.1"]}}
|
|
{"instruction":"What templates does TypeRadio's allowlist support?","input":"","output":"From `framework-reference-v2.md §5.4` (TypeRadio row): `name, value, id, class, checked`. Renders `<input type=\"radio\" …>`. The `checked` attribute follows the same gotcha as TypeCheckbox — passing `true` produces `checked=\"CHECKED\"` literal output. From `framework-reference-v2.md §5.4` and §5.2.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"code-recall","citations":["core/c/typeradio.php","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How do I render a `<textarea>`?","input":"","output":"```php\nForm::addInputTypeTextarea([\n 'name' => 'description',\n 'rows' => '5',\n 'cols' => '60',\n 'value' => 'Initial text content',\n]);\n```\nUses `TypeTextarea`, template `<textarea …>VALUE</textarea>`. The `VALUE` token is replaced by the inner text. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"My fileupload form posts but `$_FILES` is empty. What's wrong?","input":"","output":"The `<form>` tag is missing `enctype=\"multipart/form-data\"`. Pass it to `Form::addForm`:\n```php\nForm::addForm([\n 'method' => 'POST',\n 'action' => '/upload',\n 'enctype' => 'multipart/form-data',\n]);\n```\nWithout the enctype, browsers send only the filename in `$_POST`, not the file contents in `$_FILES`. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"debug","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What's the URL convention that maps to a Nibiru controller?","input":"","output":"URL segment 1 -> controller name, segment 2 -> via `_action` (or default). Example: `/users/login` -> `usersController.php` with `$_REQUEST['_action'] = 'login'` -> `loginAction()`. From `framework-reference-v2.md §12`.","metadata":{"language":"en","source":"framework-reference-v2","section":"12 Request Trace","kind":"workflow","citations":["framework-reference-v2.md §12"]}}
|
|
{"instruction":"How do I unit test an action method that uses `View::forwardTo`?","input":"","output":"`View::forwardTo($page)` triggers an HTTP redirect — typically `header('Location: …')` and `exit`. To unit-test, mock the `View` singleton or wrap the controller's `forwardTo` call behind a method you can stub. The framework doesn't ship a test harness; the static singleton makes direct testing awkward. The pragmatic approach is integration testing via HTTP. From `framework-reference-v2.md §2.6`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"How do I read an INI int value as int instead of string?","input":"","output":"PHP's `parse_ini_file(..., true)` returns scalar values as strings (numeric or otherwise) unless interpreted with `INI_SCANNER_TYPED` flag. Nibiru's `Config::getInstance()` (per `framework-reference-v2.md §2.1`) uses `parse_ini_file(..., true)`, so values come back as strings. Cast at the read site: `(int) Config::getInstance()->getConfig()['SETTINGS']['entriesperpage']`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"edge-case","citations":["framework-reference-v2.md §2.1"]}}
|
|
{"instruction":"How does `addInputTypeSwitch` differ from `addInputTypeCheckbox`?","input":"","output":"Both render boolean controls. `TypeCheckbox` (factory `addInputTypeCheckbox`) is a plain `<input type=\"checkbox\" …>`. `TypeSwitch` (factory `addInputTypeSwitch`) renders an HTML5 toggle/switch markup with `name, id, class, checked, onchange` attributes — visually styled as a slider. Functionally similar; the difference is the rendered markup style. From `framework-reference-v2.md §5.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"comparison","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What's the cleanest pattern for a page that lists all rows from a table?","input":"","output":"```php\nclass UsersController extends Controller {\n public function navigationAction() {\n // load nav for this page\n }\n\n public function pageAction() {\n $rows = Db::loadModel('App\\Users')->loadTableAsArray();\n View::assign(['users' => $rows]);\n // display the template\n }\n}\n```\nDispatcher calls `navigationAction()` first, then `pageAction()` last (per `framework-reference-v2.md §6.3`). The `View::assign` exposes data to Smarty.","metadata":{"language":"en","source":"framework-reference-v2","section":"Cross-Section Workflow","kind":"workflow","citations":["framework-reference-v2.md §6.3","framework-reference-v2.md §2.3","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"How do I bail out of an action early?","input":"","output":"`View::forwardTo($page)` redirects and exits. Useful for ACL plugins:\n```php\nif(!$this->validate()) {\n View::forwardTo('/users/login');\n}\n```\nFrom `loach.mssql.database-connection/application/module/users/plugins/acl.php` and `framework-reference-v2.md §4.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.4 Plugin Pattern","kind":"workflow","citations":["loach.mssql.database-connection/application/module/users/plugins/acl.php","framework-reference-v2.md §4.4"]}}
|
|
{"instruction":"What's the relationship between `[GENERATOR][config-section]` and `[DATABASE]`?","input":"","output":"`[GENERATOR][config-section]` (default `\"DATABASE\"`) tells the autogenerator WHICH `[DATABASE*]` block to introspect for table schema. So `config-section = \"DATABASE_REPORTING\"` makes the generator connect to the database described in `[DATABASE_REPORTING]` and write models that hardcode `Pdo::settingsSection('DATABASE_REPORTING')` in their `__construct()`. From `framework-reference-v2.md §3.2` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"comparison","citations":["framework-reference-v2.md §3.2","framework-reference-v2.md §7"]}}
|
|
{"instruction":"My Smarty template can't find `{$user_name}` even though I assigned it. What's wrong?","input":"","output":"Likely causes:\n1. `View::assign()` was called AFTER the page was rendered. The Dispatcher renders at the end of `run()` via `Display::getInstance()->display()`, so all `assign` calls must happen before that — typically inside `pageAction()`.\n2. You assigned to a different singleton scope. `View::assign(...)` must use the framework's static — make sure you're not instantiating a separate Smarty in your code.\n3. The variable was assigned with a different key than referenced (case-sensitive).\n\nFrom `framework-reference-v2.md §6.4` and §2.6.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"debug","citations":["framework-reference-v2.md §2.6","framework-reference-v2.md §6.4"]}}
|
|
{"instruction":"What does `[GENERATOR][folder-out]` look like in real INIs?","input":"","output":"```ini\nfolder-out = \"/../../application/model/\"\n```\nResolved as `__DIR__ . $value` in `core/c/table.php:217` where `__DIR__` is `core/c/`. The leading `/../../` walks up to project root. The folder-namespace fragment (PascalCased basename) is appended afterward. From `framework-reference-v2.md §3.2` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI [GENERATOR]","kind":"inikey","citations":["core/c/table.php:217","framework-reference-v2.md §7"]}}
|
|
{"instruction":"How do I attach an Observer to a module that implements `SplSubject`?","input":"","output":"Production `Users` module example uses PHP's built-in pattern (`framework-reference-v2.md §10.3`):\n```php\nclass Users extends Module implements Interfaces\\Users, SplSubject\n{\n protected SplObjectStorage $observers;\n\n public function __construct() {\n $this->observers = new SplObjectStorage();\n }\n\n public function attach(SplObserver $obs): void { $this->observers->attach($obs); }\n public function detach(SplObserver $obs): void { $this->observers->detach($obs); }\n public function notify(): void { foreach ($this->observers as $o) $o->update($this); }\n}\n```\nNot core — convention only. The framework neither requires nor wires this up automatically.","metadata":{"language":"en","source":"framework-reference-v2","section":"10.3 Observer Pattern","kind":"workflow","citations":["develop.maschinen-stockert.de/application/module/users/users.php:20-32","framework-reference-v2.md §10.3"]}}
|
|
{"instruction":"What's the canonical 'load nav, render page' controller skeleton?","input":"","output":"```php\nclass usersController extends Controller {\n public function navigationAction() {\n $nav = json_decode(file_get_contents(/* nav path */), true);\n View::assign(['nav' => $nav]);\n }\n\n public function pageAction() {\n // your data loading\n View::assign(['title' => 'Users']);\n // template assignments...\n }\n}\n```\nThe Dispatcher always calls `navigationAction()` before `pageAction()` (per `framework-reference-v2.md §6.3`). Smarty has access to both sets of variables when rendering.","metadata":{"language":"en","source":"framework-reference-v2","section":"6.3 Controller Lifecycle","kind":"workflow","citations":["framework-reference-v2.md §6.3"]}}
|
|
{"instruction":"Quick: how do I read `$_GET['page']` safely?","input":"","output":"```php\n$page = (int) $this->getGet('page');\n```\n`Controller::getGet($param)` returns the value from `$_GET` (or null/empty when absent). Cast to int for pagination. The framework helper doesn't auto-validate — caller is responsible. From `framework-reference-v2.md §2.5`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.5 Controller","kind":"workflow","citations":["core/c/controller.php:14","framework-reference-v2.md §2.5"]}}
|
|
{"instruction":"How does Nibiru's autogenerator handle a Postgres view (not a table)?","input":"","output":"The v2 reference doesn't document special view handling. `Table::_setTables()` runs `SHOW TABLES` (MySQL) or queries `information_schema` (Postgres). On Postgres, `information_schema.tables` includes views by default unless filtered — so a view will be picked up and a model generated for it. SELECT-only operations work; INSERT/UPDATE on a non-updatable view will fail at query time. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["core/c/table.php","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"What does `IDb::loadTableAsArray()` return?","input":"","output":"The entire table as a PHP array of rows. Each row is itself an associative array of column => value. From `core/i/IDb.php` and `framework-reference-v2.md §2.3`. Equivalent to `SELECT * FROM <table>` with no LIMIT.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"code-recall","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"How does the framework choose between `MySQL\\Db`, `Postgres\\Db`, and `Postgresql\\Db` adapters at runtime?","input":"","output":"Choice is baked into the GENERATED model file at autogen time, not runtime. The mask line `use Nibiru\\Adapter\\[ADAPTER]\\Db;` is substituted with `MySQL`, `Postgres`, or `Postgresql` based on `[GENERATOR][driver]` and `[GENERATOR][odbc]` (see `core/c/model.php:115-132`). After generation, the model `extends Db` forever. To change adapter you must regenerate. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"edge-case","citations":["core/c/model.php:115-132","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"Show me how INI section names map to constants on `IMysql`.","input":"","output":"From `core/i/IMysql.php`:\n- `SETTINGS_DATABASE = \"DATABASE\"` -> the default `[DATABASE]` block.\n- `PLACE_DATABASE = \"basename\"` -> the `basename` key inside that block.\n- `PLACE_USERNAME = \"username\"`, `PLACE_PASSWORD = \"password\"`, etc.\n\nThese constants are how the framework spells the literal INI keys when looking values up. Avoids string typos at the call site. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"code-recall","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"Why is there both `core/c/auto.php` and `core/c/autoloader.php`?","input":"","output":"`auto.php` hosts `Auto::loader()` — the modern, INI-driven autoloader actively used by `Dispatcher::run()`. `autoloader.php` is the deprecated legacy one kept for backward compatibility. New code should always use `Auto::loader()`. From `framework-reference-v2.md` Appendix file index.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"comparison","citations":["framework-reference-v2.md Appendix"]}}
|
|
{"instruction":"How do I customize the `<form>` action attribute?","input":"","output":"Pass `'action'` in the `addForm` attributes array:\n```php\nForm::addForm([\n 'method' => 'POST',\n 'action' => '/users/save',\n]);\n```\nThe Form Type's template `<form … action=\"ACTION\" …>` substitutes `ACTION` -> `/users/save`. From `framework-reference-v2.md §5.4` (Form wrapper row).","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"How does Smarty find templates relative to the project root?","input":"","output":"`View::_setEngine()` at `core/c/view.php:66-79` builds the template dir as `core/c/../../{ENGINE[templates]}`. With `[ENGINE][templates] = \"/../../application/view/templates/\"` (default-style), the absolute path becomes `application/view/templates/`. Templates inside are addressed relative to that root: `View::display('users/list.tpl')` -> `application/view/templates/users/list.tpl`. From `framework-reference-v2.md §2.6` and §7.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.6 View","kind":"workflow","citations":["core/c/view.php:66-79","framework-reference-v2.md §2.6"]}}
|
|
{"instruction":"Quick: what's the strict order in which Auto::loader does work?","input":"","output":"From `core/c/dispatcher.php:42-43` and `framework-reference-v2.md §4.3`:\n1. `loadModelFiles()` (line 42).\n2. `loadModules()` (line 43), which internally:\n a. iterates `iface.pos[]` and requires interfaces.\n b. iterates `trait.pos[]` and requires traits.\n c. iterates `class.pos[]` and requires + instantiates module mains.\n d. iterates `class.plugin.pos[]` and requires + instantiates plugins.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["core/c/dispatcher.php:42-43","framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"What's the gotcha with `addSelectDropdown` in production traits?","input":"","output":"Production `addSelectDropdown` (lines 183-225 of `nibiru-modules/application/module/users/traits/userForm.php`) uses a `foreach` to add `addSelectOption` calls, then a single `addSelect` to flush them. If the helper is called twice without `Form::create()` between, options from both calls accumulate (because `addSelect` clears the option buffer per call, but the form buffer stays put). The pattern works because each `addSelect` clears the option buffer for the next group. From `framework-reference-v2.md §5.6` and §5.9.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.9 Production Usage","kind":"gotcha","citations":["nibiru-modules/application/module/users/traits/userForm.php:183-225","framework-reference-v2.md §5.6"]}}
|
|
{"instruction":"What's the role of `core/c/debug.php`?","input":"","output":"It hosts the `Debug` class invoked at the end of `Dispatcher::run()` via `Debug::getInstance()`. Adds debug info (timing, query counts) to the response if enabled. Pairs with `[ENGINE][debugbar] = true` and `[ENGINE][debug_template]`. From `framework-reference-v2.md §6.4` and Appendix.","metadata":{"language":"en","source":"framework-reference-v2","section":"Appendix File Index","kind":"code-recall","citations":["core/c/debug.php","framework-reference-v2.md §6.4"]}}
|
|
{"instruction":"What does it look like when I'm writing my own INI from scratch for a tiny dev app?","input":"","output":"```ini\n[ENGINE]\ntemplates = \"/../../application/view/templates/\"\ntemplates_c = \"/../../application/view/templates_c/\"\ncache = \"/../../application/view/cache/\"\nconfig_dir = \"/../../application/view/configs/\"\ncaching = false\ndebugbar = true\nerror_controller = \"errorController\"\nerror_template = \"error.tpl\"\n\n[AUTOLOADER]\nclass.pos[] = \"users\"\n\n[GENERATOR]\ndatabase = true\ndatabase.overwrite = false\nconfig-section = \"DATABASE\"\nfolder-out = \"/../../application/model/\"\nmodeltemplate = \"/../../application/settings/db/db.class.mask\"\n\n[DATABASE]\nis.active = true\nusername = \"dev\"\npassword = \"devpass\"\nhostname = \"localhost\"\nbasename = \"my_app\"\ndriver = \"mysql\"\nport = \"3306\"\nencoding = \"utf8\"\n\n[SETTINGS]\ntimezone = \"Europe/Berlin\"\n\n[ROUTING]\nroute[index] = \"/\"\nroute[controller] = \"/controller\"\n```\nFrom `framework-reference-v2.md §7`.","metadata":{"language":"en","source":"framework-reference-v2","section":"7 INI Reference","kind":"workflow","citations":["framework-reference-v2.md §7"]}}
|
|
{"instruction":"What's special about the `class.plugin.pos[]` array vs the others?","input":"","output":"It's loaded LAST. The Auto::loader processes `iface.pos[]` first, then `trait.pos[]`, then `class.pos[]`, then `class.plugin.pos[]`. Plugins thus have access to all interfaces, traits, and module main classes already required. Within `class.plugin.pos[]` itself, the array order dictates load order — same gotcha as other categories. From `framework-reference-v2.md §4.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"4.3 Module Loading Flow","kind":"workflow","citations":["framework-reference-v2.md §4.3"]}}
|
|
{"instruction":"What's the most efficient way to load a single row by ID?","input":"","output":"```php\n$row = Db::loadModel('App\\Users')->selectRowsetById(42);\n```\nFrom `core/i/IDb.php`. Uses the model's TABLE constant to know the PK column. Returns the matching row or empty result. One round-trip. From `framework-reference-v2.md §2.3`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.3 Db Factory","kind":"workflow","citations":["core/i/IDb.php","framework-reference-v2.md §2.3"]}}
|
|
{"instruction":"Why does the substitution language use UPPERCASE tokens specifically?","input":"","output":"To avoid colliding with valid HTML attribute values (which are typically lowercase) and PHP variable names. The user passes lowercase keys (`'name'`); the substitution engine `strtoupper`s them at replace time (`core/c/formattributes.php:54`). The tokens in the templates are written in the all-caps form (`NAME`, `VALUE`, `PLACEHOLDER`). This separation keeps user-supplied values from accidentally matching template tokens. From `framework-reference-v2.md §5.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.2 Form Substitution","kind":"comparison","citations":["core/c/formattributes.php:48-58","framework-reference-v2.md §5.2"]}}
|
|
{"instruction":"How do I build a quick three-field form to capture a contact?","input":"","output":"```php\nForm::create();\nForm::addInputTypeText(['name' => 'name', 'placeholder' => 'Name']);\nForm::addInputTypeEmail(['name' => 'email', 'placeholder' => 'Email', 'required' => 'required']);\nForm::addInputTypeTextarea(['name' => 'message', 'rows' => '4']);\nForm::addInputTypeSubmit(['value' => 'Send']);\n$html = Form::addForm(['method' => 'POST', 'action' => '/contact/submit']);\necho $html;\n```\nFrom `framework-reference-v2.md §2.4` and §5.4.","metadata":{"language":"en","source":"framework-reference-v2","section":"5.4 Type Class Registry","kind":"workflow","citations":["framework-reference-v2.md §2.4","framework-reference-v2.md §5.4"]}}
|
|
{"instruction":"What does `Form::create()` reset?","input":"","output":"It clears `self::$form` (the field-buffer static). It does NOT clear `self::$option` (the option buffer for selects) or `self::$div` (the wrap state) — those are managed independently. From `core/f/form.php:41` and `framework-reference-v2.md §2.4`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.4 Form Factory","kind":"edge-case","citations":["core/f/form.php:41","framework-reference-v2.md §2.4"]}}
|
|
{"instruction":"What's the difference between `IMysql::PLACE_DRIVER` and `[DATABASE][driver]`?","input":"","output":"`IMysql::PLACE_DRIVER` is the constant `\"driver\"` — it's the string used to look up the INI key. `[DATABASE][driver]` is the actual INI key/value pair (e.g. `\"mysql\"`). Code reads it as `Config::getInstance()->getConfig()[IMysql::SETTINGS_DATABASE][IMysql::PLACE_DRIVER]` -> `\"mysql\"`. The constants are typo-proofing for the lookup keys. From `framework-reference-v2.md §9`.","metadata":{"language":"en","source":"framework-reference-v2","section":"9 Constants","kind":"comparison","citations":["core/i/IMysql.php","framework-reference-v2.md §9"]}}
|
|
{"instruction":"How do generated Postgres models call settingsSection?","input":"","output":"For `driver = \"psql\"` with `odbc = true`, the mask substitution produces:\n```php\npublic function __construct()\n{\n Postgres::settingsSection('DBSECTION');\n self::initTable( self::TABLE );\n}\n```\nWith `odbc = false`, it's `Postgresql::settingsSection(...)`. The Postgres-mode footgun is that the mask hardcodes `use Nibiru\\Pdo;` regardless of driver — so unless you patch the import, the unqualified call fails. From `framework-reference-v2.md §3.2`.","metadata":{"language":"en","source":"framework-reference-v2","section":"3.2 Autogenerator Pipeline","kind":"code-recall","citations":["application/settings/db/db.class.mask","framework-reference-v2.md §3.2"]}}
|
|
{"instruction":"How is `Config::getInstance()` typed?","input":"","output":"```php\npublic static function getInstance(): Settings\n```\nReturn type `Settings` is `\\Nibiru\\Settings` from `core/c/settings.php`. Defined at `core/c/config.php:12`. From `framework-reference-v2.md §2.1`.","metadata":{"language":"en","source":"framework-reference-v2","section":"2.1 Config Singleton","kind":"code-recall","citations":["core/c/config.php:12","framework-reference-v2.md §2.1"]}}
|