Jump to content

Like page (photo) for logged in user


sirhc
 Share

Recommended Posts

Hi all,

Im working on a photography website where users can comment and like on photos (which are pages). I solved the comment part with the comment module, but I also want a 'like' system. Which includes;

- Like a photo. Like count on the photo adds up.
- If user has a few favourite photos, i would like a 'Favourites' section on the user profile page, with all of the liked photos.
- Apart from the likes, i would like to have a page 'Most liked photos of this week', so each week the community can see the photos with the most likes that week.

I came across the Like plug-in, but i would like to have a little more tailored solution and keep it to logged-in users only and be able to see all of the liked photos of a user.

Any idea how to keep track of the likes and build a 'Most liked this week' page?
Help would be appreciated!

Thnx.

Link to comment
Share on other sites

hi sirhc,

you could create a page reference field on your photo-template and when a user clicks on like you can add this user to the pagefield. if you have lots of users (likes) that could cause some problems on the page edit screen i guess, but if you set the field to hidden it should work.

like count is as easy as counting referenced pages (users).

show all liked photos would be an easy selector like "template=photo,likes=youruserid"

 

most likes this week... hmmm... that's not possible with the setup above. then maybe it's better to create 2 new templates:

1) likes (just the parent for all likes)
2) like (pagefield referencing the photo, user that liked)

then you can create a new "like" page whenever a user likes a photo and then you can also count all likes of that week: $pages->count("template=like,photo=yourphotoid,created>xxx,created<yyy");

and counting all likes for one photo would be even easier: $pages->count("template=like,photo=yourphotoid");

  • Like 1
Link to comment
Share on other sites

Edit September 2022

See this thread: 

---

 

I would have taken another way. 

As each photo are Page, he could create a module which work with a custom MySQL table where he update the like of a page with some informations aside, like the userID (the user who like the page), the pageID (the page being liked) , a likeStatus (like or unliked) and a timestamp.

 

I made a small module to show the idea :

 

Spoiler
<?php namespace ProcessWire;

class LikeSystem extends WireData implements Module {

    const minVersion = '3.0.0';
    protected $tableName = 'likes_system';

    public static function getModuleInfo()
    {
        return [
            'title' => 'LikeSystem',
            'version' => "0.0.1",
            'summary' => 'Like System for ProcessWire.',
            'author' => 'flydev',
            'href' => 'https://processwire.com',
            'singular' => false,
            'autoload' => false,
            'icon' => 'thumbs-up',
            'requires' => [
                'ProcessWire>=3.0.0'
            ]
        ];
    }

    protected function createTable() {

        $sql =  "CREATE TABLE IF NOT EXISTS " . $this->tableName . " ( " .
                "id int unsigned NOT NULL AUTO_INCREMENT, " .
                "userId int unsigned NOT NULL, " .
                "pageId int unsigned NOT NULL, " .
                "likes boolean NOT NULL," .
                "ts timestamp NULL DEFAULT CURRENT_TIMESTAMP, " .
                "PRIMARY KEY (id) " .
                ")";
        $this->database->exec($sql);
        $sql = "CREATE UNIQUE INDEX userId_pageId ON " . $this->tableName . " ('userId', 'pageId');";
        $this->database->exec($sql);

    }

    public function ___install() {

        if (version_compare($this->config->version, self::minVersion, '<'))
            throw new WireException("This module requires ProcessWire " . self::minVersion . " or newer.");

        $this->createTable();
    }

    public function ___uninstall() {
        $sql = "DROP TABLE IF EXISTS " . $this->tableName;
        $this->database->exec($sql);
    }

    public function init() {
        // check if the button 'like' as been clicked
        if(wire('input')->post->likethispage) {
            $status = (wire('input')->post->likethispage === 'like') ? 1 : 0;
            $this->likePage($status);
        }
    }

    // Like or unlike a page
    protected function likePage($status) {
        $userId = wire('user')->id;
        $sql = "INSERT INTO " . $this->tableName . "(userId, pageId, likes) VALUES ('".$userId."', '".wire('page')->id. "', '" . $status . "')
                ON DUPLICATE KEY UPDATE 
                likes = $status,
                ts = CURRENT_TIMESTAMP;";
        $this->database->exec($sql);
    }

    // get the total of like of $pageId or current page
    public function getTotal($pageId = '') {
        $pageId = empty($pageId) ? wire('page')->id : $pageId;
        $sql = "SELECT pageId FROM " . $this->tableName . " WHERE pageId = '" . $pageId . "' and likes = '1';";
        $res = $this->database->query($sql);
        $row = $res->fetchAll();
        return count($row);
    }

    // get the most liked page, if $limit is defined, it return the N most liked page
    public function getMostLikedPage($limit = 5) {
        $sql = "SELECT pageId, count(pageId) as likesCount FROM " . $this->tableName .
               " WHERE likes='1' GROUP BY pageId ORDER BY likesCount DESC LIMIT $limit;";
        $res = $this->database->query($sql);
        $row = $res->fetchAll();

        return $row;
    }

    public function render() {

        $modules = wire('modules');

        $sql = "SELECT pageId, likes FROM " . $this->tableName . " WHERE pageId = '" . wire('page')->id . "' and userId = '". wire('user')->id ."';";
        $res = $this->database->query($sql);
        $row = $res->fetch();
        $label = 'like';
        if(count($row)) {
            if($row['likes'] == 1) $label = 'unlike';
        }

        $form = $modules->get("InputfieldForm");
        $form->action = './';
        $form->method = 'post';
        $form->attr('id+name', 'likeSystemForm');

        $field = $modules->get("InputfieldSubmit");
        $field->value = $label;
        $field->icon = "thumbs-up";
        $field->attr('id+name', 'likethispage');

        $form->append($field);

        return $form->render();
    }
}

 

 

then in the frontend, you can render a 'like' button on choosen templates, and finaly get the total number of likes of a page and the most liked page, see:

 

<?php namespace ProcessWire;

$likesmod = $modules->get('LikeSystem');
// render a 'like' button
$content = $likesmod->render();
// total like of the page
$content .= "Number of likes for this page: " . $likesmod->getTotal($page->id);
// most liked page
$limit = 1
$mostliked = $likesmod->getMostLikedPage($limit);
$content .= "<br>Most liked page: " . $pages->get($mostliked[0]['pageId'])->title . "(" . $mostliked[0]['pageId'] . ") " . " (N likes: ". $mostliked[0]['likesCount'] . ")";

 

Edited by flydev ??
update 2022
  • Like 5
Link to comment
Share on other sites

7 hours ago, bernhard said:

most likes this week... hmmm... that's not possible with the setup above.

There is the Page Reference with Date Field module that might be useful for this sort of thing. I've never used it and the module page doesn't indicate that it is compatible with PW3.

But the real problem with using Page Reference fields for likes or any purpose that could potentially use thousands of pages is that there is no pagination or limiting possible when getting the field value. So it's not just a matter of dealing with the inputfield in Page Edit but also the impact on memory when getting the value via the API.

There's an open request about this but no sign of activity.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...