Skip to content

Conversation

@datamweb
Copy link
Contributor

@datamweb datamweb commented Dec 30, 2025

Description
This PR adds the ability to override namespaced views (typically from modules or packages) by placing a matching file structure within the application's local app/Views directory.

Screenshot 2025-12-30 101231

See : https://forum.codeigniter.com/showthread.php?tid=93684&pid=427797#pid427797

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@neznaika0
Copy link
Contributor

It looks good for modules. Questions:

  1. What happens if NS is specified as \Example\Blog\Views\blog_view? Contains Views.
  2. Is there a possible collision when NS exists, when the View expects a template from the module modules/Example/, and outputs it from the app/Views ?

@datamweb
Copy link
Contributor Author

  • What happens if NS is specified as \Example\Blog\Views\blog_view? Contains Views.

CodeIgniter will look for: app/Views/Example/Blog/Views/blog_view.php. If the user explicitly includes Views in the call string, they should act accordingly in their override directory structure.

2. Is there a possible collision when NS exists, when the View expects a template from the module modules/Example/, and outputs it from the app/Views ?

Yes, if a file exists in the matching path within app/Views, it will take precedence over the module's file.
This collision is actually the intended behavior (the Override). Since the app/Views directory is user-controlled space, we assume that if a developer creates a directory structure matching a namespace (e.g., app/Views/Example/Blog/), they explicitly intend to override that modules/packages view. It is highly unlikely for such a specific directory structure to exist accidentally.
In any case, this is entirely under the developer’s control and can be managed.

@michalsn michalsn added enhancement PRs that improve existing functionalities 4.7 labels Dec 30, 2025
Copy link
Member

@michalsn michalsn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether we should add a configuration option for this, allowing users to disable the functionality. The chances of this breaking existing code are small, though.

As for the difference between view('Example\Blog\blog_view') and view('Example\Blog\Views\blog_view'), this is a module developer's decision. We should not attempt to manipulate or normalize it, as that could lead to issues when developers choose more complex or non-standard folder structures.

Co-authored-by: Michal Sniatala <michal@sniatala.pl>
@datamweb
Copy link
Contributor Author

I'm not sure whether we should add a configuration option for this, allowing users to disable the functionality. The chances of this breaking existing code are small, though.

We could technically add a flag to app\Config\View.php to toggle this behavior. However, I personally believe it is unnecessary. Since this logic only triggers when a user deliberately creates a matching directory structure in app/Views corresponding to a specific namespace, the probability of an accidental collision is extremely low.

As for the difference between view('Example\Blog\blog_view') and view('Example\Blog\Views\blog_view'), this is a module developer's decision. We should not attempt to manipulate or normalize it, as that could lead to issues when developers choose more complex or non-standard folder structures.

Exactly. The current implementation intentionally avoids any magic stripping of segments like Views. It performs a direct 1-to-1 mapping of the namespace string to the directory path. This ensures predictable behavior regardless of how the module developer structured their views.

datamweb and others added 2 commits December 30, 2025 23:05
Co-authored-by: Michal Sniatala <michal@sniatala.pl>
Co-authored-by: Michal Sniatala <michal@sniatala.pl>
$this->renderVars['file'] = $this->viewPath . $this->renderVars['view'];

if (str_contains($this->renderVars['view'], '\\')) {
$this->renderVars['file'] = $this->viewPath . ltrim(str_replace('\\', DIRECTORY_SEPARATOR, $this->renderVars['view']), DIRECTORY_SEPARATOR);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not accurate, we can add a directory to app/Views: _modules, share,.. to explicitly separate the overwritable templates. As app/Views/share/Example/Blog/blog_view.php.

There is unlikely to be an NS with such a shared\Example\Blog value, so it looks safer. If desired, this folder can be customized. The auto-selection of the search should remain.

@neznaika0
Copy link
Contributor

I've been trying modularity for a long time and working with templates is causing problems. I would not like to develop templates for Bootstrap when the global project theme is written in TailwindCSS. This feature seems to solve this problem - I don't need to create templates for the module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.7 enhancement PRs that improve existing functionalities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants