293 lines
7.8 KiB
Markdown
293 lines
7.8 KiB
Markdown
# 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/<module-id>/hook.php`.
|
|
|
|
### Testing Hooks
|
|
|
|
To test hooks, the site's Docker container must be running. Make a curl request to the Docker URL with the hook path. For example, if a hook is named `hooks.example_hook.php`:
|
|
|
|
```bash
|
|
curl http://{DOCKER_URL_AND_PORT}/hooks/example_hook/
|
|
```
|
|
|
|
Replace `{DOCKER_URL_AND_PORT}` with your local Docker address (e.g., `localhost:8080`) and parse hook name for url endpoint.
|
|
|
|
Do not use X-Hooks-Token because its not needed on developer environment.
|
|
|
|
### How to Call Hooks
|
|
|
|
**From Twig:**
|
|
```twig
|
|
{{ 'hooks/module_id/' | hook({param1: 'value1', param2: variable}) }}
|
|
```
|
|
|
|
**From HTML (with result):**
|
|
```html
|
|
<hook result="myVar" endpoint="/hooks/module_id/" :param1="value1" :param2="'string'"></hook>
|
|
<p>{{ myVar }}</p>
|
|
```
|
|
|
|
**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
|
|
<?php
|
|
// Called with: 'hooks/my_hook/' | hook({category: 'electronics', limit: 10})
|
|
// Available as:
|
|
$category; // 'electronics'
|
|
$limit; // 10
|
|
```
|
|
|
|
### Hook Return Values
|
|
|
|
Hooks can `echo` or `return` values. When called from Twig or `<hook>` 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 |
|