SuperAPI AI Directory

basercms5-theme-development

Frontend & websites

View repository

Updated 10-15 17:24

About this skill

baserCMS 5.x Theme Development Pattern Collection

This skill targets, in baserCMS 5.x (CakePHP 5-based),new development and modification of themes. Themes in 5.x arein plugin formatand,plugins/<ThemeName>/ and are composed of templates (templates/)・Asset (webroot/) and a small number of Helpers for front-end display (src/View/Helper/). For common rules such as environment, directories, naming, and the prohibition of core hacks, refer to basercms5-development; when giving a theme internal code equivalent to a plugin such as Controller/Table, refer to basercms5-plugin-development; and for migration work from 4.x themes, refer to basercms-theme-4-to-5-upgrade .

1. Structure of theme plugins

Create a theme with the following directory structure (core reference implementation: vendor/baserproject/bc-front/templates/, sample: plugins/BcThemeSample/)。

plugins/<ThemeName>/
├── config.php                  … テーマ情報(return 配列。'type' => 'Theme' 必須)
├── src/<ThemeName>Plugin.php   … プラグインクラス(bake 生成の雛形でよい)
├── src/View/Helper/            … テーマ独自のフロント表示用 Helper(任意)
├── templates/
│   ├── layout/                 … レイアウト(default.php 等)
│   ├── element/                … 共通エレメント(header.php / footer.php 等)
│   ├── element/widget/         … ウィジェット用 element(§5)
│   ├── Pages/                  … 固定ページテンプレート(default.php 等)
│   ├── Blog/<content>/         … ブログテンプレート(posts.php / index.php / single.php / archives.php)
│   └── Mail/<content>/         … メールフォームテンプレート(index.php / confirm.php / submit.php)
└── webroot/                    … css / js / img(テーマアセット)
  • config.php は return ['type' => 'Theme', 'title' => ..., 'description' => ..., 'author' => ..., 'url' => ...]; .
  • Layout templates/layout/default.php , output the body with $this->fetch('content') , and inside<head> , immediately before $this->BcBaser->charset() / title() / metaDescription() / css() / js() / scripts()、</body> , assemble it using BcBaser APIs such as $this->BcBaser->func() .
  • The static page template templates/Pages/default.php outputs the body edited in the admin panel with echo $page->contents ($page is a Page entity).
  • Per-content templates are placed as templates/Blog/<コンテンツのテンプレート名>/posts.php in the form "feature plugin name/template name/action name", and the directory for the template name selected in the content settings of the admin panel is used. Templates not present in the theme fall back to core (bc-front/templates/plugin/BcBlog/ plugin/BcMail/ , etc.).
  • webroot/ Assets under /テーマ名snake形式/css/style.css (plugin webroot delivery) (§4).
  • Apply the theme from the admin panel (Theme Management). To switch directly in a development environment, sites table's theme column is UPDATEd to clear the cache (bin/cake cache clear_all).

2. View and view variable conventions

In layout / element / templates, $this is the View itself. In Helpers, do not confuse it with $this->getView() (calling $this->getView() in a View calls Call to undefined method ...View::getView())。

Basically, do not depend on view variables supplied by the controller; instead,derive required values yourselfon the template side. The core does not supply global variables such as $user to all front-end views.

// ログインユーザー(UserInterface|false — false があり得るので必ず判定する)
$user = \BaserCore\Utility\BcUtil::loginUser();
$authPrefixes = $user ? $user->getAuthPrefixes() : [];

// 現在のプレフィックス(Front / Admin など)
$currentPrefix = \BaserCore\Utility\BcUtil::getRequestPrefix($this->getRequest());

// セッション
$session = $this->getRequest()->getSession();

Get the current content and site information fromrequest attributes. Both are entities, and since they may be null depending on context, reference them with ?-> .

$currentContent = $this->getRequest()->getAttribute('currentContent'); // Content エンティティ|null
$currentSite = $this->getRequest()->getAttribute('currentSite');       // Site エンティティ|null
$entityId = $currentContent?->entity_id;  // 機能側レコードID(ブログコンテンツID 等)
$siteId = $currentSite?->id;

Write the current URL path as $this->getRequest()->getPath() (returned with a leading slash).

3. Helper

BcBaser delegation mechanism (PluginBaserHelper)

