getkirby / ideas

This is the backlog of ideas and feature requests from the last two years. Use our new feedback platform to post your new ideas or vote on existing ideas.
https://feedback.getkirby.com
20 stars 0 forks source link

Ability to create a default page model #556

Open fvsch opened 4 years ago

fvsch commented 4 years ago

Page Models are IMO a better construct than custom page methods, but models always applying to a single page type can be frustrating. Would it be useful to have a built-in mechanism for defining a page model that applies to all classes?

I’ll try to explain my concern with page methods, what I’m doing with page models and how it might be improved with built-in support. It makes this post a bit long, which I apologize for in advance.

Custom page methods vs. page models

Page methods have a few downsides:

  1. You need to declare a plugin, which feels a bit awkward when it's part of the "core" features of your site or theme. You have to pick a plugin name ('projectname' doesn't work, you need 'somenamespace/projectname'), copy-paste or write some boilerplate code.
  2. They’re closures that rely on the $this object to access the page object, and editors cannot know what $this refers to and provide completions and validation.
  3. They can't override methods of the Page class, and when you try to do it, it fails silently.

They’re a bit hidden away in the "Reference > Plugins" documentation, compared to Page Models which are described more proeminently in the Guide. The page methods docs also compares page models and page methods:

Custom page methods vs. page models

Page models are a great way to create an extended version of the default page object with additional methods and functionalities. But a page model is tied to a specific template, while custom page methods apply to all page objects. If your use case is based on one specific template, a page model might be the better solution. If you have methods that should be available for all page objects in all templates, a custom page method is the way to go.

For these reasons, I tend to favor Page Models:

  1. Easier to create (less boilerplate)
  2. Good typing/intellisense support!
  3. And the ability to override a parent method if need be.

The only downside is that when you do want to add a method to all page types, you need to go back to plugin page methods.

A workaround for a 'base' page model

One way to share functionality between page models is to use class inheritance.

<?php // site/models/common.php

class CommonPage extends Page {
  // some methods here
}
<?php // site/models/article.php
require_once 'common.php';

class ArticlePage extends CommonPage {
  // other methods here
}
<?php // site/models/product.php
require_once 'common.php';

class ProductPage extends CommonPage {}

This works well and fixes all the issues mentioned before, but introduces two new issues:

  1. We have to explicitly require site/models/common.php (which can live anywhere)
  2. If we want the CommonPage methods to be available for all page types, we have to create a page model that extends CommonPage for every single page type, even if it's an "empty" one (like ProductPage in this example). In setups with half a dozen page types or more, that can be verbose.

A built-in way to have a "base" or "default" page model?

Kirby has fallback mechanisms for:

I propose introducing a fallback or "default" mechanism for page models as well.

For instance, Kirby could:

  1. autoload site/models/default.php
  2. then, for a page whose intendedTemplate is 'article', look first for an ArticlePage class then for a DefaultPage class.

Developers could then decide to:

Downside: that's a bit magical. But the way page models are loaded and defined (with conventions for file names and class names) is already a bit magical, this would fit the current model and using 'default.php' as a fallback has some precedent with templates.

I wouldn't give plugins an explicit way to define a 'default' page model though. Doesn't feel right, but I haven't thought about it much.

What do you think? Good idea? Too complex or too magical?

lukasbestle commented 4 years ago

I love the idea and I think that it's completely obvious that we should have that.

The reason why you don't like page methods is that page methods and page models are made for two completely different use-cases:

So again: It makes a lot of sense to add support for default models.

Regarding a few details:

autoload site/models/default.php

We wouldn't be able to call it default.php as that's already the model for the default template (which is why the default controller is called site.php).

However we also won't be able to call it site.php as that should be reserved if we at some point decide that we should have support for a site model (i.e. a custom class extending the Kirby\Cms\Site class).

So naming is a bit difficult here.

I wouldn't give plugins an explicit way to define a 'default' page model though.

Every part of Kirby that can be configured from the site directory (except the config options themselves) can also be configured from plugins. I think we should do it like this here as well. Plugins always have the power to do weird things anyway, so it's the responsibility of plugin authors and users to use the features properly. I can see use-cases where a global default model defined from a plugin could make sense.