Skip to content

super<name> originals are only registered for model overrides — controller/view helper overrides get no superLinkTo() #3325

Closed

Description

@bpamiri

Context

Discussion #3323: a user followed the v3 guide Overriding Core Methods, overrode linkTo(), and called superLinkTo() — HTTP 500, because that function never exists in controller/view context.

Root cause

The super<name> convention is implemented asymmetrically:

vendor/wheels/Model.cfc → $integrateFunctions() (~line 598) — when the mixin method name already exists on the target (i.e. the app overrode it), the else branch registers the framework original as super<name>:

if (!(StructKeyExists(variables, local.name) || StructKeyExists(this, local.name))) {
    variables[local.name] = local.ref;
    this[local.name] = local.ref;
} else {
    local.superName = "super" & local.name;
    variables[local.superName] = local.ref;
    this[local.superName] = local.ref;
}

vendor/wheels/Controller.cfc → $integrateFunctions() (~line 400) — no else branch. super<name> is only registered when a registered plugin/package mixin overrides the name (overrideSet). App-level overrides of controller/view helpers (defined in app/controllers/Controller.cfc or app/views/helpers.cfm) silently get nothing.

vendor/wheels/Mapper.cfc has its own $integrateFunctions() variant (~line 403) — worth checking for the same gap while in there.

Repro (verified live on develop, Lucee)

  1. In app/views/helpers.cfm define an override:
    public string function linkTo() {
        return superLinkTo(argumentCollection = arguments);
    }
  2. Render any view that calls linkTo() → error, superLinkTo is undefined.
  3. StructKeyExists(variables, "superLinkTo") in the view returns false. The equivalent model-side override does get superFindAll() etc.

Proposed fix

  1. Add the same else branch to Controller.cfc::$integrateFunctions() (and Mapper.cfc if applicable) so controller/view overrides get super<name> parity with models. ~5 lines + a spec.
  2. Docs: the v3 guide presents the convention as general (it is model-only today), and the v4-0-0 guide tree has no "Overriding Core Methods" page at all — port + correct it once the parity fix lands.

Workaround for users today

Capture the original reference manually (late-binding — same trick $integrateFunctions itself uses); posted in #3323:

variables.coreLinkTo = CreateObject("component", "wheels.view.links").linkTo;

Activity

  1. added 4 commits that reference this issue on Aug 4, 2026
    05dffaf
    c8f3213
    2072eb3
    47aeb9f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions