Jump to content

Best way to handle saving an item as a favorite


ZionBludd
 Share

Recommended Posts

Hi All, I am wondering if you could provide input on the best way an item as a user favorite.

I am setting up a price comaprison website, and have most of the logic done for the site. Search results, listing page, login/logout, search, etc. It's all looking pretty good. However someone has suggested to me that users might like to save an item as a favorite.

So my idea behind that was to have a button on each of the grid items in the search results page. 

This is my search results page code with the button within the item.

<form id="add_fav" name="add_fav" autocomplete="off" accept-charset="utf-8" action="./" method="post">
  <button class="wish_btn" name="add_fav">Add Fav</button>
</form>

Where the business logic is on the page, this is what I have so far - I just don't know how to align an item to a user.

$log->save ('pageview', 'testing');
function clense_input($data){
            $data = trim($data);
            $data = stripslashes($data);
            $data = htmlspecialchars($data);
            return $data;
        } 
      
        $sort = "title";

        // Logic for favorites

        if ($_SERVER["REQUEST_METHOD"] == "POST") {
          if (isset($_POST['add_fav'])) {
            $favs = $sanitizer->text($_POST['add_fav']);
            if(!empty($favs)){
              $ticket = $pages->get($favs); // Set page name 
              if($favs != null){
                $favs->of(false);
                $favs->fav_title = $page->user->name; // Save username
                $favs->fav_title = $page->title->id; // Save page id to favs list
                $favs->save();
                echo "Fav saved.";
              }
            }
          }
      }

 

Link to comment
Share on other sites

1 hour ago, mattcohen said:

Where the business logic is on the page, this is what I have so far - I just don't know how to align an item to a user.

It depends on how you've set up the backend. You say logic for favourites, so I assume a user can have more than one favourite. I am also assuming that users need to login (i.e., no guest users). Finally, I assume an item is a PW page.

Two approaches I can think of.

  1. Save users to the fav item. I think this is what you are doing in your code above. I wouldn't take this approach though. I'm not sure it would scale very well. I'd do it the other way round (#2)
  2. Save favs to users. I explain below

If your items are pages, it is easy to reference them in a page field. Create a page field that accepts multiple pages. Let's call it favs. Add the page field favs to the user template. I am assuming your users are normal users. This way, we only need to save the ID of the favourite item. Using that, we can get its title or whatever field it has at runtime to display to the user his/her favourite items. Here's some untested code (could throw up errors).

 

// inputs for favourites; could be whatever input, as long as can take multiple items
// <input type='hidden' name='add_fav[]' value='1234'> a listed item
// <input type='hidden' name='add_fav[]' value='5678'> another listed item

// add favourites for a LOGGED IN user
// @note: using ProcessWire $input
if(count($input->post->add_fav)) {
    foreach ($input->post->add_fav as $fav) {
        $user->favs->add((int)$fav);
    }

    $user->of(false);
    $user->save('favs');
}

// fetch favourites for a LOGGED IN user
$out = '';
if($user->favs->count) {
    $out .= '<ul>';
    foreach($user->favs as $fav) {
        $out .= '<li>'. $fav->title .'</li>';
    }
    $out .= '</ul>';
}

echo $out;

Do you have a need to use $_POST rather than ProcessWire's $input?

Edit:

If you have losts of listable items (i.e. the selectable pages in the user field favs, although the users will not be interacting with the field directly in the backend, you might want to use autocomplete as the input for the page field.

Edited by kongondo
  • Like 2
Link to comment
Share on other sites

Thanks so much for your help kongondo. I am currently debugging my site, and can't output the user favorites or get it to save to the database. This is after adding the field favs to the user template. I'm sure I'll get it to work eventaully. ;)

 

Edit: Would cookies be another way to accomplish this? 

 

Link to comment
Share on other sites

1 hour ago, mattcohen said:

I am currently debugging my site, and can't output the user favorites or get it to save to the database.

  • How does your code look like?
  • Is the user logged in or did you try by getting the user and echoing their saved values? e.g. $u = $users->get('user-name');
  • If you save manually when editing the user in the PW backend, does it save?
  • Do you have debug on? Any errors?

 

1 hour ago, mattcohen said:

Edit: Would cookies be another way to accomplish this? 

Depends on the sort of persistence you want. If fav items need to be saved for a short time only, then, yes, cookies or even sessions would work. If a user clears their cookies for whatever reason, they'd need to start over. There's other issues to consider as well, for instance, if the user is on a shared computer. I'd go for saving favs as pages. It is more foolproof - e.g. easily grab and display a user's favs. It is also more flexible. Item is no longer available, easy to tell user 'item is no longer available', etc.

Link to comment
Share on other sites

Thanks so much for your efforts! You put me in the right direction, I ended up going for the page create function vs storing in the user->favs way. Manly because my friend who is helping me with this is a software developer and he stays clear of frameworks.

This is my code for detecting the input button.

<?php if ($input->post->add_fav) {

    // Save in the ProcessWire page tree; map submission to the template fields
    $np = new Page(); // create new page object
    $np->template = $templates->get("Favorites");
    $np->parent = $pages->get("/favorites/");
  ?>

On the results page in each item I have the following code

<form action="./" method="post"><button type="submit" value="{dbResult.id}" name="add_fav">Add Favorite</button>
</form>

And then finally this is the most stop gap measure system to actually view the favorites, and I'm sure you'll be able to point out that it is very prone to bugs and security holes

<?php
$id = $user->id ;

$get_favs = $pages->find("template=Favorites, user_id=.$id.");
foreach($get_favs as $fav) {
    echo "<li><a href='$fav->url'>$fav->product_id</a></li>";
}
?>

Thanks again for your help, What do you think? Are you shuddering :) 

Link to comment
Share on other sites

Just a couple of comments.

If I understood correctly, you are creating favourites on the fly. There are a couple of issues with this approach

  1. Unless user_id is a multi-page field, it means a favourite item cannot be shared between several users
  2. Related to above, what if user A and user B both have item X as a favourite?
  3. The items, the ones users are comparing, are they pages in ProcessWire? If yes, than you are creating two parallel page trees with the same content. One, you have a list of items (Product A, Product B, Product C, etc whose parent is /products/). Users then favourite them, /favorites/product-a/, /favorites/product-c/, etc. You now have Product A and Product C in two places. 

in your new Page() code, you are not checking if that page already exists as a favourite. Depending on the ProcessWire version you are using, ProcessWire will silently create a duplicate of the favourite, just with a different name (i.e. they will share a title but have different names, latter ones with a timestamp suffix).

Maybe you haven't shown the whole code, but in your listing, it is good to first check if the user is logged in.

If you could confirm what the lists for comparisons are (i.e. are you scraping some other website, or using REST or are they pages in your ProcessWire website), our response could be more definite. Also confirm what type of field user_id is.

 

Link to comment
Share on other sites

I'm a bit confused.

If only logged in users are able to save favorites, just create another textarea field in the user-tpl.

Save items as JSON and use array_unique() to avoid duplicates. When outputting favs, just use json_decode().

And if persistence is necessary without having to log-in / register, just use cookies or local storage.

If this list needs to be shareable, you'd need to think about a way to convert your array or JSON to a query-string - but that's easy.

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...