用户文档 开发者文档 | |

Data Providers

The data provider system is how widgets retrieve dynamic data without writing PHP. You declare what data you need in widget_info.json; WidgetDataService fulfils the request at render time.

How It Works

When WidgetService::renderArea($slug) processes a widget instance:

  1. It reads the output.providers map from the widget manifest
  2. It calls WidgetDataService::resolve($providers, $options) with the provider declarations and the current instance's option values
  3. WidgetDataService iterates the providers, instantiates the declared model, maps parameters, and calls the method
  4. The returned data is merged into the template variable bag under the declared key name

Provider Declaration Format

"providers": {
    "variable_name": {
        "provider": "ModelName.methodName",
        "params": {
            "method_param_name": "option_key"
        }
    }
}
  • variable_name — the key available in the template (e.g. posts, categories, author)
  • providerModelName.methodName where ModelName is the CI4 model class (without namespace), and methodName is the public method to call
  • params — maps method parameter names to option keys; the resolved option value is passed as the argument

Parameter Mapping

The params object maps method parameter names (left side) to option keys (right side). At resolve time, the option value for the right-hand key is fetched and passed as the named argument.

"params": {"limit": "count"}

This calls PostModel::getRecent(limit: $options['count']) — so if the widget instance has count = "5", the call becomes getRecent(limit: 5).

Type coercion: WidgetDataService casts numeric strings to integers before passing to the model method.

Context Variables

Parameter values beginning with @ are context variables, not option keys. They are injected by the render pipeline based on the current page. See the Context Variables article for the full list.

"params": {"post_id": "@current_post_id"}

Whitelist

Not every Model.method pair is available. WidgetDataService maintains a whitelist of approved combinations. Attempting to declare a non-whitelisted provider causes the widget to render an empty string with an error logged to activity_logs.

Approved combinations (non-exhaustive):

Provider stringMethod signature
PostModel.getRecentgetRecent(int $limit): array
PostModel.getByCategorygetByCategory(int $category_id, int $limit = 5): array
CategoryModel.getAllgetAll(): array
TagModel.getPopulargetPopular(int $limit = 10): array
AuthorProfileModel.getByUserIdgetByUserId(int $user_id): ?object

Contact the Pubvana team to request new provider whitelist additions.

Multiple Providers

A widget can declare multiple providers. Each resolves independently and injects its own variable:

"providers": {
    "posts": {
        "provider": "PostModel.getRecent",
        "params": {"limit": "count"}
    },
    "categories": {
        "provider": "CategoryModel.getAll"
    }
}

Template:

{% for post in posts %}
    {{ post.title }}
{% endfor %}

{% for cat in categories %}
    {{ cat.name }}
{% endfor %}

Provider Failure Behaviour

If a provider throws an exception or returns null, WidgetDataService catches the exception, logs it to activity_logs, and sets the variable to an empty array. The widget continues rendering — it will hit the {% empty %} branch or the outer {% if %} guard.