So, I have set up my new Kirby 4 version of an existing site and added comments to my blog posts. Everything is done, the registration and login forms. The form on the page to accept comments is also done.
But here is where I am hesitating, and that is where to put the comments. I see three options.
Store the comments on the blog page itself.
Store the comments in a new page within each post folder called comments.txt
Store all comments in a single page.
One seems reasonable; all comments are stored on the same page as the blog post, and everything is contained on one page.
Three is probably the worst option, as it will undoubtedly be the slowest option if many comments get added over time.
I am asking because I think two will be the most commonly suggested approach, and I am edging towards one. I don’t know what I am missing, if anything, as to why I should go for one and not two.
Any views are appreciated. I want to get it right first time
I’d go with option 2, i.e. a subpage for comments, probably even subpages for each comment. Especially with many comments, subpages would be the better option. If you go with this option, you should have a route in place or add templates that prevent direct access to the comments page and its children.
If they are separated from your page content, this cannot be messed up by many attempts to store something in the page at the same time.
Another option you did not list above would be to store comments in a SQLite database.
Thanks, @texnixe, that makes sense. I can see how that would be an issue, especially on the multiple attempts to store something causing page locks.
I did consider SQLite but didn’t want to go with that as, on this site, the number of comments will be little enough that a DB wouldn’t be justified. If I were going to use it for more than just comments, that would likely be a better option. Or maybe I should do that to solve the potential for page locking.
In honesty, I am implementing this as proof it works, as my next project will need it, and that page-locking issue may be far more likely.
SQLite generates just a file with a special file format and is installed on most systems, so not a huge database, and fits Kirby very well, in my opinion. Also used by the Retour plugin, for example. Just something to consider when you have many comments, for everything else, I’d go with the file system storage but consider single subpages per comment.
I am trying the comment-per-page option. I have got it all working as a rough design. Each page is being created correctly, but it’s storing all the comments in the _drafts folder. What have I missed?
In my controller:
return function($page, $pages)
{
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$text = get('comment');
if ($text) {
$author = null;
// Check if a user is logged in
if ($user = kirby()->user()) {
$author = $user->username();
}
$page->createChild([
'slug' => 'comment-' . time(),
'template' => 'comment',
'content' => [
'author' => $author,
'text' => $text,
],
'num' => $page->children()->count() + 1,
'status' => 'listed',
]);
go($page->url() . '#comments');
}
}
};
The comments are all listed as expected; see the screenshot below. Just in the wrong place.
A newly created page is by default in the _drafts folder. However, I think it would be better to create a new parent folder comments within each article folder, then within this comments folder, create the comments.
To publish the comments, you can
Make this a manual process, so that comments need to be reviewed before they are published. You will usually get a lot of spam, so IMO, this is the best option.
Auto-publish the comments, by setting the draft option to false in the createChild method.
Thanks, I reworked the code to create a comments folder; of course, I already have a couple of hundred posts, so I need to check and create first if it does not exist.
There is still some work to do, but everything works as expected. I can now tidy it all up. Thanks as always for your help, @texnixe.
<?php
return function($page, $pages)
{
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$text = get('comment');
if ($text) {
$author = null;
// Check if a user is logged in, may not need this, check already done before you can see the form on the blog post.
if ($user = kirby()->user()) {
$author = $user->username();
}
// Check if the comments folder already exists (hundreds of existing posts at this point), if not then create it.
$commentsFolder = $page->find('comments');
if (!$commentsFolder) {
// Create the comments folder from template
$commentsFolder = $page->createChild([
'slug' => 'comments',
'template' => 'comments',
'content' => [
'title' => 'Comments',
],
'num' => 1,
'status' => 'listed',
'isDraft' => false,
]);
}
// Now create a new folder inside the comments folder for each comment made.
$commentsFolder->createChild([
'slug' => 'comment-' . time(), // need something better than this. do it like other pages
1_comment, 2_comment etc..
'template' => 'comment',
'content' => [
'author' => $author, // Can only comment if logged in so $author is always a
registered user.
'text' => $text,
],
'status' => 'listed',
'isDraft' => false,
]);
// redirecting back to the comments section on the page.
go($page->url() . '#comments');
}
}
};
Sorry, I do not understand the documentation on this.
If my blog post blueprint contains nothing but:
title: Blog Single Post
sections:
drafts:
label: Drafts
type: pages
status: draft
templates: product
published:
label: Published Products
type: pages
status: listed
templates: product
pages:
label: Main Pages
status: all
I see the following on the page. The child page called comments
And if I click on that, I get what I expect: a list of all comments that can be displayed, edited, and so on.
But I can’t combine any of the above with the existing blueprint, and I can’t seem to get the comments pages to display simultaneously with the existing fields needed for the blog post. Confused.
I think you are missing some basics how to create blueprints with fields and sections…
To mix fields and sections, your fields need to go into a section as well:
title: Blog Single Post
sections:
fields:
type: fields
fields:
postImage:
label: Post Image
type: files
date:
label: Date
type: date
width: 1/4
# more fields...
comments:
type: pages
label: Comments
parent: page.children.find('comments')
layout: list
template: comment
You might want to use columns or tabs to clean this up a bit.
As regards the comments parent page, it might make sense to auto-create this page when a new article is created, see Subpage builder | Kirby CMS, because the above section will throw an error when this page doesn’t exist yet.
Oh damn… It was this bit below I wasn’t getting, missed the need to do part of this. Sorry, @texnixe will need to spend a bit more quality time with the blueprints; never had to stretch further than a really basic approach until now.
So I thought everything was done, but I have come across a final issue I can’t figure out.
When creating a blog post, everything works as expected until I try to upload an image/file. Then I get this.
Here is my blueprint
title: Blog Post
sections:
fields:
type: fields
fields:
postImage:
label: Post Image
type: files
date:
label: Date
type: date
width: 1/4
category:
label: Category
type: select
options:
News: Industry News
Mortgages: Regulated Mortgages
Buy To Let: Buy To Let
Interesting Property: Interesting Property
Regulation: Regulation
Valuations: Valuations
Taxation: Taxation
Questions: Questions
General: General
Guides: Guides
width: 1/4
featured:
label: Featured post?
type: checkboxes
options:
feature: Feature
width: 1/4
postTags:
label: Post Tags
type: tags
width: 1/4
pageSummary:
label: Page Summary
type: textarea
size: small
width: 2/3
pageFiles:
label: Page Files
type: files
width: 1/3
text:
label: Text
type: textarea
size: large
width: 2/3
gallery:
label: Gallery
type: files
layout: cards
width: 2/3
comments:
type: pages
label: Comments associated with this blog post
parent: page.children.find('comments')
layout: table
columns:
date: true
author: true
text: true
width: 1/2
template: comment
The way I have set the page up is only to create a folder for comments on the first comment made on each post. Seems sensible. Anything I do to the post will save it, and it updates fine. Only when I try to add a file does it break with the error message above?
It’s related to not having a comments folder; if I create a comment and then try to upload a file, it’s fine.
Any pointers. I guess I need something that says ignore the query if there are no comments.
I am too busy looking at pages with comments, which, of course, look fine. I see this when I look far enough down on a page with no comments. Not paying attention!
But yes I got your previous comment about it throwing an error and I can of course create, maybe I should just mass create it for all the existing posts as well to fix this?
Yes, when uploading a postImage. I was confused and interested to understand why it had an issue only when uploading. No error message if you complete any other field and save, updates fine and no complaints about the query.
@texnixe. Apologies, I need a bit more help with this. Thinking it through, I need to create a child of blog posts called comments when a new blog post is created. I need the comments folder to be created before uploading an image, or the error will appear.
So is the best option to use a hook with page.create:before to achieve this or a different method?