Skip to main content

🎨 Template Development Guide

emlog allows for easy template changing. Template files are located in the content\templates directory. Each template is a separate folder, named after the template's English alias. Templates installed via the app store or uploaded from the backend are all saved in this directory.

Template File and Directory Description​

File NameDescription
cssStores all CSS style files required by the template
jsStores all JS files required by the template
imagesStores image resources like LOGO required by the template
preview.jpgTemplate preview image displayed in the backend template selection interface. Recommended: 500x300 jpg format
header.phpSite header information, generally including page head information, top title, and navigation bar
echo_log.phpArticle detail page, displaying the content of a single article
log_list.phpHomepage, displaying the article list
footer.phpSite footer information, displaying copyright information, etc.
page.phpPage, displaying custom pages
side.phpSidebar. This file is not required if making a single-column template
module.phpFunctional modules: latest articles, comments, categories, tags, etc.
404.phpCustom error page when the 404 page is not found
pw.phpCustom encrypted article password input page. If this file is missing, the system default style is used [Not Required]
user.phpTemplate loaded by route /user, can be used for user center pages, etc. [Not Required]
plugins.phpTemplate system call file. Once the template is enabled, this file will be automatically loaded by the system. Can be used to implement plugin-like functions. [Not Required]
options.phpTemplate settings configuration file, can build richer setting items. [Not Required]
callback.phpTemplate event callback function definition. See the event callback section documentation for details [Not Required]
custom_fields.phpPreset article custom fields required by the template itself [Not Required]

Template Engine​

emlog does not use any other third-party template engines. It directly uses native PHP syntax markers to embed HTML to generate dynamic pages. This not only reduces the learning burden for developers but also greatly improves page loading and rendering efficiency.

// Embed variable
<div><?= $value ?></div>

// Loop
<?php foreach ($abc as $v) :?>
<div><?= $v ?></div>
<?php endforeach;?>

// Condition
<?php if($a == 'abc') :?>
<div>hello</div>
<?php endif;?>

Common Code​

Prevent Direct Access​

The following line of code exists at the beginning of every PHP file in the template directory. Its purpose is to prevent the PHP script where the code is located from being directly accessed and executed. It must be retained.

if(!defined('EMLOG_ROOT')) {exit('error!');}

Or

defined('EMLOG_ROOT') || exit('access denied!');

Reference Template File​

The following two lines of code are used to call the code of side.php and footer.php in the template folder to the current position of the current file.

require_once View::getView('side');
require_once View::getView('footer');

// View is the template view controller. View::getView('file name', 'file suffix') will return the corresponding file under the current template installation path.
// The second parameter of the getView function is a default parameter. If no value is passed, it will return the file path with .php file suffix by default.

File Description​

header.php​

Site header information, generally including page head information, top title, and navigation bar.

Header Information​

The comment content at the beginning is necessary information for the template, which will be displayed in the backend template management interface. Please make sure to fill it in completely.

/*
Template Name: Default Template
Version: 1.0
Template Url: https://emlog.dev/template/detail/xxx
Description: The default template of emlog
Author: emlog
Author Url: https://emlog.dev/profiles/xxxx
*/
tip

For Template URL and Author URL, please use the application link and author page from the official website emlog.net. Other non-official links will not be displayed as hyperlinks in the backend.

Load Template File​

require_once View::getView('module'); // Load template common module.

Variables & Constants​

Variable & ConstantTypeDescription
$site_titleVariableSite title (affected by backend SEO optimization settings)
$site_keyVariableSite keywords
$site_descriptionVariableOutput site browser description (affected by backend SEO optimization settings)
$blognameVariableSite title
$bloginfoVariableSite subtitle
BLOG_URLConstantURL of the site homepage, output format like https://emlog.net/
TEMPLATE_URLConstantURL of the template folder, used to load CSS, JS, and other content inside the template, output format like http://emlog.net/blog/content/templates/default/

The above variables and constants can be output in the template in the following way:

<?= $page_url ?>
<?= BLOG_URL ?>

footer.php​

Site footer information, displaying copyright, ICP filing, and other information.

Variables & Constants​

Variable, ConstantTypeDescription
$icpVariableICP filing number set in the backend
$footer_infoVariablePage footer information set in the backend
Option::EMLOG_VERSIONConstantCurrent emlog version number

log_list.php​

Homepage template, displaying the article list.

Variables & Methods​

Variable, Constant, MethodTypeDescription
$value['log_cover']VariableArticle cover image URL
$value['logid']VariableID of the current article
$value['log_url']VariableArticle address URL
$value['log_title']VariableArticle title
date('Y-n-j', $value['date'])VariableArticle publication time, parameter 'Y-n-j G:i l' is used to define the date format
$value['log_description']VariableArticle excerpt (outputs full text if there is no excerpt)
$value['comnum']VariableNumber of comments for the current article
$value['views']VariableNumber of views for the current article
$value['fields']VariableCustom fields, array type, see example below for reading method
editflg($value['logid'],$value['author'])VariableDisplays "Edit" link when administrator or author is logged in
topflg($value['top'])VariableDisplays sticky mark, this function is located in template module.php
$page_urlVariableDisplays pagination function for the current list page
blog_sort($value['logid'])MethodDisplays the category the article belongs to
blog_author($value['author'])MethodDisplays the author of the article
blog_tag($value['logid'])MethodDisplays the tags of the article

The above variables and methods can be output in the template in the following way:

<?= $value['logid'] ?>
<?= blog_author($value['author']) ?>

// Read custom fields, where index abcd is the custom field name
if (isset($value['fields']['abcd'])) {
echo $value['fields']['abcd']; // Output the value of the custom field named abcd
}

echo_log.php​

Article detail page template, displaying the content of a single article.

Variables & Methods​

Variable, Constant, MethodTypeDescription
$logidVariableID of the current article
$log_titleVariableArticle title
$log_coverVariableCover image URL
date('Y-n-j', $date)VariablePublication time, parameter 'Y-n-j G:i l' is used to define the date format
$log_contentVariableArticle content
$excerptVariableArticle excerpt
$comnumVariableNumber of comments for the current article
$viewsVariableNumber of views for the current article
$fieldsVariableCustom fields, array type, see example below for reading method
$page_urlVariableDisplays pagination function for the current list page
topflg($top)MethodDisplays sticky mark
blog_tag($logid)MethodTags
blog_author($author)MethodAuthor
blog_sort($logid)MethodCategory it belongs to
editflg($logid,$author)MethodDisplays "Edit" link when administrator or author is logged in.
neighbor_log($neighborLog)MethodNeighboring articles, i.e., previous post, next post.
blog_comments($comments)MethodComment list
blog_comments_post($logid,$ckname,$ckmail,$ckurl,$verifyCode,$allow_remark)MethodPost comment box
// Output title in template
<?= $log_title ?>

// Read custom fields, where index abcd is the custom field name
if (isset($fields['abcd'])) {
echo $fields['abcd']; // Output the value of the custom field named abcd
}

page.php​

Page, displaying custom pages. Variable definitions etc. are the same as echo_log.php.

side.php​

Sidebar, mainly responsible for outputting sidebar content based on backend widgets settings. It is recommended to keep the code in this file unchanged.

module.php​

Template common code, including sidebar widgets, comments, quotes, editing, etc.

This file is composed of several functions, called by template files. Custom functions can be defined within it to implement more functions.

For example, when calling emlog cache in a custom function, assuming reading user cache information: global $CACHE; $user_cache = $CACHE->readCache('user');

If database operation is needed: $DB = MySql::getInstance(); $res = $DB->query($sql);

404.php​

Template used for custom 404 pages.

pw.php​

Used for custom encrypted article password input page. If this template file does not exist, the system default style will be used, without affecting the normal use of password input function. Please refer to the default template for template content.

user.php​

User center template, can be used for themes to build their own user center. The user center URL routing rules are as follows, where xxx is the custom route name, for example: /user/profile or /?uc=profile etc. If this template file does not exist, accessing it will prompt 404.

  • Route Rule 1 (Pseudo-static needs to be enabled): /user/xxx
  • Route Rule 2: /?uc=xxx

Example as follows:

<?php
/**
* Frontend User Center
*/
defined('EMLOG_ROOT') || exit('access denied!');


// Check if logged in
if (ISLOGIN) {
//do something
}

// Get current logged-in user info
$avatar = $userData['photo']
$name = $userData['nickname']
$bio = $userData['description']
$email = $userData['email']

// Get current route path
// Variable $routerPath stores the current request's route path, e.g., /user/profile, $routerPath value is profile
// Include header template file (can determine whether to include based on route)
if (in_array($routerPath, ['', 'order', 'account', 'profile', 'weiyu'])) {
include View::getView('header');
}

// Implement route corresponding function
if ($routerPath === 'profile') {
include View::getView('user_xxxx') // Can load other template files
} elseif ($routerPath === 'weiyu') {
// Show weiyu page
} elseif ($routerPath === 'order_calback') {
// Handle payment callback logic
} else {
show_404_page();
}

// Include footer template file
include View::getView('footer')

custom_fields.php​

Preset article custom fields required by the template itself. Adding custom fields in the backend article editing page supports drop-down selection of these preset fields. Configuration content reference as follows:

<?php
/**
* Template preset article custom fields
*/

defined('EMLOG_ROOT') || exit('access denied!');

$custom_fields = [
'price' => [
'type' => 'text',
'name' => 'Price',
'description' => 'e.g., 9.99',
'default' => ''
],
'need_vip' => [
'type' => 'radio',
'name' => 'Need VIP',
'values' => [
'0' => 'No',
'1' => 'Yes'
],
'description' => '1 for Yes, 0 for No',
'default' => '0'
],
];

plugins.php​

The template's system call file. Once the template is enabled, this file will be automatically loaded by the system. It can be used to implement plugin-like functions.

Sometimes templates also hope to customize some functions in the system, including mounting functions at plugin mounting points for functional expansion. This file gives the template this ability, so that the template does not need to install additional supporting plugins to achieve richer functions.

<?php
/**
* Template system call file
* Once the template is enabled, this file will be automatically loaded by the system. It can be used to implement plugin-like functions.
*/

if (!defined('EMLOG_ROOT')) {
exit('error!');
}

/* eg:

function sameFunc() {
echo "xxxx";
}

addAction('adm_head', 'sameFunc');

*/

options.php​

Template settings configuration file, see the Enable Template Settings section below.

Custom Templates​

Articles, categories, pages: support custom templates. Users can select custom templates supported by the template theme when creating categories, pages, and articles, thereby achieving richer page display.

Naming Rules for Custom Template Files​

  • Category: Filename starts with log_list_, e.g., log_list_abc.php
  • Article: Filename starts with echo_log_, e.g., echo_log_abc.php
  • Page: Filename starts with page_, e.g., page_abc.php

Comment Rules for Custom Template Files​

<?php
/*@name Custom Template Name*/

The content of this comment will appear as the custom template name in the drop-down selection box. Custom templates that meet the above specifications will appear in the drop-down selection box in the scenarios of adding categories and creating pages, facilitating user selection.

Template Mounting Points​

The following code format is the plugin mounting point in the template. Please refer to the default template and keep it, do not delete it.

<?php doAction('xxx') ?>
danger

Note: Be sure to refer to the default template to retain the following mounting points when developing templates to facilitate compatibility with other plugins.

Mounting PointBelonging FileMounting Point DescriptionExample
doAction('index_head')header.phpSite head tag mounting point, used to mount js or css style files
doAction('index_footer')footer.phpFooter bottom mounting point, used to mount footer information display plugins
doAction('index_loglist_top')log_list.phpHomepage article list top mounting point, recommended to add below the homepage navigation bar
doAction('log_related', $logData)echo_log.phpRelated article mounting point, added between article content and comments

Event Callbacks​

In the Appearance - Template Management page of the emlog backend, users can enable, delete, and update templates. These operations will trigger corresponding callback functions. Developers can add a callback.php file to the template and define callback functions for specific events to implement operations such as template initialization, data cleanup, and data structure updates.

EventTrigger Function
Enable Templatecallback_init()
Delete Templatecallback_rm()
Update Templatecallback_up()

Example: (Please refer to callback.php in the default theme directory)

Template Settings​

Templates support custom settings functions to provide richer configuration features for templates.

Place an options.php file in the template directory. The content format is as follows. You can add setting items arbitrarily. The starting comment cannot be deleted or changed. Reference as follows:

<?php
/*@support tpl_options*/

