Jump to content
ZionBludd

Best way to handle saving an item as a favorite

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.";
              }
            }
          }
      }

 

Share this post


Link to post
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

Share this post


Link to post
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? 

 

Share this post


Link to post
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.

Share this post


Link to post
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 :) 

Share this post


Link to post
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.

 

Share this post


Link to post
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.

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By 997 998 999
      Hello,
      I'm trying to edit the field of a page with a value from a javascript fetch post request but I can't get the
      file_get_contents("php://input") or
      $_POST value in my PHP file.
      I created a `update` template and a `update` page (to allow access from fetch request and avoid 404/403/... errors) containing this code :
      $data = file_get_contents('php://input'); echo $data; # test edit the page field with random value #$home = $pages->get("/"); #$home->of(false); #$home->testfield = "test value"; #$home->save(); # test fetch response with random value #echo "test fetch response"; That I fetch request with my client javascript like this :
      fetch('/update', { method: 'POST', body: 'test' }) .then(function(response) { return response.text(); }) .then(function(data) { console.log(data); }) .catch(error => console.log('error')) } The field edit works fine and I get the test response from the `update` file but I can't get the posted value, I only get `<empty string>`. It is working fine outside of ProcessWire so I guess this is related to how PW handle $_POST ?
      I found this post where it seems to be working :
       
      Is there any way to get post value from javascript fetch request? What am I doing wrong?
       
      Thank you
       
       
       
    • By dimitrios
      Hello,
      this module can publish content of a Processwire page on a Facebook page, triggered by saving the Processwire page.
      To set it up, configure the module with a Facebook app ID, secret and a Page ID. Following is additional configuration on Facebook for developers:
      Minimum Required Facebook App configuration:
      on Settings -> Basics, provide the App Domains, provide the Site URL, on Settings -> Advanced, set the API version (has been tested up to v3.3), add Product: Facebook Login, on Facebook Login -> Settings, set Client OAuth Login: Yes, set Web OAuth Login: Yes, set Enforce HTTPS: Yes, add "https://www.example.com/processwire/page/" to field Valid OAuth Redirect URIs. This module is configurable as follows:
      Templates: posts can take place only for pages with the defined templates. On/Off switch: specify a checkbox field that will not allow the post if checked. Specify a message and/or an image for the post.
      Usage
      edit the desired PW page and save; it will post right after the initial Facebook log in and permission granting. After that, an access token is kept.
       
      Download
      PW module directory: http://modules.processwire.com/modules/auto-fb-post/ Github: https://github.com/kastrind/AutoFbPost   Note: Facebook SDK for PHP is utilized.


    • By jds43
      Hello,
      I have a search page loosely based on Skyscrapers where I'm parsing a selector with options 'beds', 'bathrooms', 'size' fields. It is working well until I select 'Any' after I've run a search. This is where no results are returned (/?beds=&bathrooms=&size=&submit=). I want it to reset and show all results.
      I hope this isn't too vague.
       
    • By iipa
      Hello forum!
      I have a site, where I want to remember two settings defined by user:
      1) Theme (light or dark)
      2) Language (Finnish or English)
      Because user makes changes to these settings on client side, I am a bit lost with how can I save them in ProcessWire $session variable? I would like to use $session for more reliable saving, and since it is only two variables I will use, I doubt it will become too resource-needy.
      I have tried using jQuery's post() -method referring to a file in Templates folder (theme.php), but I get 403 Forbidden Error. I don't like the idea of trying to post to same file user currently is in, which is why I thought having a separate file would be good in this.
      Contents of theme.php:
      <?php namespace ProcessWire; header('Access-Control-Allow-Origin: https://domain.com'); $theme = $input->post['theme']; if(!empty($theme)) $session->theme = $theme; ?> Long story short: Does anybody have any pro tips I could use with setting and getting $session variables?
    • By pwFoo
      With JS fetch() it is a bit tricky to get for example $_POST populated (params need to be FormData / forms), but would it possible to get PW $input (get, post, urlSegments, queryString) working for fetch requests?
      Is there a fix / hook / workaround to solve it PW side?
×
×
  • Create New...