A modular script is the primary building block of the Melbis platform. Each module solves a single isolated task: building a catalog menu, rendering a product card, processing a cart, or executing a background task. The entire site is assembled from these blocks.
All modules are displayed in the file tree under the “Scripts, Templates” section of the development environment. Modular scripts are grouped by company and group — this makes navigation convenient even in large projects with dozens of modules.
When a module is opened in the editor, its interface consists of three parts:
A typical module looks like this:
<?php
/**
* Function MELBIS_CATALOGE
**/
function MELBIS_CATALOGE($mVars)
{
// Create a template engine pointer
$tpl = MELBIS()->TplCreate();
// Retrieve data from the database
$command = "SELECT id, name
FROM {DBNICK}_topic
WHERE no_visible = 0
ORDER BY absindex";
$menu = MELBIS()->SqlSelect(__LINE__, $command);
// Pass data to the template engine
MELBIS()->TplAssign($tpl, 'MENU', $menu);
// Return the result
return MELBIS()->TplFinal($tpl, 'main');
}The main function is the only required part of a module. Its name
matches the filename in uppercase. The parser calls exactly this
function, passing the input parameters as the $mVars
array.
A module may contain any number of helper functions — they are named with the main function’s name as a prefix (see the “Naming Conventions” section).
Most modules follow the same pattern:
1. Create a template engine pointer:
$tpl = MELBIS()->TplCreate();2. Retrieve data from the database using
MELBIS()->Sql* methods:
// Return a flat array of a single record
$topic = MELBIS()->SqlSelectFlat(__LINE__, $command, $params);
// Return an array of records
$menu = MELBIS()->SqlSelect(__LINE__, $command, $params);
// Return an array indexed by key
$image = MELBIS()->SqlSelectEnumFlat(__LINE__, $command, 'id', $id, $params);3. Pass data to the template engine using
MELBIS()->Tpl* methods:
// Pass a single value
MELBIS()->TplAssign($tpl, 'TITLE', $topic['name']);
// Pass an entire array
MELBIS()->TplAssign($tpl, $topic);
// Parse a template and store the result in a variable
MELBIS()->TplParse($tpl, 'CONTENT', 'page_index');4. Return the result — the final parsing of the main template:
return MELBIS()->TplFinal($tpl, 'main');The complete list of Sql* and Tpl* methods
is described in the corresponding sections of the documentation.
Parameters are passed to a module through the $mVars
array. How the array is formed depends on how the module was called.
If the module is called as an entry point (via
MELBIS()->Run()), parameters are passed explicitly from
the root script:
// In index.php:
$entry_param = [serialize($_GET), serialize($_POST)];
MELBIS()->Run('melbis_base_page', $entry_param);The module declares get: serial, post: serial — and
inside the function:
$id = (int) ( $mVars['get']['topic_id'] ?? 0 );If the module is called from a template, parameters are passed directly in the call tag — positionally, separated by commas:
{MELBIS:melbis_store_image([ID],kDefault)}
{MELBIS:melbis_store_random(8)}
{MELBIS:melbis_cataloge_sub(,,[ID])}The module must have the corresponding parameters declared, for
example id: int, key: str, and inside the function:
$id = $mVars['id'];
$key = $mVars['key'];Parameter types are declared in the field above the editor in the IDE:
| Type | Description |
|---|---|
int |
Integer |
float |
Floating-point number |
bool |
Boolean value |
str |
String |
fix |
Fixed set of values; the first is the default. Example:
mode: fix=list\|grid |
serial |
Serialized PHP array (for passing
$_GET/$_POST) |
From a template — the primary and safe method. The
parser encounters a {MELBIS:module_name(...)} tag in an
HTML template, runs the module, and substitutes its HTML result in place
of the tag. Available for any module without restrictions.
As an entry point — a call via
MELBIS()->Run() in the root script. The URL can be
anything — the key criterion is the call through Run. To
allow such a call, the “Entry Point Module” option must
be enabled in the right panel of the IDE. Without this flag, the parser
will refuse to run the module directly. Entry points are typically page
router modules, form handlers, and cron tasks.
Each module generates an HTML fragment based on its own templates. This fragment may contain call tags for other modules — to any depth. The parser processes the entire chain automatically.
Let’s look at a real example from the demo store. The router module
melbis_base_page is launched as an entry point and
generates a complete page. Its main template main.htm calls
three nested modules:
<!doctype html>
<html>
{MELBIS:melbis_base_head()}
<body>
{MELBIS:melbis_base_header()}
<main>
{CONTENT}
</main>
{MELBIS:melbis_base_footer()}
</body>
</html>The melbis_base_header module, in its own template, in
turn calls the catalog module:
<nav>
{MELBIS:melbis_cataloge()}
</nav>And the melbis_cataloge template, when iterating over
menu items, calls yet another module for the submenu, passing it the
[ID] of the current loop element:
{#MENU}
<li class="nav-item dropdown">
{MELBIS:melbis_cataloge_sub(,,[ID])}
</li>
{MENU#}In parallel, the product page template calls the product list module, which calls the card for each product, and the card in its template calls two more modules — the image and the specifications:
<!-- Template melbis_store_card/main.htm -->
<div class="card">
<h4>{NAME|html}</h4>
{MELBIS:melbis_store_image([ID],kDefault)}
{MELBIS:melbis_store_features([ID])}
...
</div>Thus, a single store page can consist of a dozen nested modules — and each of them is developed, tested, and cached independently.
The right panel of the IDE displays all available library modules
(inc). To connect a library, simply check the checkbox —
the parser will automatically load it before running the current module,
making all its functions available.
The “Tables” tab displays two lists: - Left — the database tables directly accessed by the current module. The developer marks the required tables. - Right — tables from connected libraries (informational only, cannot be changed).
This data is used by the caching system: when data in a tracked table changes, the platform knows which modules’ caches need to be invalidated. See the “Caching” section for more details.