Skip to content
This repository has been archived by the owner. It is now read-only.

Ability to create a default page model #556

Open
fvsch opened this issue May 31, 2020 · 1 comment
Open

Ability to create a default page model #556

fvsch opened this issue May 31, 2020 · 1 comment

Comments

@fvsch
Copy link

@fvsch fvsch commented May 31, 2020

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:

  • Templates: use site/templates/default.php (required)
  • Controllers: use site/templates/site.php (optional)

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:

  • create a DefaultPage class or not;
  • make their other page models extend Page or extend DefaultPage, depending on whether they want to inherit methods from DefaultPage or not.

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?

@fvsch fvsch changed the title Ability to create a default page model? Ability to create a default page model May 31, 2020
@lukasbestle
Copy link
Member

@lukasbestle lukasbestle commented Jun 1, 2020

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:

  • A page model is primarily meant to be specific to the site and custom-built by the developer for the requirements of the particular site. That's why it can be defined directly in the site/models directory without having to use a plugin.
  • The use-case for a page method is just a plugin use-case: Basically you want to define a method from your plugin that should be accessible from everywhere, but without breaking custom page models of the site. Also, it should be possible to create different page methods from multiple plugins (which wouldn't be possible with models as there can only be one model class per template). They are not meant for building custom methods for your site, only for plugins. This is why they can only be defined from plugins.

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants