Overriding core block controllers in theme

So, we noticed customizing block views is possible from within our theme. We promptly moved our application/blocks stuff into application/themes/client/blocks to keep the customization contained closer together. But then, there’s the odd block that’s been customized all the way down to the controller level and the namespaces like Application\Block\SwitchLanguage from before aren’t working anymore. I thought our page_theme.php’s Application\Theme\Client namespace was a clue and tried Application\Theme\Client\Block\SwitchLanguage but it doesn’t look like that’s helping either.

Anybody have any ideas on what I might be missing, or should this just not be attempted?

For view/template overrides, Concrete lets you place block files inside your theme so the presentation stays with the theme. But for a controller override, Concrete expects it to behave like an application-level block override, with the namespace matching the application/ path pattern, not the theme namespace. The docs show custom controller overrides living in application/blocks/<block_handle>/controller.php with a namespace like Application\Block\Search, extending the core controller

I generally put all my themes in a package. Then you can do exactly as you have mentioned and have them all in one neat place.

1 Like

Thanks. I had a feeling that would be the case. We shall revert the change for controllers and possibly try the package approach on the next site.

If you go the package way you can override a core block’s controller using the container and binding it to your custom controller.

Here’s an exemple with the core Content block. In your package’s controller on_start() method you can write:

app()->bind(
    '\Concrete\Block\Content\Controller',
    '\Namespace\For\Your\Own\Controller'
);

Just a few things:

  • I’m assuming you’re using Concrete 9. If you’re using Concrete 8 replace app() with $this->app
  • It is not a good idea to override the whole controller. Much better to override only the minimum you need and make your custom controller expand the core one.
  • In Concrete 8 I could use Controller::class in the bind instead of the whole classname. But, for whatever reason, in Concrete 9 it didn’t work unless I did it the way above. It might have been fixed since.
  • Concrete has an override cache and you might have to empty your cache the first time to see this work.

I hope it helps.

Thanks for the additional pointers. I try to keep things up-to-date and lean, so I mostly deal with v9 and the usual need for controller modification is to add some detail or custom logic to view() so that’ll be about the only thing I extend on the original.