Library Modules

Library modules are modular scripts belonging to the inc group. Unlike regular modules, the parser does not invoke them and they have no templates. Their purpose is to contain shared functions used by multiple regular modules simultaneously. This allows repetitive logic to be extracted into a single place rather than duplicated across individual modules.

To connect a library to a regular module, simply check the box next to it in the IDE’s right panel — the parser will load it automatically before running the module, making all its functions available.

Let’s look at three representative examples from the demo store.

melbis_inc_temp — Temporary Tables

This module contains a single function — MELBIS_INC_TEMP_topic_sub. Its purpose: to build an in-memory temporary table containing all subcategories of a given category, recursively traversing the category tree.

function MELBIS_INC_TEMP_topic_sub($mId)
{
    $command = "CREATE TEMPORARY TABLE {DBNICK}_topic_sub ENGINE=MEMORY
                WITH RECURSIVE topic_sub AS (
                    SELECT t.tindex, t.id
                      FROM {DBNICK}_topic t
                     WHERE t.id = :ID
                     UNION ALL
                    SELECT ts.tindex, t.id
                      FROM topic_sub ts
                      JOIN {DBNICK}_topic t ON ts.id = t.tindex
                )
                SELECT * FROM topic_sub";

    MELBIS()->SqlQuery(__LINE__, $command, ['id' => $mId]);
}

Why is this needed? When a module displays a list of products in a category, it must account not only for products in that category itself, but also for products in all its subcategories. The same table will be needed by the attribute filter module. Instead of writing a recursive CTE in each of these modules, it is sufficient to call MELBIS_INC_TEMP_topic_sub from the library once — and the temporary table is ready for use in subsequent queries:

// In the melbis_store_topic module:
function MELBIS_STORE_TOPIC($mVars)
{
    $id = $mVars['id'];

    // Create a temporary table of subcategories
    MELBIS_INC_TEMP_topic_sub($id);

    // Now we can JOIN with {DBNICK}_topic_sub
    $goods = MELBIS()->SqlSelect(__LINE__,
        "SELECT s.id
           FROM {DBNICK}_topic_sub t_sub
           JOIN {DBNICK}_topic_store ts ON ts.topic_id = t_sub.id
           JOIN {DBNICK}_store s ON ts.store_id = s.id
          WHERE s.no_visible = 0
       ORDER BY t_sub.absindex, ts.pos"
    );
    ...
}

melbis_inc_callback — Template Engine Callbacks

This module registers global template engine modifiers via MELBIS()->DefineCallback. A callback is a PHP function that can be called directly from an HTML template as a variable modifier.

// Registering a callback when the library is loaded:
MELBIS()->DefineCallback('page_link', 'MELBIS_INC_CALLBACK_page_link');

function MELBIS_INC_CALLBACK_page_link($mVars)
{
    return ( $mVars['kind_key'] == 'kLink' )
        ? $mVars['link']
        : '/?topic_id=' . $mVars['id'];
}

Once this library is connected, the $page_link modifier becomes available in any template, computing the correct URL for a category based on its type:

{#MENU}
    <a href="{ID|$page_link:KIND_KEY,LINK}">{NAME|html}</a>
{MENU#}

For more details on modifiers and callback syntax, see the “Templates and Keys” section.

melbis_inc_logic — Unified Business Logic

This is the most significant type of library module. melbis_inc_logic contains all functions for working with orders: creation, loading, editing, calculation, adding and removing products, discount calculation, and notifications:

MELBIS_INC_LOGIC_order_create        — create a new order version
MELBIS_INC_LOGIC_order_load          — load the current version
MELBIS_INC_LOGIC_order_edit          — open an order for editing
MELBIS_INC_LOGIC_order_calc          — calculate totals
MELBIS_INC_LOGIC_order_goods_add     — add a product to the order
MELBIS_INC_LOGIC_order_goods_remove  — remove a product from the order
MELBIS_INC_LOGIC_order_goods_discount — calculate discounts
MELBIS_INC_LOGIC_notify_events       — check system events

These functions are called from the shopping cart module on the storefront:

// In the melbis_basket module:
$version = MELBIS()->SessionGetValue('order') ?? MELBIS_INC_LOGIC_order_create();
$version = MELBIS_INC_LOGIC_order_goods_add($version, $store_id);
$version = MELBIS_INC_LOGIC_order_calc(null, $version);

The key advantage of this approach is unified business logic for both the website and the desktop application. The very same functions from melbis_inc_logic are called by the Melbis Shop application when a manager works with orders through the Windows client. The configuration of callable functions is done in the application via the “Design → Settings Registry” menu, the “Basic Settings” tab, under the “Callable Modules” section. For example, in the “Orders → Calculation” section, the library name and the function name that the application should call to calculate an order are specified.

This way, a customer placing an order through the website and a manager editing it in the application both work through the same PHP code — with no risk of logic divergence or synchronization errors.

Other Library Examples

In addition to those listed above, other libraries are also common in projects built on the Melbis platform:

Any logic that is needed in more than one module should be extracted into a library.