Skip to content
Docs

Developer guide

Building add-ons and widgets

Add-ons and widgets are lighter ways to extend the site than modules.

  • Add-ons: hook into the processing of every request to add behavior (counters, auto-linking, nickname badges, etc.)
  • Widgets: content pieces you can drop anywhere in a layout or page (login box, latest posts, etc.)

Building an add-on

addons/myaddon/
├── conf/info.xml       ← 이름·설명·설정 항목
└── myaddon.addon.php   ← 본체

myaddon.addon.php is called at several points during request processing. Use the $called_position variable to tell which point you're at.

<?php

if (!defined('__XE__'))
{
	exit();
}

// 화면 HTML이 완성되기 직전에 한 번 실행
if ($called_position === 'before_display_content'
	&& Context::getResponseMethod() === 'HTML'
	&& Context::get('module') !== 'admin'
	&& !isCrawler())
{
	// $output 변수에 완성된 HTML이 들어 있고, 수정하면 그대로 반영됩니다
	$output = str_replace('%FOO%', '바꿀 내용', $output);
}

Main call points:

$called_positionWhen
before_module_initBefore the module is prepared to run
before_module_procRight before the action runs
after_module_procRight after the action runs
before_display_contentRight before the final HTML is output ($output can be modified)

Things to watch out for:

  • Add-ons run on almost every request. Do heavy work (DB queries, etc.) only after narrowing the conditions as much as possible, and cache the results.
  • It's usually safest to skip the admin screen (Context::get('module') === 'admin') and non-HTML responses (JSON, etc.).
  • If you declare <extra_vars> in conf/info.xml, you can receive values in the admin add-on settings and read them in the main file with $addon_info->{var_name}.

Add-ons are turned on and off from the add-on list in the admin screen. You can set PC and mobile separately.

Building a widget

widgets/mywidget/
├── conf/info.xml           ← 이름·설명·설정 항목(extra_vars)
├── mywidget.class.php      ← 본체
└── skins/default/          ← 위젯 스킨
    ├── skin.xml
    └── widget.html

The main file extends WidgetHandler, and the file name and class name must match the widget name.

<?php

class mywidget extends WidgetHandler
{
	/**
	 * info.xml의 extra_vars 값이 $args로 들어옵니다.
	 * 결과 HTML을 출력하지 말고 반환해야 합니다.
	 */
	function proc($args)
	{
		$list = $this->getMyList((int)($args->count ?? 5));

		Context::set('list', $list);
		Context::set('colorset', $args->colorset);

		$tpl_path = sprintf('%sskins/%s', $this->widget_path, $args->skin);
		$oTemplate = TemplateHandler::getInstance();
		return $oTemplate->compile($tpl_path, 'widget');
	}
}
  • Settings declared with <extra_vars> in conf/info.xml become the fields entered on the widget insertion screen.
  • Skins work the same way as module skins. Compile the template in the skin folder selected by $args->skin and return it.
  • Return the result; don't echo it. Widgets are joined as strings while the page is assembled.

Where widgets are used

  • Inserted from the widget placement screen of layouts and pages
  • Directly in template v2: @widget('mywidget', $args)
  • The widget insertion feature in the editor body

Which one to build

What you wantTool
Automatic behavior on every page (display, replacement, logging)Add-on
A content box the admin drops wherever they wantWidget
A feature with its own data, screens, and settingsModule