Jump to content
evanmcd

How to save submitted form data from a module

Recommended Posts

Hi,

I've started to work on a simple vote up/down module for PW, and am stuck at how to save the vote from the user.

Here's the stubbed out function I've got that I thought would do the trick (I got the basics from the the FieldtypeComments module), but when I submit to the page, I don't get anything - no errors (with debugging on), and no inserted data.  Guessing I'm missing something simple.

Thanks.

public function ___savePageField(Page $page, Field $field) {
    $sql = "INSERT INTO `{$field->table}` SET pages_id={$page->id}, vote = 1";
    if(!$result = $this->db->query($sql)) $this->error("Error saving item");
    return true;
}

Share this post


Link to post
Share on other sites

Evan, I'm not sure we can tell much from the code snippet you posted. Because a Fieldtype is a system with various components involved, I think we might need to see the broader context here (full Fieldtype and Inputfield).

Share this post


Link to post
Share on other sites

Hi guys,

No, not trying to save a page, trying to save the post value from a form created by my module into the field's table. Just like a comment from a user on a page using the comment module.

The form is created in the formatValue function, as is done in the comments module. 

Here's the full code of the module as it stands.

Thanks for your help.  Really enjoying getting into making a module, and looking forward to contributing it to the community.  :)

https://gist.github.com/1473421

Share this post


Link to post
Share on other sites

Are you sure this is from FieldtypeComments? That module doesn't override the formatValue() function. Also the comments on that function refer to renderMapMarkup? :) This is different than how formatValue is meant to be used, but it is still okay. But there is a major component missing, and that is how the value goes from user input into your fieldtype? Fieldtypes aren't meant to handle user input (Inputfields are), so we have to come up with another way to get front-end user input into here.

Before we go further, I just mention how FieldtypeComments works: It has no formatValue() function because it doesn't need one. formatValue is an optional method to convert a runtime value into one ready for presentation on the site... the best example is taking a string of text and encoding the entities in it (i.e. '&' becomes '&'). FieldtypeComments doesn't need a formatValue() function because its wakeupValue() returns an object (of type CommentArray). That CommentArray has some built in helper methods that you can use on your site to render comments or render the form for them. So here's how you render comments:

echo $page->comments->render(); 

And the form for inputting comments is rendered like this:

echo $page->comments->renderForm(); 

That renderForm() method actually loads up another class called CommentForm(), and that class is looking for posted comments. This is different from other Fieldtypes because it's something designed to accept input from the frontend rather than the admin. Admin input is handled with Inputfields.

So in your case, you are trying to achieve the same result at FieldtypeComments. I think it may be okay to let your formatValue() function take this role. But your formatValue function will need to detect when a up/down has been submitted, in addition to outputting the form that it is now.

At least for now, I would suggest making your Fieldtype a regular Fieldtype and not a FieldtypeMulti. I don't think a FieldtypeMulti isn't necessary here and might even make it more difficult to implement. Instead, I would use a schema that increments a single counter for every up vote. Probably the same schema as FieldtypeInteger. If you wanted to maintain separate up and down counters, then you would expand your Fieldtype schema to have two counters. But I would suggest just starting with one to get things going, and then expand. Likewise, if you determine you need a FieldtypeMulti, than no problem, but since that evolves from a regular Fieldtype, it's good to understand the workings of a regular Fieldtype first.

Assuming the stuff in the paragraph above, your formatValue would do something like this:

<?php

public function formatValue(Page $page, Field $field, $value) { 

    if($input->post->vote) { 
        // a vote was submitted

        // turns off outputFormatting so we can save a raw value
        $page->setOutputFormatting(false);

        // now increment and save the value
        $name = $field->name;
        $value++; // increment the counter
        $page->set($name, $value); 
        $page->save($name); 

        // turn outputFormatting back on, so we're leaving everything as it was
        $page->setOutputFormatting(true);

        $out = "<p>Thank you for voting. Current votes: $value</p>";

    } else {
        // no vote submitted, display the form 

        $out = "<form action='./' method='post'>" . 
               "<p>Current votes: $value</p>" . 
               "<p><input type='submit' name='vote' value='Vote' /></p>" . 
               "</form>";
    }

    return $out; 
}

Note that there is no security or validation to ensure the user doesn't double vote or hasn't already voted for that page, etc. So it's just for demonstration purposes, but I think gets across the part I was talking about: something to identify the vote submission and save the vote.

Share this post


Link to post
Share on other sites

Hi Ryan,

Thanks for the detailed response.  I forgot to mention that I used code from the GMap module as well - I guess that's where I got the formatValue function.

The key part that I didn't understand until your example was the proper way to get a user submitted value.  If doing it in formatValue works, then I'll do it from there.  If you have a better (i,e. more standardized across other modules) way to do it, then I'd do that instead.

I think I'll stick with fieldType multi because, although my current need doesn't require it, I want to build the module to have the option of tying each vote on a page to the user that cast it.  If a user is logged in, it will save their ID, if not it will save it without.

This is obviously so we can prevent users from voting more than once on a specific page.  For the non signed-in users, I'll do that with a cookie (not foolproof obviously, but better than nothing).

Again, thanks for the help.  I'll post an update here once I've got it to the next stage.

Share this post


Link to post
Share on other sites

This is obviously so we can prevent users from voting more than once on a specific page.  For the non signed-in users, I'll do that with a cookie (not foolproof obviously, but better than nothing).

You could also value signed-in votes more than anonymous. Depends on the use case also.

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.

×
×
  • Create New...