silverstripe / silverstripe-framework

Silverstripe Framework, the MVC framework that powers Silverstripe CMS
https://www.silverstripe.org
BSD 3-Clause "New" or "Revised" License
721 stars 821 forks source link

RFC: Template prefix shortcut #5956

Closed chillu closed 3 months ago

chillu commented 8 years ago

There's been a lot of discussion about namespaces in templates (https://github.com/silverstripe/silverstripe-framework/issues/5445, https://github.com/silverstripe/silverstripe-framework/issues/5952).

One goal is to retain ease of use for template developers who might not be as familiar with PHP namespaces, or the SilverStripe theme "cascade". @sminnee suggested namespacing mapping similar to PSR-4. I've discussed this with him, and we agreed that this might be overcomplicating for little gain.

As an alternative approach, we're suggesting a template control to avoid repeatedly writing a template "namespace" in <% include %> statements.

templates/
  Some/
    Namespace
      MyFile.ss
<!-- Before -->
<div>
<% include Some/Namespace/MyFile %>
</div>

<!-- After -->
<% template_prefix Some/Namespace %>
<div>
<% include MyFile %>
</div>

It's specifically not called a namespace, since the mental model here should be the folder path. The theme "cascade" means there might be multiple versions of this file in different "base" folders. But you can add *.ss to any of these references and have the end of a file path.

This will only make code less verbose if you have multiple <% include %> statements in a single template, or if you create a template boilerplate to avoid mistakes by template developers

flamerohr commented 8 years ago

Would this logic flow down if template_prefix was called somewhere below? Or like namespacing it is only one per file?

If one per file, would the template_prefix have to be at the top of the Template file?

e.g.

<% template_prefix Some/Namespace %>
<div>
<% include MyFile %>
</div>
<% template_prefix Another/Namespace %>
<div>
<% include DifferentFile %>
</div>
sminnee commented 8 years ago

I'd probably say that it is allowed once per file and applies globally. If you provide two it's a compile error.

If we wanted to use different prefixes in different parts of the file then I'd probably suggest a <with_template_prefix > ... < end_with_template_prefix > style block, but to be honest I think it's overkill.

sminnee commented 8 years ago

If you want to ignore the prefix, start your template name with /

assertchris commented 8 years ago

An alternative: <% prefix SilverStripe/Admin %><% end_prefix %>.

sminnee commented 8 years ago

The use case that led to recommending this feature is where you have the classes & templates from your module or project all contained within a namespace, and you want to avoid listing that namespace on every <% include %> tag.

I'm can't think of a use case where you would be chopping and changing includes from different namespaces so much that multiple prefix entities are desirable.

Can anyone think of such a use-case?

flamerohr commented 8 years ago

The most common use case for changing Includes prefix would be trying to include an extended/parent Classes' Include template.

Where the desire is to only change one part of the entire template.

assertchris commented 8 years ago

The use case that led to recommending this feature [snip]

In that case, my personal preference is not to be able to set it from within the template, but rather at a Controller/SS_Viewer level.

sminnee commented 8 years ago

The problem with that is then you've have to open up the Controller to know how to interpret your template file. I'd rather be able to understand the meaning of the template file independently.

EDIT: I guess the benefit is that you would be able to move closer to a point where templates were able to "ignore namespaces" and in that sense be simpler. The responsibility of shielding the template designer from the potential for namespace conflicts would go to the person who write the controller.

Given Ingo's dismay at the complexity we were introducing, this might be worth some more thought.

SpiritLevel commented 8 years ago

What about being able to define multiple short aliases at the top of the file as abbreviations for lengthy template paths?

<% template_prefix aliasA Some/Template/Path %>
<% template_prefix aliasB Another/Template/Path %>
...
<% include aliasA/SomeTemplateFile %>
...
<% include aliasB/AnotherTemplateFile %>

Simple, intuitive, all contained in the template file...One would have to make the aliases local to each file somehow to avoid clashes (ie: in case, say, the alias aliasA is also defined in an included template) but this and the parsing of the argument shouldn't be too difficult.

sminnee commented 8 years ago

We were trying to keep it simple, and recognise that the target audience of templates are HTML/CSS developers not PHP developers. Without a clear use-case for multiple aliases I'm disinclined to include it in the initial implementation.

Note that my expectation is that we'd process the aliasing at template-compile time, which is per-template.

chillu commented 8 years ago

I think even the "single alias" use case might only be applicable to maybe 10% of projects (where multiple include statements justify it). I can't think of a project I've worked on that would've benefitted from multiple aliases (e.g. including my own project templates and at least one other module template sources). Take silverstripe.org's forum module use for example: We would've overloaded pretty much any template from forum/templates anyway in themes/ssorg

kinglozzer commented 8 years ago

The point about overloading templates from other modules is a good one, how do the template changes for SS4 affect that? Let’s say we include the blog module which has a template blog/templates/SilverStripe/Blog/BlogList.ss. If I want to override that template in my theme, do I have to create themes/mytheme/templates/SilverStripe/Blog/BlogList.ss? I don’t think it would be any harder to learn & write “namespaced” includes than it would be to get used to that template structure.

sminnee commented 7 years ago

From the looks of things, this can be implemented without breaking APIs. I'm downgrading to change/minor.

chillu commented 5 years ago

Bumping this to impact/high since "namespaced templates" seems to be the number one pain point from talking to a few devs at meetups.

michalkleiner commented 5 years ago

Wow, it's been around for 18 months already.

As @chillu mentioned, it's a massive pain. We started organising our includes differently, not following the actual class names but rather more compartmentalising. For template overrides it needs to be namespaces.

Our main points:

On the other hand, opening and closing a prefix scope for two includes is roughly the same amount of writing, so not sure which way we'd go.

Potentially, it might be confusing for devs seeing two includes somewhere in the middle of the file, not noticing the prefix scope change, subsequently having troubles locating the files, until realising what's going on.

sminnee commented 5 years ago

Instead of nested scopes you could also do aliasing:

<% prefix Some/Namespace %>
<% prefix Another/Namespace as B %> (or "<% alias Another/Namespace as B %>"?)

<% include MyFile %> <!-- Some/Namespace/MyFile -->
<% include B/OtherFile %> <!-- Another/Namespace/OtherFile -->
<% include B %> <!-- Another/Namespace. A bit weird, but listing here to clarify semantics  -->

In the example above, it would be impossible to include Some/Namespace/B. Do do that you, you would need to choose a different alias.

michalkleiner commented 5 years ago

Ok, with that, could we make it a yaml configured map so it doesn't need to be at the beginning of all template files, repeated possibly tens of times?

GuySartorelli commented 3 months ago

I don't think this is worth proceeding with, it would have made sense back when namespaces were introduced but they've been around for so long now that I think this doesn't provide enough value to outweigh the implementation and maintenance cost.

In addition to that, I agree with this statement:

Potentially, it might be confusing for devs seeing two includes somewhere in the middle of the file, not noticing the prefix scope change, subsequently having troubles locating the files, until realising what's going on.

Adds additional confusion, adds maintenance burden, and ultimately is only beneficial in a small handful of cases. I'm gonna close this, but if someone has a really good argument for it and is willing to put in the work to implement it, we can consider reopening.