$this->BcBaser->blogPosts('news', 5) Feature shortcuts such as Bc<Plugin>BaserHelper::methods() are not methods of BcBaserHelper itself, but are provided viaMapping tablereturned by each plugin's __call (e.g., bc-blog's BcBlogBaserHelper::methods() に 'blogPosts' => ['Blog', 'posts'])。

  • Existence is checked in two steps: ①grep -rln "function <名前>" vendor/baserproject/ to find the function definition → ② if not found, grep -rn "'<名前>'" vendor/baserproject/*/src/View/Helper/Bc*BaserHelper.php で methods() to find the mapping. Because of mapping delegation,having no function definition is normal, so do not judge "does not exist" based on ① alone.
  • The delegation target methodworks only when the providing plugin is enabled. When disabled, it results in BadMethodCall.

Commonly used static utilities

\BaserCore\Utility\BcSiteConfig::get('formal_name');  // サイト基本設定(address / name 等のキー)
\BaserCore\Utility\BcUtil::fullUrl($url);              // フルURL生成

Dynamic loading of helpers

The helper is new , do not instantiate (with no DI container injected, getService() fails), but load from the View.loadHelper() returns an instance.

$blog = $this->getView()->loadHelper('BcBlog.Blog');  // Helper 内から
$blog = $this->loadHelper('BcBlog.Blog');             // テンプレート内($this が View)から

Reference name conventions and guards for dependencies on other plugins

  • Core feature reference names are written with the Bc prefix: helper BcBlog.Blog, table TableRegistry::getTableLocator()->get('BcBlog.BlogPosts')、element $this->BcBaser->element('BcBlog.xxx'). The core table isplural + plugin prefix(BaserCore.Contents / BaserCore.Sites)。
  • From the themeWhen calling another plugin's helper, guard with Plugin::isLoaded() so the entire theme does not break when the plugin is disabled, and loadHelper if necessary.
if (\Cake\Core\Plugin::isLoaded('<Plugin>')) {
    $helper = $this->helpers()->has('Sample')
        ? $this->Sample
        : $this->loadHelper('<Plugin>.Sample');
    $helper->show(['num' => 3]);
}

4. Assets and URLs

css() / js() signatures

BcBaser->css($path, $inline = true, $options = [])(js() likewise).The second argument is $inline(false buffer it with scripts() output with), andmedia attributes such asthird argumentare written in.

$this->BcBaser->css('style');                                  // <link ...>
$this->BcBaser->css(['print'], true, ['media' => 'print']);    // 属性は第3引数
$this->BcBaser->js('theme', true, ['defer' => true]);

Do not hardcode URLs

URLs for links, images, etc. should be written through/about/ , etc.). The base is automatically added when installed in a subdirectory. BcBaser->getUrl('/path') rather than hardcoding root-relative paths (

<a href="<?php echo $this->BcBaser->getUrl('/about/') ?>">会社概要</a>
<?php $this->BcBaser->link('会社概要', '/about/') ?>

When assembling URL strings inside a Helper, either pass through \Cake\Routing\Router::url($url) or prefix the request's webroot: $this->getView()->getRequest()->getAttribute('webroot') . ltrim($url, '/')。

Displaying uploaded images (BcUploadHelper::uploadImage)

uploadImage('<field>', $entity, $options) write it as — the first argument is the plain field name,the second argument must be an EntityInterface(strings not allowed). BcUploadHelper resolves the table from the View's plugin/name by default, so when using it from a theme or another plugin's template, explicitly specify 'table' => '<Plugin>.<Tables>'(with BcUpload behavior) in options. The image size is 'imgsize', and the fallback when absent is 'noimage'. For mail form templates including file type, refer to setTableToUpload() in §6.

Delivery format for theme assets

Theme's webroot/ Underthe theme name in snake_case is delivered via URLs prefixed with.

$this->BcBaser->css('style');  // <ThemeName> の webroot/css/style.css を解決
// URL を直接組む場合
$this->BcBaser->getUrl('/sample_theme/css/style.css');  // plugins/SampleTheme/webroot/css/style.css

5. Widgets

Place the element to display in the widget area under templates/element/widget/(singular widget。widgets , not). BcWidgetArea searches this path (core placement example: bc-front/templates/plugin/BcBlog/element/widget/blog_recent_entries.php)。

  • Even when using a widget provided by a plugin (e.g., BcBlog.widget/blog_recent_entries)をOverride in the theme, place it at the same path on the theme side templates/element/widget/<名前>.php .
  • Place elements for admin panel widget settings under templates/Admin/element/widget/ .

6. Mail form templates

The mail form template is templates/Mail/<テンプレート名>/index.php(input),confirm.php(confirmation),submit.php(completion), and form rendering is done with BcBaser's mailForm-related APIs to write (BcMailBaserHelper::methods() bridges to the Mailform helper). The core source of truth is in vendor/baserproject/bc-front/templates/plugin/BcMail/ , so if in doubt, match that.

For form generation, take the entity $mailMessage set by the controller as the first argument, and specifyvalueSources .

$this->BcBaser->createMailForm($mailMessage, array_merge($options, ['valueSources' => ['context']]));

Main APIs (write field names as plain names. The context of theMailMessage. prefix is handled internally):

Purpose How to write
hidden field $this->BcBaser->mailFormHidden('mode', ['id' => 'MailMessageMode'])
field unlock $this->BcBaser->unlockMailFormField('mode')
Submit button $this->BcBaser->mailFormSubmit($caption, $options)
Error display $this->BcBaser->mailFormError('field_name', $message)
Image verification $this->BcBaser->mailFormAuthCaptcha('auth_captcha', ['helper' => $this->BcBaser])
Form end $this->BcBaser->endMailForm()
freeze (confirm.php) $this->BcBaser->freezeMailForm()
Field rendering $this->BcBaser->mailFormControl($fieldName, $options)
label $this->BcBaser->mailFormLabel($fieldName, $text)
Getting input values $this->BcBaser->getMailFormSourceValue($fieldName)
Group last field determination $this->BcBaser->isMailFormGroupLastField($mailFields, $field)
  • mailFormHidden('mode') with a plain field name, the id refers to mode . JS #MailMessageMode if referring to ['id' => 'MailMessageMode'] explicitly.
  • At the beginning of templates that render file-type fields (index.php / confirm.php), always write the following one line. Without it, it fails with BcUploadHelper を利用するには … table … を指定してください(BcException).
$this->BcBaser->setTableToUpload('BcMail.MailMessages');
  • The element('mail_input') that renders the field list falls back to the core version (bc-front/.../BcMail/element/mail_input.php), so if you do not need a custom design, you do not have to place it in the theme.

7. Blog templates

The blog template is templates/Blog/<テンプレート名>/ に index.php(list),archives.php(category/tag/year-month archive),single.php(detail),posts.php(BcBaser->blogPosts() parts list called from ).

  • $posts / $post はentity(or its ResultSet). Write associations with property access too: $post->title、$post->content、$post->detail、$post->blog_category->title、$post->blog_content_id。
  • The column name for the post date/time is posted. Write sort specification as 'sort' => 'posted' / orderBy(['BlogPosts.posted' => 'DESC']) .
  • The featured image is $this->Blog->getEyeCatch($post, ['width' => 300, 'link' => true]) or BcBaser-delegated $this->BcBaser->blogPostEyeCatch($post, [...]) . Check existence with $post->eye_catch .
  • Article links, dates, categories, and titles can also be written with BcBaser-delegated APIs: getBlogPostLinkUrl($post) / blogPostDate($post, 'Y.m.d') / blogPostCategory($post) / blogPostTitle($post, false) / blogPostContent($post, true, false, 46)。
  • Category lists and tag lists are rendered with the Blog helper/element (refer to the core element/blog_category_list.php / blog_tag_list.php ).
  • When fetching articles by querying the Table directly, write with the query builder from TableRegistry::getTableLocator()->get('BcBlog.BlogPosts') , and use getConditionAllowPublish() for publication conditions.
$blogPostsTable = \Cake\ORM\TableRegistry::getTableLocator()->get('BcBlog.BlogPosts');
$posts = $blogPostsTable->find()
    ->where($blogPostsTable->getConditionAllowPublish())
    ->where(['BlogPosts.blog_content_id' => $blogContentId])
    ->orderBy(['BlogPosts.posted' => 'DESC'])
    ->limit($num)
    ->all();

If the same kind of retrieval logic is scattered across multiple templates, consolidate it into the theme's src/View/Helper/<ThemeName>Helper.php .