!defined('EMLOG_ROOT') && exit('access denied!');

$options = [
/** This item must exist */
'TplOptionsNavi' => [
'type' => 'radio',
'name' => 'Define Setting Tab Name',
'values' => [
'tpl-head' => 'Header Settings',
],
'icons' => array(
'tpl-head' => 'ri-home-line',
),
'description' => '<p>Template: Morning <br>Welcome to use this simple template, currently only supports setting header logo</p>'
],
'sale_qq' => [
'labels' => 'tpl-head',
'type' => 'text',
'name' => 'QQ Consultation',
'multi' => 'true',
'values' => ['12345678'],
],
'logotype' => [
'labels' => 'tpl-head',
'type' => 'radio',
'name' => 'LOGO Display Mode',
'values' => [
'1' => 'Text',
'0' => 'Image',
],
'default' => '1',
],
'appearance-color' => [
'labels' => 'tpl-appearance',
'type' => 'color',
'name' => 'Website Main Color',
'description' => '',
'values' => array('#006fff'),
],
'logoimg' => [
'labels' => 'tpl-head',
'type' => 'image',
'name' => 'LOGO Upload',
'values' => [
TEMPLATE_URL . 'images/logo.png',
],
'description' => 'Upload LOGO image.'
],
'index_sort_list' => [
'labels' => 'modules',
'type' => 'sort',
'name' => 'Category Multi-select',
'multi' => 'true',
'description' => ''
],
'index_page_list' => [
'labels' => 'modules',
'type' => 'page',
'name' => 'Page Multi-select',
'multi' => 'true',
'description' => ''
],
'styles-lazyopts' => [
'labels' => 'styles',
'type' => 'checkbox',
'name' => 'Image Asynchronous Lazy Load',
'values' => [
'view' => 'Views',
'comnum' => 'Comments',
'agree' => 'Likes',
],
'default' => array('view', 'comnum'),
'description' => '',
],
'index_tag' => [
'labels' => 'tpl-head',
'type' => 'checkon',
'name' => 'Show Tag List on Homepage',
'values' => ['1' => 'Enable'],
'default' => '1',
'description' => ''
],
'index_post_list' => [
'labels' => 'tpl-head',
'type' => 'select',
'name' => 'Search Articles',
'new' => 'NEW',
'pattern' => 'post',
'description' => ''
],
'index_cate_list' => [
'labels' => 'tpl-head',
'type' => 'select',
'name' => 'Search Categories',
'new' => 'NEW',
'pattern' => 'cate',
'description' => ''
],
'index_page_list' => [
'labels' => 'tpl-head',
'type' => 'select',
'name' => 'Search Pages',
'new' => 'NEW',
'pattern' => 'page',
'description' => ''
],
'index_block_list' => [
'labels' => 'tpl-head',
'type' => 'block',
'name' => 'Drag Multi-content Block',
'new' => 'NEW',
'description' => ''
],
'index-image_list' => [
'labels' => 'tpl-head',
'type' => 'block',
'name' => 'Drag Multi-image Content Block',
'new' => 'NEW',
'pattern' => 'image',
'description' => ''
],
'index-num_text' => [
'labels' => 'tpl-head',
'type' => 'text',
'name' => 'Number Text Box',
'new' => 'NEW',
'pattern' => 'num',
'unit' => 'Seconds',
'max' => '10',
'min' => '1',
'description' => ''
],
'index-date_text' => [
'labels' => 'tpl-head',
'type' => 'text',
'name' => 'Date Text Box',
'new' => 'NEW',
'date' => 'true',
'description' => ''
],
];

What to write in each element in options.php?​

As shown above, in the $options array, the key is the id of the setting item, and the value is an array containing several elements. Among them, type and name attributes are required. name is the name of the setting item, and type is used to specify the type of the setting item.

Supported types for setting items:​

  • radio: Radio button
  • checkbox: Checkbox
  • checkon: Switch
  • text: Single-line/multi-line text
  • image: Image upload and media library selector
  • color: Color picker
  • sort: Category selector
  • page: Page selector
  • tag: Tag selector
  • select: Search selection (posts/categories/pages)
  • block: Multi-content block (supports text/image sortable items)
  • number: Dedicated number input
  • slider: Slider control
  • date: Date picker
  • link: Link component
  • link_color: Link state colors
  • spacing: Spacing component
  • border: Border component
  • background: Background component
  • notice: Alert notice card
  • submessage: Compact submessage with left colored border

Setting Item Description​

  • For all types, the default attribute is used to specify the default value. When default is not specified, the first value in values is used. If none are specified, a default value will be used.
  • For radio and checkbox types, the values attribute is used to set the value and display name of each button.
  • Except for sort, depend can be specified as sort, indicating that this option can set different values according to different categories. When depend is specified as sort, the unsorted attribute is optional. When true, it means including uncategorized; when false, it does not include. The default is true.
  • Except for tag, depend can be specified as tag, indicating that this option can set different values according to different tags, such as adding icons to tags.
  • For sort and page, the multi attribute can be set to true, indicating multi-selection.
  • The description attribute is used to describe the option (optional).
  • If type is text, the multi attribute can be set to true, indicating multi-line text.
  • Optional attribute rich is used to support rich text. If this value is set, the editor will be loaded (deprecated, not supported in pro series versions).
  • If you want to use a number text box, type is still text, and you can set the pattern attribute to num. You can specify max, min, unit, i.e., limit the maximum value, minimum value, and unit of quantity. You can set the minimum or maximum value separately. For example, if only the minimum value is set, the maximum value will not restrict input. The unit of measurement will be displayed on the far right of the text box.
  • If using a date text box, type is still text, just set the date attribute to true.
  • If type is sort, page, or tag, and multi-selection is set, the default value will be empty, otherwise it will be the first value of that type.
  • For type select, the pattern attribute is required. You can fill in: (1). post (2). cate (3). page. Corresponding to articles, categories, and pages respectively. This functional module may query slowly when the data is very large. The array content obtained using built-in functions is the ID of the setting type, for example, getting a group of article gids.
  • (Optional) All the above types support the new attribute, which will display a reminder badge after the setting item name, the effect can be seen in the default template. This attribute value can be filled in arbitrarily, such as: NEW, etc. If empty or not filled, it will not be displayed.
  • For type block, the pattern attribute is optional. If the pattern attribute is not set, the default content is text. The multi attribute can be set to true, indicating multi-line text. Setting the pattern attribute to image allows using multi-image content blocks.

Detailed Guide & Examples for Setting Types​

Radio Button (radio)​

A mutually exclusive single-selection radio button group.

  • Attributes:
    • name: Option title.
    • values: Associative array where key is stored value, value is display label.
    • default: Default selected value (defaults to first key in values).
    • description: Option description (optional).
    • labels: Tab group name.
'post_layout' => [
'labels' => 'tpl-head',
'type' => 'radio',
'name' => 'Post List Layout',
'values' => [
'card' => 'Grid Cards',
'list' => 'Single Column List',
'text' => 'Minimal Text',
],
'default' => 'card',
'description' => 'Select display layout for home and archive pages',
],
  • Template Usage:
<?php
$layout = _g('post_layout'); // returns string, e.g. "card"
if ($layout === 'card') {
// render card layout
}
?>

Checkbox (checkbox)​

Multi-selection checkboxes allowing users to select multiple options. Saves and returns an array.

  • Attributes:
    • name: Option title.
    • values: Associative array of option keys and labels.
    • default: Array of default selected keys (e.g. ['author', 'date']).
    • description: Option description (optional).
    • labels: Tab group name.
'meta_elements' => [
'labels' => 'tpl-head',
'type' => 'checkbox',
'name' => 'Post Card Metadata',
'values' => [
'author' => 'Author',
'date' => 'Date',
'views' => 'Views',
'comnum' => 'Comments',
],
'default' => ['author', 'date', 'views'],
'description' => 'Select metadata elements to display on post cards',
],
  • Template Usage:
<?php
$meta = _g('meta_elements') ?: []; // returns array, e.g. ['author', 'date', 'views']
if (in_array('views', $meta)) {
echo '<span>Views: ' . $value['views'] . '</span>';
}
?>

Switch (checkon)​

A modern toggle switch button for binary on/off options. Value is '1' when checked, empty or '0' when unchecked.

  • Attributes:
    • name: Option title.
    • values: Enabled value, usually ['1' => 'On'].
    • default: '1' for on, '0' for off.
    • description: Option description (optional).
    • labels: Tab group name.
'enable_dark_mode' => [
'labels' => 'tpl-appearance',
'type' => 'checkon',
'name' => 'Enable Dark Mode Toggle',
'values' => ['1' => 'On'],
'default' => '1',
'description' => 'Display a dark/light theme toggle in header navigation',
],
  • Template Usage:
<?php
$dark_mode = _g('enable_dark_mode'); // returns "1" when enabled, empty or "0" when disabled
if ($dark_mode == '1') {
// render theme toggle
}
?>

Text Input (text)​

Single-line text input or multi-line textarea. Set multi => true to render as a multi-line textarea.

  • Attributes:
    • name: Option title.
    • multi: Multi-line textarea (boolean or 'true', default single-line).
    • default: Default text.
    • description: Option description (optional).
    • labels: Tab group name.
// Single-line text
'contact_email' => [
'labels' => 'tpl-head',
'type' => 'text',
'name' => 'Contact Email',
'default' => 'admin@example.com',
'description' => 'Displayed in the site footer',
],

// Multi-line textarea
'footer_custom_code' => [
'labels' => 'tpl-head',
'type' => 'text',
'multi' => true,
'name' => 'Footer Custom Script / Code',
'default' => '',
'description' => 'Custom analytics script or custom JavaScript',
],
  • Template Usage:
// Output single-line text
<a href="mailto:<?= _g('contact_email') ?>"><?= _g('contact_email') ?></a>

// Output multi-line custom code
<?= _g('footer_custom_code') ?>

Color Picker (color)​

Native HTML5 color picker allowing users to click to pick colors or enter hex values.

  • Attributes:
    • name: Option title.
    • default / values: Default color hex (e.g. '#006fff').
    • description: Option description (optional).
    • labels: Tab group name.
'primary_color' => [
'labels' => 'tpl-appearance',
'type' => 'color',
'name' => 'Theme Primary Color',
'default' => '#006fff',
'description' => 'Primary accent color for buttons and links',
],
  • Template Usage:
<?php $primary = _g('primary_color') ?: '#006fff'; ?>
<style>
:root {
--theme-primary: <?= $primary ?>;
}
</style>

Image Selector (image)​

Full-featured image selector supporting media library modal selection, local image upload, and external image URLs.

  • Attributes:
    • name: Option title.
    • default / values: Default image URL.
    • description: Option description (optional).
    • labels: Tab group name.
'site_logo' => [
'labels' => 'tpl-head',
'type' => 'image',
'name' => 'Site LOGO',
'default' => TEMPLATE_URL . 'images/logo.png',
'description' => 'Recommended size 200x50 transparent PNG or SVG',
],
  • Template Usage:
<?php $logo = _g('site_logo'); ?>
<img src="<?= $logo ?>" alt="<?= $blogname ?>">

Category Selector (sort)​

Automatically loads all site categories for users to choose. Supports single selection and multi-selection (multi => true).

  • Attributes:
    • name: Option title.
    • multi: Multi-selection (boolean or 'true').
    • default: Default selected category ID (array for multi, string for single).
    • description: Option description (optional).
    • labels: Tab group name.
// Single category
'featured_sort' => [
'labels' => 'tpl-head',
'type' => 'sort',
'name' => 'Featured Category',
'description' => 'Select a category to highlight on home page',
],

// Multi categories
'slider_exclude_sorts' => [
'labels' => 'tpl-head',
'type' => 'sort',
'multi' => true,
'name' => 'Excluded Categories for Slider',
'description' => 'Check categories to exclude from slider',
],
  • Template Usage:
// Single: returns category ID string, e.g. "2"
$featured_sid = _g('featured_sort');

// Multi: returns category ID array, e.g. ["1", "3"]
$exclude_sids = _g('slider_exclude_sorts') ?: [];

Page Selector (page)​

Automatically reads custom static pages for selection. Supports single and multi-selection (multi => true).

  • Attributes:
    • name: Option title.
    • multi: Multi-selection (boolean or 'true').
    • default: Default selected page ID.
    • description: Option description (optional).
    • labels: Tab group name.
'about_page' => [
'labels' => 'tpl-head',
'type' => 'page',
'name' => 'About Page Link',
'description' => 'Select custom page for About Us link target',
],
  • Template Usage:
<?php
$about_page_id = _g('about_page'); // returns page ID, e.g. "5"
?>

Tag Selector (tag)​

Automatically lists all site tags with post count badges for multi-selection via checkboxes.

  • Attributes:
    • name: Option title.
    • default: Default selected tag names array.
    • description: Option description (optional).
    • labels: Tab group name.
'hot_tags' => [
'labels' => 'tpl-head',
'type' => 'tag',
'name' => 'Recommended Tags',
'description' => 'Pick popular tags displayed under search box',
],
  • Template Usage:
<?php
$tags = _g('hot_tags') ?: []; // returns tag name array, e.g. ["PHP", "Emlog", "Tutorial"]
foreach ($tags as $tag_name) {
echo '<a href="' . BLOG_URL . '?tag=' . urlencode($tag_name) . '">' . htmlspecialchars($tag_name) . '</a>';
}
?>

Search Selector (select)​

Live fuzzy search selector allowing precise searching and linking of posts (post), categories (cate), or pages (page).

  • Attributes:
    • name: Option title.
    • pattern: Required, choice of:
      • 'post': Search posts by title keyword.
      • 'cate': Search categories.
      • 'page': Search custom pages.
    • description: Option description (optional).
    • labels: Tab group name.
'home_top_post' => [
'labels' => 'tpl-head',
'type' => 'select',
'pattern' => 'post',
'name' => 'Home Featured Post',
'description' => 'Search and pick a featured post by title keyword',
],
  • Template Usage:
<?php
// Returns array of selected post IDs, e.g. ["12", "34"]
$top_post_ids = _g('home_top_post') ?: [];
if (!empty($top_post_ids)) {
// iterate over post IDs to load details
}
?>

Multi-Content Block (block)​

Sortable multi-item container allowing adding, dragging to reorder, and deleting items. Supports two patterns:

  1. Image Block (pattern => 'image'): Each item includes a title input and image selector.
  2. Text Block (default or pure text): Each item includes a title input and text content (or multi-line textarea with multi => true).
  • Attributes:
    • name: Option title.
    • pattern: Optional 'image' (for image block mode).
    • multi: Multi-line textarea for content (text block mode only).
    • placeholder: Associative array for custom placeholder text: ['title' => '...', 'content' => '...'].
    • description: Option description (optional).
    • labels: Tab group name.
// Image slider block
'home_slider' => [
'labels' => 'tpl-head',
'type' => 'block',
'pattern' => 'image',
'name' => 'Home Banner Slider',
'placeholder' => [
'title' => 'Slide Title or Link URL',
'content' => 'Image URL (select or upload)',
],
'description' => 'Add multiple slides with drag-and-drop sorting',
],

// FAQ text block
'home_faq' => [
'labels' => 'tpl-head',
'type' => 'block',
'multi' => true,
'name' => 'FAQ Items',
'placeholder' => [
'title' => 'Question',
'content' => 'Answer content',
],
],
  • Template Usage: Use the dedicated helper _getBlock($key, $type):
    • $key: Option name (e.g. 'home_slider').
    • $type: 'title' (returns titles array) or 'content' (returns content/image URL array, default).
<?php
$titles = _getBlock('home_slider', 'title'); // returns titles array
$images = _getBlock('home_slider', 'content'); // returns images array

if (!empty($images)) {
foreach ($images as $index => $img_url) {
$title = $titles[$index] ?? '';
echo '<div class="slide-item">';
echo '<img src="' . htmlspecialchars($img_url) . '" alt="' . htmlspecialchars($title) . '">';
echo '<h3>' . htmlspecialchars($title) . '</h3>';
echo '</div>';
}
}
?>

Notice Bar (notice)​

Used for displaying guidelines, setup instructions, or alert cards in the template settings interface. This type is display-only and does not persist data.

  • Attributes:
    • style: Alert style: info (blue, default), success (green), warning (yellow), danger (red), normal (gray).
    • name: Notice title (optional).
    • content: Notice body content (supports HTML).
    • description: Extra descriptive text (optional).
'demo_notice' => [
'labels' => 'tpl-head',
'type' => 'notice',
'style' => 'info',
'name' => 'Configuration Guide',
'content' => 'Welcome to this theme! Please follow each module guide below to configure your site style and options.',
],

Submessage (submessage)​

A compact, inline message with a left colored status stripe, ideal for placing above specific options as quick tips. This type is display-only and does not persist data.

  • Attributes:
    • style: Message style: normal (gray, default), info, success, warning, danger.
    • content: Message text (falls back to name if omitted).
'demo_submessage' => [
'labels' => 'tpl-head',
'type' => 'submessage',
'style' => 'success',
'content' => 'Tip: Enabling image lazy loading can significantly reduce initial page load times.',
],

Number Input (number)​

Dedicated number input control with min/max validation, step controls, and an optional unit badge on the right.

  • Attributes:
    • min: Minimum allowed number.
    • max: Maximum allowed number.
    • step: Step value (e.g. 1 or 0.1, defaults to any).
    • unit: Unit badge text (e.g. px, posts, sec, %).
    • placeholder: Input placeholder text.
    • default: Default value.
'page_posts_num' => [
'labels' => 'tpl-head',
'type' => 'number',
'name' => 'Posts Per Page',
'description' => 'Number of articles to display per page on lists (1-100)',
'min' => 1,
'max' => 100,
'step' => 1,
'unit' => 'posts',
'default' => '10',
],
  • Template Usage:
<?php
$posts_per_page = _g('page_posts_num'); // e.g. "10"
?>

Slider (slider)​

An interactive range slider synchronized with a numeric input field in real time. Ideal for adjusting border-radius, opacity, dimensions, etc.

  • Attributes:
    • min: Minimum value (default 0).
    • max: Maximum value (default 100).
    • step: Step value (default 1).
    • unit: Unit suffix (e.g. px, %).
    • default: Default value.
'card_radius' => [
'labels' => 'tpl-appearance',
'type' => 'slider',
'name' => 'Card Border Radius',
'description' => 'Drag the slider or enter a number to adjust card corner roundness',
'min' => 0,
'max' => 50,
'step' => 1,
'unit' => 'px',
'default' => '8',
],
  • Template Usage:
<?php
$card_radius = _g('card_radius'); // e.g. "8"
?>
<style>
.card {
border-radius: <?= $card_radius ?>px;
}
</style>

Date Picker (date)​

Embedded calendar control supporting both single date selection and date range (from_to) selection.

  • Attributes:
    • from_to: Boolean (true enables start/end date range, false for single date, default false).
    • text_from: Label for the start date input (default 'From').
    • text_to: Label for the end date input (default 'To').
    • default: String for single date (e.g. '2026-12-31'), associative array for date range (e.g. ['from' => '2026-10-01', 'to' => '2026-10-31']).
// Single date
'event_deadline' => [
'labels' => 'tpl-head',
'type' => 'date',
'name' => 'Event Deadline',
'description' => 'Select the deadline date for the event',
'default' => '2026-12-31',
],

// Date range
'campaign_period' => [
'labels' => 'tpl-head',
'type' => 'date',
'name' => 'Campaign Period',
'description' => 'Select start and end dates',
'from_to' => true,
'text_from' => 'Start',
'text_to' => 'End',
'default' => [
'from' => '2026-10-01',
'to' => '2026-10-31',
],
],
  • Template Usage:
<?php
// Single date
$deadline = _g('event_deadline'); // "2026-12-31"

// Date range
$period = _g('campaign_period');
$start_date = $period['from'] ?? '';
$end_date = $period['to'] ?? '';
?>

Aggregates link label, target URL, and "Open in new tab (target="_blank")" option into a single unified control.

  • Attributes:
    • default: Associative array with text, url, and target ('_blank' or '_self').
'banner_link' => [
'labels' => 'tpl-head',
'type' => 'link',
'name' => 'Banner Link',
'description' => 'Configure promotional banner title, link URL, and open mode',
'default' => [
'text' => 'Emlog Official',
'url' => 'https://www.emlog.net',
'target' => '_blank',
],
],
  • Template Usage:
<?php $link = _g('banner_link'); ?>
<?php if (!empty($link['url'])): ?>
<a href="<?= $link['url'] ?>" target="<?= $link['target'] ?>"><?= $link['text'] ?></a>
<?php endif; ?>

A dedicated multi-state color palette for hyperlinks, supporting standard, hover, active, visited, and focus states.

  • Attributes:
    • color: Enable regular state color (boolean, default true).
    • hover: Enable hover state color (boolean, default true).
    • active: Enable active state color (boolean, default false).
    • visited: Enable visited state color (boolean, default false).
    • focus: Enable focus state color (boolean, default false).
    • default: Associative array of state hex colors.
'theme_link_colors' => [
'labels' => 'tpl-appearance',
'type' => 'link_color',
'name' => 'Link State Colors',
'description' => 'Configure hyperlink colors for normal, hover, and active states',
'color' => true,
'hover' => true,
'active' => true,
'default' => [
'color' => '#1a73e8',
'hover' => '#1557b0',
'active' => '#0d47a1',
],
],
  • Template Usage:
<?php $lc = _g('theme_link_colors'); ?>
<style>
a { color: <?= $lc['color'] ?>; }
a:hover { color: <?= $lc['hover'] ?>; }
<?php if (!empty($lc['active'])): ?>
a:active { color: <?= $lc['active'] ?>; }
<?php endif; ?>
</style>

Spacing (spacing)​

Used to configure padding or margin. Supports all-sides unified entry or individual controls for top, right, bottom, left, plus unit switching (px, %, rem, em).

  • Attributes:
    • all: Boolean (true for all-sides unified input; false (default) for 4 directional inputs).
    • units: Array of supported units, e.g. ['px', '%', 'rem', 'em'].
    • default: Associative array:
      • 4-direction mode: ['top' => '16', 'right' => '20', 'bottom' => '16', 'left' => '20', 'unit' => 'px']
      • All-in-one mode: ['all' => '20', 'unit' => 'px']
'container_padding' => [
'labels' => 'tpl-appearance',
'type' => 'spacing',
'name' => 'Container Padding',
'description' => 'Configure container inner padding with unit selection',
'units' => ['px', '%', 'rem'],
'default' => [
'top' => '16',
'right' => '20',
'bottom' => '16',
'left' => '20',
'unit' => 'px',
],
],
  • Template Usage:
<?php $sp = _g('container_padding'); ?>
<style>
.container {
padding: <?= "{$sp['top']}{$sp['unit']} {$sp['right']}{$sp['unit']} {$sp['bottom']}{$sp['unit']} {$sp['left']}{$sp['unit']}" ?>;
}
</style>

Border (border)​

An integrated border styling control combining width, border style (solid, dashed, dotted, double, inset, outset, none), and color picker.

  • Attributes:
    • all: Boolean (true (default) for unified border width; false for independent top/right/bottom/left widths).
    • unit: Border width unit (default 'px').
    • default: Associative array containing all (or top/right/bottom/left), style, and color.
'card_border' => [
'labels' => 'tpl-appearance',
'type' => 'border',
'name' => 'Card Border Style',
'description' => 'Configure border width, line style, and color',
'all' => true,
'unit' => 'px',
'default' => [
'all' => '1',
'style' => 'solid',
'color' => '#e2e8f0',
],
],
  • Template Usage:
<?php $border = _g('card_border'); ?>
<style>
.card {
border: <?= $border['all'] ?>px <?= $border['style'] ?> <?= $border['color'] ?>;
}
</style>

Background (background)​

Full-featured background style component covering background color, image upload / media library picker, repeat mode, alignment position, sizing, and attachment behavior. Image URLs are automatically resolved to full paths when retrieved.

  • Attributes:
    • default: Associative array with keys:
      • background-color: Hex color (e.g. '#f8fafc')
      • background-image: Background image URL
      • background-repeat: Repeat mode (no-repeat, repeat, repeat-x, repeat-y)
      • background-position: Position (e.g. center center, left top)
      • background-size: Sizing (cover, contain, auto, 100% 100%)
      • background-attachment: Attachment mode (scroll, fixed)
'site_background' => [
'labels' => 'tpl-appearance',
'type' => 'background',
'name' => 'Global Background',
'description' => 'Configure background color, image, tiling, position, and attachment',
'default' => [
'background-color' => '#f8fafc',
'background-image' => '',
'background-repeat' => 'no-repeat',
'background-position' => 'center center',
'background-size' => 'cover',
'background-attachment' => 'scroll',
],
],
  • Template Usage:
<?php $bg = _g('site_background'); ?>
<style>
body {
background-color: <?= $bg['background-color'] ?>;
<?php if (!empty($bg['background-image'])): ?>
background-image: url('<?= $bg['background-image'] ?>');
background-repeat: <?= $bg['background-repeat'] ?>;
background-position: <?= $bg['background-position'] ?>;
background-size: <?= $bg['background-size'] ?>;
background-attachment: <?= $bg['background-attachment'] ?>;
<?php endif; ?>
}
</style>

Adding icons to the settings menu​

You can add an icons array within the TplOptionsNavi item to add an icon before the parent setting name of your theme settings sidebar menu. The key names of the icons array are consistent with the values array of the TplOptionsNavi item. Using Remixicon, find a suitable icon on the icon site and copy the attribute value in its class, for example class="ri-home-line", just copy ri-home-line. In addition, you need to add the following code to the template plugins.php to introduce icon CSS.

function optionIconFont() {
echo sprintf('<link rel="stylesheet" href="%s">', 'https://cdn.bootcdn.net/ajax/libs/remixicon/3.5.0/remixicon.min.css?ver=' . Option::EMLOG_VERSION_TIMESTAMP);
}
addAction('adm_head', 'optionIconFont');

How to call setting items in the template​

The plugin provides a simple method _g($key) or _em($key) to get settings. Taking _g($key) as an example:

  • Use _g('sidebar') to get the sidebar setting. The value obtained will be 0 or 1.
  • Use _g('sortIcon') to get all settings of category icons, an array with category id as the key.
  • Use _g('sortIcon.1') to get the sortIcon with category id 1 (if it exists). Note that for type page, the page id will be obtained; for type sort, the category id will be obtained; for type tag, the tag name will be obtained.

If no parameters are passed, i.e., using _g() method, all setting items will be obtained. For templates migrated from old ones, you can use extract(_g()); to replace the original loading of the option file.

Example: Configuration from the default theme setting site logo


<?php if (_g('logotype') == 1): ?>
<a class="blog-header-title" href="<?= BLOG_URL ?>"><?= $blogname ?></a>
<div class="blog-header-subtitle subtitle-overflow" title="<?= $bloginfo ?>"><?= $bloginfo ?></div>
<?php else: ?>
<a href="<?php echo BLOG_URL; ?>" title="<?php echo $bloginfo; ?>"><img src="<?php echo _g('logoimg'); ?>" alt="<?php echo $blogname; ?>"/></a>
<?php endif; ?>

If you need to get data from multi-content blocks, provide the _getBlock($key, $type) method to get it:

  • $key is the same as the parameter provided by the _g() method
  • $type is the data type of the multi-content block, divided into title and content. This parameter can be omitted, and content will be obtained by default. title is the title filled in the multi-content block. content is the content. Using this built-in function, you can get the text of the text type multi-content block or the image URL set by the image type multi-content block.
  • Return value type is array

Use case:

_getBlock('image-block', 'content')

Complete Example of Default Theme options.php​

Below is the complete real configuration file example from the default theme (content/templates/default/options.php), which developers can refer to or copy directly:

<?php
/*@support tpl_options*/

/**
* 模板设置的配置文件
* 详见官网文档-模板开发:https://www.emlog.net/docs/dev/template
*/

defined('EMLOG_ROOT') || exit('access denied!');

