4

I've been reading on here about suggestions on implementing commenting systems. I'm aware of disqus integration but I want/need built in commenting.

I have seen it mentioned a couple of times that one approach would be to create a section (presumably a channel) dedicated to comments and the relate that to an entry via an entries field.

I just can't quite wrap my head around how that works out. Do the entries have to be manually selected in order to relate them?

If anyone's built something like this then I would love to know how they tackled it!

One thing to add is that only registered members will be commenting. And there would be several different sections needing comments.

Thanks!

shorn
  • 438
  • 2
  • 9

3 Answers3

8

One approach would be to create a comments channel with an entries fieldtype (with sources checked for any channels that you want to allow commenting; limit set to 1) called 'relatedEntry' (or whatever you like). On your article template, include a for loop to display existing comments relateTo the entry. Check to see if there is a current user, and if yes, include a comments form. In the comments form place a hidden field with the id for the current entry. Something like this:

<article>
  {{ entry.title }}
  {{ entry.body }}
</article>

<ul class="comments">
{% for comment in craft.entries.section('comments').relatedTo(entry) %}
   <li>{{ comment.author.fullName }}<br/>{{ comment.body }}</li>
{% endfor %}
</ul>

{% if currentuser %}
<form method="post" action="" accept-charset="UTF-8">
    <input type="hidden" name="action" value="entries/saveEntry">
    <input type="hidden" name="sectionId" value="2">
    <input type="hidden" name="redirect" value="{{ entry.url }}">
    <input type="hidden" name="fields[relatedEntry][]" value="{{ entry.id }}">

    <label for="comment">Comment</label><br/>
    <input type="text" name="comment">
</form>
{% endif %}

name="fields[relatedEntry][] is formated this way because related fields expect an array even if it's only a single related entry.

You could also create threaded comments by creating another related entries fieldtype called parentComment (or whatever you like) and including that as a hidden field in the form as well (you might need ajax or javascript here to help set the hidden field value from the 'comment' link).

To make it a little nicer you could also load the comments form via ajax or reveal it with javascript.

Untested, but hopefully this will point you in the right direction.

Douglas McDonald
  • 13,457
  • 24
  • 57
  • This is brilliant. That's helped me get my head around it a bit better. I was (wrongly) thinking of how an entries field within the main entry rather than the comment section. I'm going to have a play tonight and test it out. As you mentioned, my aim would be to get the comments loading in via Ajax and somehow prevent the need for a page refresh, but that's refinement once I've got the basics in place. Will update once I've had a chance to test! – shorn Oct 06 '14 at 09:50
  • I've ticked this as an answer but to be honest both answers here have helped. I have just got this up and running, and it's working pretty well. I have just two questions though. Should I set the comments section to have there own URLs? and also, I'm wondering what the best approach for generating the title of the comment entry is? I only want to present a single textarea and not have any other fields so auto generating one might be the best bet, but I'm open to suggestions as to the best way to set them up? – shorn Oct 06 '14 at 14:36
  • You don't really need to have URLs for the comments channel unless you plan to have a template to view the comments separately from the article. And the title doesn't really matter. The title would just be there for you to identify it in the Control Panel. You could use something like {{ postDate|date("m/d/Y H:i") }} or {{ relatedArticle[0].title }} or {{ relatedArticle[0].author.fullName }} or some combination. – Douglas McDonald Oct 06 '14 at 15:20
  • 1
    Thanks for that. I'm not planning on templating the comments separately but I guess it wouldn't hurt to generate a URL to future proof against potentially needing/deciding to in the future. Trying to think of what would be the most useful title for the CP. I tried your suggestion of {{ postDate|date("m/d/Y H:i") }} which works fine, but I'm not sure how {{ relatedArticle[0].title }} breaks down. I presume it should output the main entrys title, but can you explain the 0 within the [] as I'm not sure what that does. (New to Craft) Thanks again! – shorn Oct 06 '14 at 17:51
  • Related entries are always an array, even if there is only one. And since we know that there is only one related entry because (hopefully) a limit of 1 is set in the field settings, we can reliably assume it is the first entry with an index of 0. – Douglas McDonald Oct 06 '14 at 18:18
  • That makes sense, but when I add it to my auto title, nothing gets outputted. The date is generated but the title is not? – shorn Oct 06 '14 at 20:10
  • My mistake... use { relatedArticle.first.title } – Douglas McDonald Oct 06 '14 at 20:30
  • Doh! Think I was having a moment. My entries field is relatedEntry rather than relatedArticle so I now have this {relatedEntry[0].title} - {author} and it outputs the main entry's title together with the comment authors username. Seems to work fine! – shorn Oct 06 '14 at 20:30
  • Great! Guess either one works then. – Douglas McDonald Oct 06 '14 at 20:32
  • Yep, tried both and both work. Thanks for your help on this. Really helped me along, and it's much appreciated! – shorn Oct 06 '14 at 20:33
  • Hey @DouglasMcDonald, I'm just in the process of using this method for adding comments to entires and I've got it working, but I have one issue as I have more than one comment type field within the related entry, so if the user completes one of the fields one time and then goes back and completes the other comments field(s) it creates another entry.

    Is there anyway around this? Does it even make sense?

    – richardpixel Jan 05 '16 at 18:06
  • @richardpixel - I'm not sure what you mean. What two comment fields do you need? Can you provide an example? Wouldn't both fields be part of the same comment? I.e. if the user went back and submitted the form again, wouldn't you want this to be it's own comment/entry? You could also potentially allow the ability for a user to edit (or in this case complete) their own comment by adding an edit button (and ajax loading a form preloaded with their previous field entries). – Douglas McDonald Jan 06 '16 at 19:34
  • @DouglasMcDonald Thanks for your reply but I've just figured it out. What I needed to do was set a variable in my template to the related comments of the current user and then add that as a hidden field in the form, plus fill the comments fields with any previously entered content. – richardpixel Jan 07 '16 at 10:55
  • @richardpixel glad you got it sorted! – Douglas McDonald Jan 08 '16 at 17:43
6

I've used this method before, works quite nice!

The way to do this:

  • Create the fields you need for commenting (name, message, etc.). Be sure to add a relational field to which you can later assign the 'parent entry'
  • Create a section (channel) called comments (or whatever else you want to call it)
  • Assign the fields to the section you just created
  • Use a frontend entry form for commenting. The sectionId is the id of the comments section, the action is 'entries/saveEntry'.
  • Create a hidden input field, with the name of your relational field and assign the id of the 'parent entry' to it. Don't forget to add fields and []. Fields because it's not a default field, the [] because it's a relational field. So:

    <input type="hidden" name="fields[yourRelationalFieldName][]" value="{{ entry.id }}" />

Now, when the user commits this form (and has the permissions to create new entries in the comments section), a new comments entry will be created, related to the parent entry. You can even relate comments to other comments this way.

Good luck!

Paul
  • 6,338
  • 12
  • 26
  • Sorry Paul. Didn't mean to overwrite your answer. We were obviously posting at the same time. Good tag team effort ;) – Douglas McDonald Oct 06 '14 at 08:18
  • No problem at all! – Paul Oct 06 '14 at 08:39
  • Thanks again. Between the two answers here I think I have enough to get me up and running. I'll update here tonight when I've tested a bit more. I do think this way of commenting allows for a lot of flexibility. – shorn Oct 06 '14 at 09:51
0

This worked like a charm for me! Thanks if anyone needs the short code for the hidden input it's basically the same...

{{ hiddenInput('fields[yourRelationalFieldName][]', postId) }}

It took me a couple of tries to get it. The second [] is required like the post says.