# Hooks & Server-Side API ## Hooks Hooks are PHP files in the `hooks/` directory that execute server-side logic. They can also live inside a module at `template/estandar/modulos//hook.php`. ### How to Call Hooks **From Twig:** ```twig {{ 'hooks/module_id/' | hook({param1: 'value1', param2: variable}) }} ``` **From HTML (with result):** ```html

{{ myVar }}

``` **From JavaScript:** ```js CmsApi.hook('/hooks/module_id/', { param1: 'value1' }, function(response) { console.log(response); }); ``` **From c-form:** Hooks are automatically triggered on form submission when configured. ### Hook Parameters Parameters are received as PHP variables: ```php ` tag, the output is captured into the result variable. ## CmsApi (PHP) Server-side API for database operations. Available in all hooks. ### Read Records ```php // Get all records $products = CmsApi::get('productos'); // With WHERE condition $active = CmsApi::get('productos', ['active' => 1]); // With order and limit $latest = CmsApi::get('noticias', [], 'fecha DESC', 5); // With operators $expensive = CmsApi::get('productos', ['precio' => ['>=' => 100]]); $search = CmsApi::get('productos', ['nombre' => ['LIKE' => '%keyword%']]); $inList = CmsApi::get('productos', ['categoria_num' => ['IN' => [1, 2, 3]]]); ``` ### Insert Records ```php $newRecord = CmsApi::insert('contacto', [ 'nombre' => 'John', 'email' => 'john@example.com', 'mensaje' => 'Hello', ]); ``` ### Update Records ```php CmsApi::update('productos', ['precio' => 29.99, 'activo' => 1], // fields to update ['num' => 42] // where condition ); ``` ### Delete Records ```php CmsApi::delete('productos', ['num' => 42]); ``` ### Important Rules - Table names **without** `cms_` prefix - Primary key is always `num`, never `id` - Upload fields are handled separately (not via insert/update) - Operators: `=`, `!=`, `>`, `>=`, `<`, `<=`, `LIKE`, `IN` ## CmsApi (JavaScript — Client-Side) ```js // Hook call CmsApi.hook('/hooks/module_id/', { param: 'value' }, function(response) { // response is the hook output }); // Record operations (if exposed via hooks) CmsApi.get('tableName', { where: conditions }, function(records) { // records array }); ``` ## CocoDB Low-level database abstraction layer used internally by CmsApi. Use directly from hooks when you need more control. ### `CocoDB::get($table, $where, $order, $limit, $options)` Reads records from a table. This is the same method CmsApi::get wraps. ```php // Basic query $records = CocoDB::get('productos', ['activo' => 1], 'orden ASC', 10); // With advanced where (array syntax for operators) $records = CocoDB::get('productos', [ ['column' => 'precio', 'value' => 100, 'operator' => '>='], ['column' => 'categoria_num', 'value' => [1, 2, 3], 'operator' => 'IN'], ]); // OR conditions $records = CocoDB::get('productos', [ ['column' => 'nombre', 'value' => '%keyword%', 'operator' => 'LIKE'], ['column' => 'descripcion', 'value' => '%keyword%', 'operator' => 'LIKE', 'or' => true], ]); // NOT condition $records = CocoDB::get('productos', [ ['column' => 'estado', 'value' => 'borrador', 'operator' => '=', 'not' => true], ]); // IS NULL $records = CocoDB::get('productos', [ ['column' => 'fecha_baja', 'value' => '', 'operator' => 'IS NULL'], ]); // Limit with offset $records = CocoDB::get('productos', [], 'num DESC', ['limit' => 10, 'offset' => 20]); ``` #### Options for `get()` | Option | Type | Default | Description | |--------|------|---------|-------------| | `uploads` | bool | `true` | Include upload field data | | `relations` | bool/array | `true` | Resolve foreign key relations. Pass array to limit: `['category']` | | `relationsDepth` | int | 2 | Depth of nested relation resolution | | `translates` | string | current lang | Language code for translations | | `groupBy` | string | null | GROUP BY clause | | `aggregates` | array | `[]` | Aggregate functions | | `onlyFields` | array | null | Select specific fields only | | `debug` | bool | false | Output SQL query for debugging | | `redis` | bool | null | Force Redis cache | | `redis_expire` | int | 60 | Redis cache TTL in seconds | ### `CocoDB::insertRecords($table, $records, $functions, $options)` Insert one or multiple records. ```php // Single record $count = CocoDB::insertRecords('contacto', [ 'nombre' => 'John', 'email' => 'john@example.com', ]); // Returns number of inserted records. Use mysql_insert_id() to get the new num. // Multiple records $count = CocoDB::insertRecords('productos', [ ['nombre' => 'Product A', 'precio' => 10], ['nombre' => 'Product B', 'precio' => 20], ]); ``` #### Options for insert/update | Option | Description | |--------|-------------| | `forceNum` | Allow setting the `num` field manually | | `ignoreSchema` | Skip schema validation | | `ignoreFields` | Array of field names to skip | ### `CocoDB::updateRecords($table, $records, $where, $functions, $options)` Update records matching a where condition. ```php CocoDB::updateRecords('productos', ['precio' => 29.99, 'activo' => 1], // fields to update ['num' => 42] // where condition ); // With operator in where CocoDB::updateRecords('productos', ['activo' => 0], [['column' => 'stock', 'value' => 0, 'operator' => '<=']] ); ``` ### `CocoDB::deleteRecords($table, $where, $options)` Delete records matching a where condition. ```php CocoDB::deleteRecords('productos', ['num' => 42]); // With operator CocoDB::deleteRecords('logs', [ ['column' => 'fecha', 'value' => '2024-01-01', 'operator' => '<'] ]); ``` ### Where Clause Syntax The `$where` parameter supports two formats: **Simple (key-value):** ```php ['campo' => 'valor'] // campo = 'valor' ``` **Advanced (array of conditions):** ```php [ 'column' => 'field_name', // Required 'value' => 'match_value', // Required 'operator' => '=', // =, !=, <, >, <=, >=, LIKE, IN, IS NULL 'or' => false, // Use OR instead of AND 'not' => false, // Negate the condition 'raw_key' => false, // Skip column existence check ] ``` ### Functions Parameter The `$functions` parameter lets you apply MySQL functions to values during insert/update: ```php CocoDB::insertRecords('logs', [ 'mensaje' => 'Login exitoso', 'fecha' => '', ], [ 'fecha' => 'NOW()', // Will use MySQL NOW() instead of the value ]); ``` ## Table Schemas Table schemas are stored as JSON in `cms/data/schema/`. Each file defines: - Field names and types - Validation rules - Relationships (foreign keys) - Display configuration ### Field Format Types | Type | PHP Format | Notes | |------|-----------|-------| | Text | String | Plain text | | Date/time | `YYYY-MM-DD HH:mm:ss` | MySQL datetime format | | Checkbox | `1` or `0` | Boolean as integer | | WYSIWYG | HTML string | Rich text with Tailwind classes | | List | String or num | Foreign key if linked to table | | Multivalores | JSON string | Serialized array | | Upload | — | Handled separately, never in insert/update |