$options = [
'TplOptionsNavi' => [
'name' => 'Define Settings Tab Name',
'values' => [
'tpl-head' => 'Header Settings',
'tpl-home' => 'Home Settings',
'tpl-article' => 'Article Settings',
],
'description' => '' // Settings description (optional)
],
'logotype' => [
'labels' => 'tpl-head',
'type' => 'radio',
'name' => 'LOGO Display Mode',
'values' => [
'1' => 'Text',
'0' => 'Image',
'2' => 'Image and text',
],
'default' => '1',
],
'logoimg' => [
'labels' => 'tpl-head',
'type' => 'image',
'name' => 'Upload LOGO',
'values' => [
TEMPLATE_URL . 'images/logo.png',
],
'description' => 'Upload LOGO image, recommended size 180x60 pixels, height not exceeding 60 pixels'
],
'favicon' => [
'labels' => 'tpl-head',
'type' => 'image',
'name' => 'Browser Icon (favicon)',
'description' => 'Upload browser icon, recommended size 48x48 PNG or JPG image'
],
'slideShow' => [
'labels' => 'tpl-home',
'type' => 'text',
'name' => 'Home Slideshow',
'multi' => true,
'description' => 'One per line, recommended image height 260 pixels, format: Image URL | Image Title | Link URL',
],
'isShowCover' => [
'labels' => 'tpl-article',
'type' => 'checkon',
'name' => 'Display article cover image on article page',
'values' => ['1' => 'Enable'],
'default' => '0',
'description' => ''
],
'isSideBar' => [
'labels' => 'tpl-article',
'type' => 'checkon',
'name' => 'Display sidebar on article page',
'values' => ['1' => 'Enable'],
'default' => '0',
'description' => ''
],
'isAllowCommentUrl' => [
'labels' => 'tpl-article',
'type' => 'checkon',
'name' => 'Allow submitting homepage in comments',
'values' => ['1' => 'Enable'],
'default' => '1',
'description' => ''
],
/*
// ==========================================
// 新增类型演示(参考小风主题选项框架扩展)
// ==========================================

// 1. notice - 提醒
'demo_notice' => [
'labels' => 'tpl-demo',
'type' => 'notice',
'style' => 'info',
'name' => '组件演示说明',
'content' => '本页面演示了模板设置插件新增支持的 10 种选项类型:background(背景)、border(边框)、date(日期)、link(链接)、link_color(超链接颜色)、notice(提醒)、number(数字框)、slider(滑块)、spacing(间距)、submessage(小提醒)。',
],

// 2. submessage - 小提醒
'demo_submessage' => [
'labels' => 'tpl-demo',
'type' => 'submessage',
'style' => 'success',
'content' => '小提醒(submessage):以左侧色条的紧凑形式展示内联提示、注意事项或配置引导。',
],

// 3. number - 数字文本框
'demo_number' => [
'labels' => 'tpl-demo',
'type' => 'number',
'name' => '分页显示文章数',
'description' => '数字文本框(number):支持设置数值上下限(min/max)、步长与后缀单位',
'min' => 1,
'max' => 100,
'step' => 1,
'unit' => '篇',
'default' => '10',
],

// 4. slider - 滑块
'demo_slider' => [
'labels' => 'tpl-demo',
'type' => 'slider',
'name' => '列表卡片圆角弧度',
'description' => '滑块(slider):拖动滑块或在右侧数字框输入,实时双向联动更新',
'min' => 0,
'max' => 50,
'step' => 1,
'unit' => 'px',
'default' => '8',
],

// 5. date - 日期(单日期与区间)
'demo_date' => [
'labels' => 'tpl-demo',
'type' => 'date',
'name' => '单个活动截止日期',
'description' => '日期组件(date):单日期选择器,采用写文章页面的日历交互控件',
'default' => '2026-12-31',
],
'demo_date_range' => [
'labels' => 'tpl-demo',
'type' => 'date',
'name' => '活动起止时间范围',
'description' => '日期组件(date):支持起止范围区间选择(from_to)',
'from_to' => true,
'text_from' => '开始',
'text_to' => '结束',
'default' => [
'from' => '2026-10-01',
'to' => '2026-10-31',
],
],

// 6. link - 链接
'demo_link' => [
'labels' => 'tpl-demo',
'type' => 'link',
'name' => '自定义推荐链接',
'description' => '链接组件(link):包含链接文字、链接网址以及在新标签页中打开',
'default' => [
'text' => 'Emlog 官网',
'url' => 'https://www.emlog.net',
'target' => '_blank',
],
],

// 7. link_color - 超链接颜色
'demo_link_color' => [
'labels' => 'tpl-demo',
'type' => 'link_color',
'name' => '超链接多状态颜色',
'description' => '超链接颜色(link_color):支持常规、悬浮、激活等多状态色彩配置',
'color' => true,
'hover' => true,
'active' => true,
'default' => [
'color' => '#1a73e8',
'hover' => '#1557b0',
'active' => '#0d47a1',
],
],

// 8. spacing - 间距
'demo_spacing' => [
'labels' => 'tpl-demo',
'type' => 'spacing',
'name' => '页面容器内边距(Padding)',
'description' => '间距组件(spacing):支持独立配置上、右、下、左间距及单位选择',
'units' => ['px', '%', 'rem'],
'default' => [
'top' => '16',
'right' => '20',
'bottom' => '16',
'left' => '20',
'unit' => 'px',
],
],

// 9. border - 边框
'demo_border' => [
'labels' => 'tpl-demo',
'type' => 'border',
'name' => '卡片边框样式',
'description' => '边框组件(border):支持边框粗细、线型样式(实线/虚线/点线等)以及边框颜色',
'all' => true,
'unit' => 'px',
'default' => [
'all' => '1',
'style' => 'solid',
'color' => '#e2e8f0',
],
],

// 10. background - 背景
'demo_background' => [
'labels' => 'tpl-demo',
'type' => 'background',
'name' => '全局背景配置',
'description' => '背景组件(background):支持背景色、背景图上传、平铺模式、对齐位置与附着方式',
'default' => [
'background-color' => '#f8fafc',
'background-image' => '',
'background-repeat' => 'no-repeat',
'background-position' => 'center center',
'background-size' => 'cover',
'background-attachment' => 'scroll',
],
],
*/
];

Directly Usable Constants​

Variable, ConstantTypeDescription
Option::EMLOG_VERSIONConstantGet current emlog version number
ROLEConstantCurrent user role (user group): admin, writer, visitor
ROLE_ADMINConstantadmin
ROLE_WRITERConstantwriter
ROLE_VISITORConstantvisitor
UIDConstantCurrent user UID
BLOG_URLConstantSite URL
ISLOGINConstantLogin status, true for logged in, false for not logged in
TEMPLATE_URLConstantCurrent template URL eg: http://localhost:8080/content/templates/default/
TEMPLATE_PATHConstantAbsolute path of current template eg:/www/emlog/content/templates/default/

The above constants can be used in the template in the following way:

// Output current site URL
<?= BLOG_URL ?>

Common Configuration Information Retrieval​

Configuration ItemGet Example
Site TitleOption::get('blogname')
Site SubtitleOption::get('bloginfo')
Site Meta Info: titleOption::get('site_title')
Site Meta Info: descriptionOption::get('site_description')
Site Meta Info: keywordOption::get('site_key')
Site URLOption::get('blogurl')

Usage Example:

// Output current site name
<?= Option::get('blogname')?>

Common Methods & Functions​

Directly usable methods and functions: Common Methods and Functions

Asynchronous Requests​

The Pro version supports ajax asynchronous requests and returns json format information, facilitating users to build friendlier frontend interaction experiences such as comments, popup login, registration, and password retrieval.

Post Comment​

User Login​

User Registration​

Retrieve Password​

Article Search​

Search route: https://yoursite_domain/?keyword=emlog&sid=1

  • keyword: Search keyword
  • sid: Category id, optional. If filled, only search articles under this category. Themes can implement search by category themselves.

Comment UBB Support​

emlog comments support UBB tag shortcode parsing. Users can use UBB tags in comments to format comment content, such as bold, color, images, links. Developers can develop comment input boxes that support inserting UBB codes to provide a richer comment experience.

Currently supported UBB tag shortcodes are as follows: bold, color, link, image:

[b]text[/b]
[color=red]text[/color]
[url]http://example.com[/url]
[img]http://example.com/xxx.jpg[/img]

Reference Demo​

The default theme that comes with the emlog system is the best demo. You can modify it based on this theme to develop your own theme, or refer to some elements and files of this theme. Default template directory: content/templates/default

Open Source Release​

If the template you developed is open sourced on Github, please add the topic to the repository: emlog-template

Publish to App Store​

The finished theme, after testing, can be packaged and published to the official app store.

  1. Packaging: Go to the content\templates directory, find the template folder, and directly use the zip compression tool to package this folder (note: do not enter the folder to package), and name the packaged compressed package as: template English alias.zip, such as default.zip
  2. Publish: Log in to the official website emlog.net - My - App Development - Publish Template, fill in the necessary information according to the prompts to publish, and wait for review.```