This skill targetsThemebaserCMS 4 → 5 migration. A theme is mainly composed of templates such as templates/layout・templates/element・templates/Blog・templates/Pages・templates/Mail , has no Controller/Table, and refers to a configuration accompanied by a small number of Helpers for front-end display logic (src/View/Helper/*.php).BcAddonMigrator Converted a theme into a 5.x theme plugin withafterIt contains the manual rewriting patterns required (TH- series) and real-world example patterns of front-end display errors among template/theme rendering issues (F- series).
What this skill handles isDetection and conversion of 4.x theme codeis.The authoritative source for how to correctly write 5.x themes is basercms5-theme-development(plugin internal code is covered by basercms5-plugin-development), so if you are unsure about the target specifications (theme plugin structure, view variable conventions, helpers, assets and URLs, widgets, mail form/blog templates), refer to that. Read each section below in the form "detection of 4.x idioms (symptoms/grep patterns) → key points of conversion → the corresponding section of the authoritative skill".
The overall theme conversion procedure (zipping the theme → BcAddonMigrator conversion with plugins/ placement into sites of the table theme cross-cutting 5.x conversion → application to basercms4-to-5-upgrade refer to the corresponding section of the skill (standard flow for theme conversion/migration). This skill is called from within that process and provides concrete measures for bringing the converted templates and Helpers into a state where rendering actually works.
The principle of cross-cutting handling (once you fix one place, use grep -rn to enumerate all instances of the same pattern → mechanically apply unique conversions in bulk → verify all changed files with php -l ) and the rewriting patterns for C-0 (mechanical bulk conversion catalog), event listeners, and Helpers are covered by the basercms-plugin-4-to-5-upgrade skill. If the theme contains plugin-equivalent internal code (Controller/Table/admin screens), use that skill as well.
Theme-specific migration patterns (differences from the T-/C- series)
Themes have no Controller/Table(because their structure is fundamentally different from plugins), so the T- (Table/ORM) and C- (Controller/screens) catalogs in the basercms-plugin-4-to-5-upgrade skill are basically not applicable. The main subject of a theme is
templates/layouttemplates/elementtemplates/Blogtemplates/Pagestemplates/Mailand a small number ofsrc/View/Helper/*.php。F- series (front-end display errors) are the main targetHowever, because the way theme-specific "disappeared shortcut-style helper methods" are encountered differs from plugins, they are summarized below as specific patterns (intended to be called from the "Theme Conversion" chapter ofbasercms4-to-5-upgrade).
TH-1. $this->BcBaser->siteConfig['key'] / View variable $siteConfig['key'] does not exist in 5.x
- Detection: Template/Helper
$siteConfig['key']/$this->BcBaser->siteConfig['key'](grep -rn "siteConfig\[" templates/ src/). In version 5, it does not cause a syntax error,and an empty string is output with a warning for an undefined variable/undefined propertyonly, so it is easy to miss (site name, address, etc. silently become empty). - Conversion:
\BaserCore\Utility\BcSiteConfig::get('key')to (static method). The keys are the same as the version 4site_configsof the tablenamecolumns. Once found in one place, apply it across the entire theme (layout, element, Helper) with grep. - For the version 5 conventions of static utilities, refer to basercms5-theme-development §3 "Helper".
TH-2. Global function fullUrl() does not exist in version 5
- Detection:
Call to undefined function fullUrl()causes Fatal (version 4 global function). - Conversion:
\BaserCore\Utility\BcUtil::fullUrl($url)to (static method) (see basercms5-theme-development §3 "Helper").
TH-3. Code in which a theme Helper directly instantiates a version 4-only Component causes an immediate Fatal — first check whether equivalent functionality has already been ported to baser-core
Code in which a version 4 theme-specific Helper directly creates a CakePHP2 Component such as new XxxComponent(new ComponentCollection()) ,BcAddonMigrator may remain as-is even after mechanical conversion.Component Neither the ComponentCollection exists in version 5, soit causes a Fatal the moment it is called(this has the same root cause as F-4 "manual instantiation of helpers", but differs in that the target is a Component).
- Order of handling: Do not immediately reimplement it yourself.First,
grep -rli "<機能キーワード>" vendor/baserproject/Confirm withwhether an equivalent utility has already been ported to baser-core/the relevant core plugin. BaserCMS5 often has already ported major version 4-only logic (such as Google Geocoding integration) asBaserCore\Utility\*やBaserCore\View\Helper\*. - Example: of the theme
BcGooglemapsHelper::getLocation()がnew BcGmapsComponent(new ComponentCollection())(version 4lib/Baser/Controller/Component/BcGmapsComponent.php. Its contents are an XML request to the Google Geocoding API) was being called. As a result of investigation,BaserCore\Utility\BcGmaps::getLocation($address)(Cake\Http\Clientin baser-core, converted to an HTTP request withCacheand cached by['latitude'=>..,'longitude'=>..]the same shape as version 4), already existed. On the theme side, the issue was resolved simply by keeping the originalload()/_getScript()interface while replacing only the contents ofgetLocation()with delegation to this core utility (no need to implement an HTTP client or XML parser on your own). - Easy-to-overlook caller: Component calls are hidden inside the Helper, so from the element template side they look like nothing more than a method call. First read and understand the conditions under which the element template actually reaches that method (for example, it is called only with default arguments), and then trace the Helper-side implementation (in this example, work was started after confirming the conditional branch that "it reaches
loadLocation()→getLocation()only when latitude/longitude are not explicitly specified").
TH-4. BcBaserHelper Verifying the existence of shortcut methods by "grepping function names" alone leads to misjudgments (★a lesson already corrected)
- Detection: Calls to front-end shortcuts (
BcBaserHelperetc.) that existed in the 4.x seriesblogPosts($blogName, $num). In the 5.x series, they are delegated tomethods()via the PluginBaserHelper mechanism (the__callmapping of each plugin), soit is normal for no function definition to exist。grep -rln "function <名前>"and disable the call (★a warning from an actual misjudgment). - Key points of the conversion: Verify existence in "① grep for the function definition → ②
methods()mapping grep"two stages". If it is found in ②, it works as-is when the providing plugin is enabled (when disabled, it becomes BadMethodCall rather than a MissingHelperException-type error, so also suspect the possibility that the plugin is disabled). Only when it is absent from both ① and ② is it truly abolished → manually reimplement it with the query builder, and if it is scattered across multiple places, consolidate it into the theme's Helper. - For the authoritative source on the delegation mechanism and the two-stage verification procedure, see basercms5-theme-development §3 "Helpers"; for the basic form of reimplementing blog article retrieval (
getConditionAllowPublish()etc.), see §7 "Blog Templates" in the same document. - Cross-checking with duplicate implementations: There may be functional overlap with a custom-implemented element. However, before judging it a "duplicate",check whether that element is actually referenced(
grep -rn "element('<名前>'"— if it is an unconnected file with zero references, it is not a duplicate, and the correct action is to restore the one faithful to 4.x behavior (the original call).
TH-5. Code in layouts/elements that directly calls another plugin's Helper must be distinguished between "a theme bug" and "the dependent plugin not being installed"
The theme's layout and elements may be like $this->Banner->showBanner(...) asA Helper provided by another plugin may be called directly. If the migration work is divided into stages like フェーズ3.5(棚卸し) → フェーズ4-(b)(テーマ/プラグイン機械変換) → フェーズ4-(a)(マーケット配布の5系プラグイン導入) , looking only at the theme side at a stage where that dependent plugin has not yet been installed may make it appear as Undefined property: $this->Banner(Helper not loaded), butthis is not a defect in the theme's code; the dependent plugin's phase simply has not arrived yetThere are cases like this.
- Handling: In the ledger, record it distinctly as **"Deferred (dependent plugin not installed; waiting for phase 4-(a))"** rather than "not started / migrated", and do not include it in the theme's standalone completion criteria. Verify operation again after the installation phase for the relevant plugin is complete.
- At minimum, note the caller's method name and expected options (
['num' => 0]etc.) in the ledger so they can be cross-checked later (because the signature may have changed in the 5.x version of the plugin once it is installed).
TH-6. BcSite::findCurrent() + getBaseUrl() . 'theme/<name>/' The 4.x idiom of building theme asset URLs with this immediately causes a Fatal error
- Detection:
grep -rn "BcSite::findCurrent\|'theme/'" templates/ src/. The 4.x series took the theme name from the site entity and built URLs in thetheme/<name>/img/...format, but theBcSiteclass does not exist in the 5.x series, causing an immediate Fatal error. - Conversion: Theme assets are delivered in the plugin webroot format
$this->BcBaser->getUrl('/<テーマ名snake>/img/...')(Source: basercms5-theme-development §4 "Assets and URLs").
Examples of front-end display error patterns (symptom → cause → fix)
Frequently occurring examples when restoring the front-end display of a theme/plugin.
BcAddonMigratorTypical defects that remain even after automatic conversion with .Search by the error message and match it to the corresponding pattern. Since fixing one causes the next error to appear in an "onion peeling" manner,curl -sk -o /dev/null -w "%{http_code}" <URL>check the status with and eliminate them one by one.
F-1. MissingTableClassException: Table class for alias 'Content' could not be found.
- Detected: v4-style
TableRegistry::getTableLocator()->get('Content')(singular form, no plugin prefix). - Conversion: Core tables useplural form + plugin prefix(
BaserCore.Contents/BaserCore.Sites). Also,find('first', 配列)→ query builder, array access → entity ($content->id)、where()condition keys should include the table alias. For the reference name conventions, see basercms5-theme-development §3 "Helpers".
F-2. Retrieving current content/site information (changes to request attributes)
- Detected: v4's
$this->request->params['Content']['site_id']/params['Site']['device'](deprecated). - Conversion: Refer to it via request attribute
currentContent/currentSitefrom (entity)->id->site_id->device, etc. For the authoritative source on how to retrieve it, see basercms5-theme-development §2 "View and View Variable Conventions".
F-3. Bc prefix in core plugin reference names (common to Helpers, tables, and elements)
- Detected: Still using v4 reference names (
loadHelper('Blog.Blog')・get('Blog.BlogContents')・getElement('Blog...'))。 - Conversion: Core plugins use the
Bcprefix (Blog→BcBlog、Mail→BcMail). This applies not only to URL arrays but also to helper loading, table aliases, and element paths. For the authoritative source on the conventions, see basercms5-theme-development §3 "Helpers".
F-4. Manual instantiation of helpers (new XxxHelper(new BcAppView()))
- Detected: v4-style
new <Xxx>Helper(new BcAppView())(BcAppViewis deprecated, and without DI container injection,getService()fails). - Conversion:
$this->getView()->loadHelper('Plugin.Helper')load with (loadHelper()returns an instance). For the conventions on dynamic loading, see basercms5-theme-development §3 "Helpers".
F-5. League\Container\Exception\NotFoundException: Alias (...ServiceInterface) is not being managed / MissingHelperException
If a plugin that the front end depends on (e.g., BcBlog) is In the plugins table, status=0(disabled) , that plugin's ServiceProvider is not registered in the container, and it fails at the Helper constructor's getService(XxxServiceInterface::class) .
- Identification:
SELECT name, status FROM plugins;Check the status of the target plugin with . - Fix:Enablethe plugin that was used in v4 (the standard approach is plugin management in the admin panel. If the data has been migrated and the tables are in place,
UPDATE plugins SET status=1 WHERE name='BcBlog';is also acceptable). After enabling,bin/cake cache clear_all。 - Note: Another option is to rewrite the code so it does not depend on services that are not in the container (e.g., for template path determination, retrieve the blog content with
TableRegistrywithout going through a service and assemble'BcBlog...' . DS . 'Blog' . DS . $contentsTemplate . DS . $template).
F-9. Blog post sort column posts_date does not exist in v5
SQLSTATE[42S22]: Unknown column 'BlogPosts.posts_date'. For the 5 series, the blog_posts post date column is posted。
- Fix: Set the sort specification to
'sort' => 'posted'. The reliable way is to check the column name in the destination DB'sSHOW COLUMNS FROM blog_posts;.
F-11. The front-end header/menu is rendered "only when logged in"
In portal-type themes, the header navigation, user menu, app launcher, etc. are wrapped in if(!empty($user)) , andwhen not logged in, only the logo + site name are shownThis is by design. Furthermore, the header depends on plugins such as CuAppLauncher CuCustomUser CuTimeCard , so if they are disabled, the corresponding block becomes empty.
- Tip for checking: Do not jump to the conclusion that "the header does not appear" is a code bug. FirstLog in to the front, and check the activation status of dependent plugins (F-5).
F-12. Image 404s such as eyecatch images can be a mismatch between the DB and physical files
/files/blog/.../xxxx_eye_catch.jpg の MissingRouteException Even if manythe corresponding image does not exist locally in the migration source (4 series) eithermay be the case (the entity exists only on the production server, and only the local DB dump was brought over, etc.). This is not a defect in the migration code.
- Discrimination: Check whether the entity exists in the migration source's
files/(orapp/webroot/files/). If images from older years/months display but only newer years/months return 404, it is simply that the actual files are not present locally.
F-13. In the front theme, $user become empty and the header etc. is missing
- Detection: In the 4 series, the core supplied
$useretc. to all front-end views, butthe 5 series does not supply it to the front end(it is dedicated to the admin screen layer). If the theme's element references$user, it will be treated as not logged in even while logged in, and everything underif(!empty($user))(navigation, user menu, etc.) will not be rendered at all. - Conversion: Derive the necessary variables yourself at the beginning of the element/layout (
BcUtil::loginUser()=UserInterface|false・getRequestPrefix()・getAuthPrefixes()). Also, the 4 series'$this->Session->...(SessionHelper abolished) →$this->getRequest()->getSession()->...。In the element/layout,$thisis the View itselfso$this->getRequest()use (getView()is for Helpers. If called in a View,Call to undefined method ...View::getView()). For the correct way to write your own derivation, refer to basercms5-theme-development §2 "View and view variable conventions". - Supplement: The front end (prefix=
Front)のBcUtil::loginUser(), if you are logged in to the admin screen, the user can be obtained on the front end as well.
F-14. BcBaser->css() / js() 's second argument changed to $inline and media/attribute specification is ignored
- Detection: Locations where options (
css(['print'], ['media' => 'print']), etc.) are passed as the second argument in the 4 series style. In the 5 series, the second argument is$inline, so attributes are not output, resulting in the confusing symptom thatthe print-only CSS is also applied to the screen and the header etc. disappears(it is output in the HTML, and in DevTools thedisplay:none。<link>にmedia="print"derived from print.css is absent). - Conversion: pass as the second argument
$inline(usuallytrue), and attributes as the third argument. Check allallcss()/js()callswithin layouts/elements. The authoritative signature is in basercms5-theme-development §4 "Assets and URLs".
F-15. Attempt to read property "X" on array(request->params['Content'][...] conversion mistake)
- Detection:
BcAddonMigratoris a leftover from mistakenly converting the v4params['Content']['entity_id']etc.getAttribute('params')->entity_idlikearray into object arrow access(getAttribute('params')is a routing parameterarray)。 - Conversion: get the current content information from
getAttribute('currentContent')(Content entity) (see basercms5-theme-development §2 "View/View Variable Conventions").getAttribute('params')Array access to['pass'][1]itself (on a method call result is not allowedisset()— receive it in a variable first, then reference it with etc.) is correct, but?? ''.
F-16. In the view, $this->getRequest()->url is deprecated
- Detection: v4's
$this->request->url(leading slashnone). It tends to remain not only in controllers but also in theme elements. - Conversion: to
$this->getRequest()->getPath()(leading slashpresent). For places that used'/' . $request->urlin v4, remove the leading'/' .(same root as F-2. See basercms5-theme-development §2).
F-17. Migration of mail form (BcMail) theme templates
- Detection: when displaying mail form content (type=
MailContent, plugin=BcMail), first BcMail is disabled causingMissingControllerException(F-5), and even after enabling it, the theme's mail templates remain on the v4$this->Mailform->...API, resulting in multiple stages of errors. - (a) Form generation:
No context provider found for value of type 'string'—$this->Mailform->create('MailMessage', $opts)→$this->BcBaser->createMailForm($mailMessage, ...)(the first argument is what the controller sets to viewentity)。 - (b) Form-related helpers: each method of v4
$this->Mailform->(hidden/unlockField/submit/error/authCaptcha/end/freezeetc.) strips theMailMessage.prefix from the field name, then,according to the correspondence table in basercms5-theme-development §6 "Mail Form Templates" , convert to BcBaser's mailForm-related API (mailFormHidden/unlockMailFormField/mailFormSubmit/mailFormError/mailFormAuthCaptcha/endMailForm/freezeMailFormetc.). For explicit ids when JS references old ids such as#MailMessageMode, refer to the same section. - (c) BcUpload table specification for file-type fields (important, easily forgotten): if a template with file-type fields (index.php / confirm.php) lacks
setTableToUpload('BcMail.MailMessages')at the beginning, it fails withBcUploadHelper を利用するには … table … を指定してください(BcException) (see basercms5-theme-development §6). element('mail_input')falls back to the core version, so if there is no override in the theme, no action is needed (same §6).- (d) Mail body (email) text template: v4's
element('../Emails/text/mail_data')becomeselement('../email/text/mail_data')in v5 (directory name changed). In the template,$mailConfig['x']has changed from array toentity($mailConfig->x).
F-19. When installed in a subdirectory, image/asset URLs /v5/ are missing (also lurking in external plugins for the 5.x series)
- Detection: Broken image links plus
error.logのMissingRouteException: /files/.... Even in existing "5.x-compatible" external plugins, upload URLs etc. may behardcoded as root-relative, making them incompatible with subdirectory installations. - Conversion: Prefix with the request's webroot (simply passing through
getAttribute('webroot') . ltrim($url, '/')) or, if it is a link URL,\Cake\Routing\Router::url($url)also adds the base. The authoritative source for URL generation is basercms5-theme-development §4 "Assets and URLs". If the upstream project doesn't support this, leave a comment as a local patch and make it a candidate for upstream reporting. - Even for plugins that use the existing 5.x version,don't skip rendering verification in a subdirectorything.
F-22. BcUploadHelper::uploadImage() requires an EntityInterface as the second argument in 5.x (in 4.x it was a filename string)
- Detection:
第2引数に EntityInterface を指定してください。(BcException/500), orgrep -rn "uploadImage('" templates/ src/where the second argument is a string/array value. Frequently seen in templates/helpers that display eyecatch or uploaded images. - Conversion: To
uploadImage('<field>', $entity, ['table' => '<Plugin>.<Tables>', ...])—the first argument is the plain field name (removing the 4.xModel.fieldqualification), the second argument is theentity that has the field, and since BcUploadHelper resolves the table from the View's plugin/name by default, explicitly specify'table'option for the table that has the BcUpload behavior. If the template only has 4.x-compatible array data, fix the supply side (the controller/helper's conversion process) to also pass the original entity along. Old'size'option is'imgsize'。
F-20. Widget elements are 4.x Elements/widgets/(plural) → 5.x templates/element/widget/(singular)
- Detection: The front end exposes "Element template '.widget/xxx' was not found."
BcAddonMigratormigrates the 4.xView/Elements/widgets/(plural) as-is totemplates/element/widgets/, but since 5.x BcWidgetArea looks forelement/widget/(the singular form), the path doesn't match. - Conversion:
templates/element/widgets/→templates/element/widget/rename to (templates/Admin/element/widgets/as well). Converting the contents to 5.x (arrays→entities, etc.) is needed separately. The authoritative source for placement is basercms5-theme-development §5 "Widgets". - ★Don't forget to similarly rename the theme-side override version. If you only fix the plugin side, the theme override (custom design version) won't be used, and it will look like "the design broke" with the plugin's bare template (measured: a card-style ranking became a plain list display).
F-23. For symptoms of the "elements not visible at initial display / layout breaks" type, first compare against the actual production HTML and suspect "extra classes added during migration"
- Detection: Symptoms such as a specific block or list card "not appearing until you scroll" or "the layout breaking" intuitively look like a problem with shared JS (animation control, etc.) or CSS, butWhen migrating to v5, CSS classes that do not exist in production (
fadeinAnime/sideinAnimeanimation-related classes such as these are typical) may have been mistakenly added to the templateand this can be the true root cause. In some cases the shared JS/CSS side has the same specifications as the v4 original, and that itself is not a defect. - Identification procedure (always perform this before suspecting the shared JS/CSS): Check the class attribute of the relevant element in the actual HTML source of the production site (the DevTools Elements panel, or
view-source:), and compare it against the class written in the local/v5 template. If a class that is not present in production is added only locally, that is an extra addition on the template side, and it can be fixed simply by removing it from the template without changing the shared JS/CSS (minimal impact). - ★Pitfall:
WebFetchDo not try to check production HTML with the。WebFetchtoolconverts the retrieved HTML intopassing it to a small model, soclassmost HTML attributes, including the attribute, are lost in this conversion. An answer fromWebFetchsaying "the relevant class does not exist" can be a false negative (actual example: I once almost believed an incorrect "it does not exist" result, and later corrected it after confirming with a DevTools screenshot andview-source:'s actual source). When you want to check whether a class attribute is present, retrieve the raw HTML source withcurl(if permitted), or ask the user for a screenshot of DevTools/view-source:.