Jump to content

The structure of fields and templates


Michal Gancarski
 Share

Recommended Posts

Hi!

I am finally (after months of delay due to other projects) building my first site with ProcessWire. As I delve into documentation and experiment with various settings, I stumbled upon a problem of how to structure the relationship between fields and templates properly. Let's say I will start with establishing a basic structure for blogging. This means at least two templates: for tags/categories and for posts themselves.

I assume each template will have main body text. For posts it will be the content of the article, for tags - a description of a tag. I could approach this in two ways: by creating a general field called, say, "main-body" and adding it to both templates or by creating two separate fields, "post-body" and "tag-body". Their function would be the same but each of them would be used for a different template.

Now, here is my (obvious by now, I guess) question: what are the advantages and disadvantages of both approaches?

Take care!

Link to comment
Share on other sites

Hi Michael, welcome!

As I see it there are no real disadvantages to reusing fields in your various templates. You can even label them differently for each template. Ie: body could be labelled "blog content" in one template and "copy" in another.

It's definitely better practice to reuse fields wherever possible. If you go to your template settings and click on the fields there, you will get a contextual menu where you can modify settings of the field for that particular template.

The only possible scenario I can think of for duplicating similar fields is when you need say two "images" fields in the same template. There may be others but your safe (and it's preferable) to reuse fields until you hit that particular scenario :)

Link to comment
Share on other sites

I try to reuse the fields as much as possible. But don't reuse fields if that doesn't make sense on code level. General ones usually work just fine, like title, summary and body:

<h1><?= $post->title ?></h1>
<p><?= $post->summary ?></p>
<?php
foreach ($post->tags as $tag) {
 echo "<em>$tag->title</em>";
}
// I would say that is much cleaner than having $post->post_body etc...
?>

But don't start doing this kind of things, even if the field would fit in other aspects:

echo $tag->author; // "author" here means tag description...
Link to comment
Share on other sites

One of the little difficulties in recycling fields is with the Textarea/TinyMCE field.

Settings for the TInyMCE configuration are at the field level, so if you want slightly different configurations between uses, then you will have to create different fields.

In the end, it is a question of finding a balance between efficiency and organisation, and quite where that balance point lies is completely up to you!

Joss

Link to comment
Share on other sites

Thank you all! What about performance of queries using PW's selectors? Is there any advantage or disadvantage to one of the approaches? Also, what about comments? I know there is a comments field built into ProcessWire but I was thinking about implementing them using pages for full control over markup and for freedom in displaying them in various contexts using various selectors. Is there a case to be made for creating a separate "comment-body" field, then?

Link to comment
Share on other sites

I just wanted to mention you can reuse fields and change label and descr in the template context.

I would recommend also to reuse aa much as possible and let title summary and body. This also makes it easy to search selectors to use body in all pages instead of multiple.

Theres no advantage in creating new field in evry new context than rather disadvantage. Performancewise I cant see any dis-/advantage.

Regarding comments you can of course use/build your own system very easily with pages. Many done, Ive done it and yes use body everywhere where you need a body. Also if pages are comments.

Sorry am on mobile...

Link to comment
Share on other sites

Greetings,

I think re-using fields makes most sense, as long as the fields are really equivalent from one template to the next (as apeisa says).

With contexts, you can re-use fields and still have them be unique for each template! Thank you for this, ProcessWire!

One advantage I am seeing with re-using fields is that I can regularly create "inc" snippets that can be inserted into different templates that have identical sections (same set of fields). For example, in my current project for an arts organization, they have "events" that fall into several categories. I have separate templates that reference the same core "event" submissions, and using a $pages reference, each of the templates filters the results according to what someone checked off on a check-box (event category), but many other parts are identical across the templates.

Just an example.

Thanks,

Matthew

  • Like 2
Link to comment
Share on other sites

Joss actually emailed me a similar question and I'll duplicate my reply here since it seems relevant:

Performance as it relates to database is really not an issue that one needs to consider much (or at all) when it comes to creating their fields. Most field data in ProcessWire is loaded on-demand. It loads data selectively and only when it needs it. This enables it to be highly memory efficient with large quantities of pages in memory at once. When you have a $page, behind the scenes, none of the page data is actually loaded until you access it. For instance, if you access $page->body, then it goes and retrieves it at that moment (if it hasn't already retrieved it before). MySQL is extremely fast with simple primary key, non-joined selects, and we take advantage of that. What I'm trying to get across is that quantity of fields does not translate to an increase in joins or other factors that would slow the system down.

Where ProcessWire does join data automatically is at page load time is when you check the "autojoin" box on a Field's "advanced" tab. Some fields you know will always be needed with every $page instance, and that's what autojoin is for. Typically, I make my "title" field autojoin, as it is already by default. I've hidden that autojoin option under the Advanced tab simply because most people never need to consider it. The original intentions behind autojoin have become less applicable than I originally thought [with regards to performance], so it's not something that comes up that often.

ProcessWire also uses joins when it performs queries for $pages->find("selector"), and related DB-querying selector functions. It joins all the tables for fields that you query. So if you perform a find for "date>2012-12-19, body*=holidays" then it's going to join the field_date and field_body tables when a value matches. Though it doesn't do this for the purpose of loading the data, only for matching the data. Technically this type of query could be potentially faster if all those fields were in one table. But that doesn't translate to results that matter for us, and doesn't affect the way that you should use ProcessWire. The benefits of our one-table-per-field architecture far outweigh any drawbacks. I put a lot of time into finding the right architecture and balance here when coding ProcessWire 2. Incidentally, ProcessWire 1 did use the one-table approach (all the field data was stored with the page rather than in separate tables) and it was far less efficient with memory, and about the same in terms of performance.

It's better to re-use something like "body" (when possible) rather than create "article_maintext" or other template-coupled variations like that. The reasons for that are for your own benefit. It is less to keep track of, and tends to foster better consistency. It also results in more reusable code and broadens the potential of where the data can be used. Take the example of an on-site search engine, like you see in the upper right corner of processwire.com. If we know that the main text field(s) of most templates has some consistency in their field names (like title and body), then we can write code that doesn't need to know whether something is an article, a press release or a product. We can find all pages that match "holidays" in the text just by doing this:

$pages->find("title|body*=holidays"); 

But if created a separate textarea field for every template, then any code that queries those fields needs to know a lot more about them:

$pages->find("title|article_maintext|pr_maintext|product_maintext*=holidays"); 

While that still works, it doesn't scale nearly as well. This also translates to the code you use to output the results. If you want to show a snippet of the matching text with the search results, you are going to have a lot more fields to consider than just "body".

Now if each of your templates genuinely needs very different settings for each of their main text fields, then of course it's fine to create them as you need them. But in the real world, I think you draw more benefit by planning for reusability when possible. The benefits are for you (the developer), as it doesn't matter much to ProcessWire. Reuse fields where it's obvious that the name of the field makes sense in the context of multiple templates. If template "employee" needs a date_of_birth field and template "press_release" needs a date_publish field then just create one field called date and use it on both templates. On the other hand, if you need multiple date fields on the same template (like date_unpublish) then more specific field names start to make sense. In that case, I would usually use my date field for publish date, and create a separate date_unpublish field for my unpublished date field. Though some may prefer to actually have separate date_publish and date_unpublish fields because they are obviously related by name.

Ultimately, use what works best for you, but always keep an eye out for obvious reusability potential with fields. I think that most people naturally arrive at the right balance for their needs after some experimentation. What is a best practice for one need might not necessarily be for another. So these are mostly general purpose guidelines and people should find what makes the most sense in their context. For the majority of cases, I think avoiding tightly coupled template and field names is a better strategy.

TL;DR: It doesn't matter to ProcessWire what you do. Aim to reuse fields when you can and when it makes sense, for your benefit.

  • Like 22
Link to comment
Share on other sites

Joss actually emailed me a similar question and I'll duplicate my reply here since it seems relevant:

And I have emailed back to Ryan an even longer article version of what he wrote to me .... but I will spare you all that for the moment :) (Just in case I got it really, really wrong...)

Link to comment
Share on other sites

Hey Ryan,

Thanks for the input. As you mentioned, through experimentation I naturally came to see the benefits of re-using fields. I'm glad to know that even if fields are re-used it does not affect performance. But as you said, there are other benefits to re-using fields.

For my first couple of tests with ProcessWire, I re-created fields for each template. I did that because I needed, for example, different descriptions for text fields in each template. But then I realized that I could get template-specific descriptions using a different (more efficient) technique, and I "collapsed" all similar fields into one that gets re-used across templates. Then, when I turned my attention back to my template PHP files, I naturally discovered that templates for various content types could be easily copied and re-used because they referenced similarly-named fields.

This is great. We know that re-using is not necessary, but we know the benefits of doing it.

Thanks,

Matthew

Link to comment
Share on other sites

@Ryan,

This was very informative. I am more and more excited about building this website with PW, even if I could probably have it up and running much faster with Wordpress (due to experience I have with it). I hope it will let me take on more complex projects as I have already hit some unconvenient limits with Wordpress I would prefer to avoid in the future.

Thanks!

  • Like 1
Link to comment
Share on other sites

  • 3 months later...

Joss actually emailed me a similar question and I'll duplicate my reply here since it seems relevant:

Performance as it relates to database is really not an issue that one needs to consider much (or at all) when it comes to creating their fields. Most field data in ProcessWire is loaded on-demand. It loads data selectively and only when it needs it. This enables it to be highly memory efficient with large quantities of pages in memory at once. When you have a $page, behind the scenes, none of the page data is actually loaded until you access it. For instance, if you access $page->body, then it goes and retrieves it at that moment (if it hasn't already retrieved it before). MySQL is extremely fast with simple primary key, non-joined selects, and we take advantage of that. What I'm trying to get across is that quantity of fields does not translate to an increase in joins or other factors that would slow the system down.

....

[stripped]

What a great post this was by the way...

Edited by Soma
stripped quote to keep things short (there's people on mobile)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...