Simple "Like"-feature

@texnixe Would you suggest it’s best to put this update function in a plugin? E.g. like so:

site/plugins/like/like.php

<?php

  function like() {
    // Update function
  }

?>

How do I call the like() function via the form in the template then?

Since you are using ajax, you could register a route in your plugin and call the like function from there passing the uri as argument:

kirby()->routes(array(  
    array(
        'pattern' => '(:all)/like',
        'method'  => 'POST',
        'action'  => function($uri) {
            // check if page exists

            like($uri);

            // ...
        }
    )
));
1 Like

Oh, that would be elegant, you’re right @pedroborges, thanks! Let me see if I can make this work!

Alright, I feel like I’m almost there, but it doesn’t work yet.

site/plugins/like/like.php

<?php

kirby()->routes([

  [
    'pattern' => "/like:(:any)",
    'method'  => 'POST',
    'action'  => function($uid) {
      $post = page('blog/' + $uid);
      try {
        $post->update(array(
          'likes' => 1000
        ));
        echo 'The page has been updated';
      } catch(Exception $e) {
        echo $e->getMessage();
      }
    }
  ]

]);

I’m making the Ajax call like that:

const btnLike = document.querySelector('.js-like');
if (btnLike) {
  btnLike.addEventListener('click', function() {
    console.log('like clicked');
    request
      .post('/like:super-t')
      .end(function(err, res) {
        if (!err) console.log('liked');
        else console.log('error');
      });
  });
}

and it’s logging “liked” in the console, so that should be fine. “super-t” is the uid of a blog post. Any idea what I’m missing here?

You are using the + operator instead of . (probably because you wrote JS before, happens to me all the time :smiley:):

$post = page('blog/' . $uid);

If it still doesn’t work, could you please request the URL directly in your browser without AJAX and check if there is any output?

Ah, true! Fixed the operator, still no luck with updating the likes count though. If I access http://localhost:3000/like:super-t in the browser it shows the homepage. I’ve set the blog-page to be the homepage and I’m omitting “blog” in the URLs of post-pages as explained here. Just in case that’s relevant.

Ah, I think Kirby parses that URL as a param.
The pattern "/like/(:any)" should work.

Ah okay, I’ve changed that accordingly, but now when I open http://localhost:3000/like/super-t in the browser it redirects to the error page. I also get a 404 in the AJAX request.

Well, that probably depends on your other route that redirects blog URLs. Make sure to add the new route before that.

Hmm, okay strange. I removed all other routes, but still no luck unfortunately. I still get the 404 when I access http://localhost:3000/blog/like/super-t and in the AJAX call. Here’s the current plugin file:

site/plugins/like/like.php

<?php

kirby()->routes([

  [
    'pattern' => "/blog/like/(:any)",
    'method'  => 'POST',
    'action'  => function($uid) {
      $post = page('blog/' . $uid);
      try {
        $post->update(array(
          'likes' => 1000
        ));
        echo 'The page has been updated';
      } catch(Exception $e) {
        echo $e->getMessage();
      }
    }
  ]

]);

and this the AJAX call:

const btnLike = document.querySelector('.js-like');
if (btnLike) {
  btnLike.addEventListener('click', function() {
    console.log('like clicked');
    request
      .post('/blog/like/super-t')
      .end(function(err, res) {
        if (!err) console.log('liked');
        else console.log('error');
      });
  });
}

If things worked correctly, what am I supposed to see instead of the 404 error?

Have you tried to remove the post method and also the slash before ‘blog’ in your pattern?

Nice, that was it! It works! Removed the method in the plugin and changed the AJAX call from POST to GET also. So it successfully updates the likes count if I pass a static value (e.g. 20) in the update function, but if I attempt to increment the count on each page reload, it doesn’t update at all. This is my current attempt:

site/plugins/like/like.php

<?php

kirby()->routes([

  [
    'pattern' => "blog/like/(:any)",
    'action'  => function($uid) {
      $post = page('blog/' . $uid);
      $likesCount = $post->likes();
      $likesCount++;
      try {
        $post->update(array(
          'likes' => $likesCount
        ));
        echo 'The page has been updated';
        echo $likesCount;
      } catch(Exception $e) {
        echo $e->getMessage();
      }
    }
  ]

]);

I’m sure I’m overlooking something super easy, but I’m having the hardest time with this, haha.

Does the following work?

$likesCount = $post->likes()->int();
$likesCount++;

No, unfortunately not. I’ve also tried something like

$post->update(array(
  'likes' => function($likesCount) {
    return $likesCount++;
  }
));

but that breaks the whole thing.

No, functions are not currently supported (but that’s a great idea, I have created a feature request issue).

We unfortunately can’t really help with line-by-line debugging. You need to test it yourself by adding dump statements here and there to check what the value is and where it gets wrong.

Alright, will figure something out :wink: Thanks for all the help!

I tried here and this worked, note that the method is just int():

$likesCount = $post->likes()->int();
$likesCount++;
1 Like

Niiiice @pedroborges, that totally works :smiley: Awesome! Thank you man!

Thanks a lot for correcting the typo. :slight_smile:

1 Like

Callback in $page->update() has just been added to the development branch and will be included in the next release. Also coming with the next release, two handy functions for this topic:

$page->increment('likes');
$page->increment('likes', $by = 10);
$page->increment('likes', $by = 10, $max = 1000);

$page->decrement('likes');
$page->decrement('likes', $by = 10);
$page->decrement('likes', $by = 10, $min = 0);
5 Likes