Jump to content

How to make a simple form and save it in database and load it in a table?


sam13579
 Share

Recommended Posts

Sorry for posting it again. I posted the same thing it in another forum. There I found some basic tutorial from a person. That was helpful, but still I need some direct answers.

I need to understand how I can,

1. Submit a form ?

2. Then load it into a table from database.

Can anyone there simply teach me this?

Link to comment
Share on other sites

Hi, welcome to the ProcessWire forums!

The questions in your recent threads are kind of broad and it’s difficult to tell what exactly you’re struggling with and what you already know. I’m assuming you have ProcessWire installed and working, and you want to save some user inputs from the frontend into the fields you have created in PW’s admin area.

Saving fields using the ProcessWire API
First of all, you need a page to hold the data. Perhaps this page already exists, then you just get it using selectors, or maybe it’s the page you’re already on. Likely you want to save a new page for every time a user fills out the form, so let’s create a page:

$p = new Page();
$p->template = 'form-submission'; //or whatever your template is called
$p->parent = wire('pages')->get('/submissions/'); //or whatever the parent page is called

Nice. Now, to get the information from the form you’re going to need ProcessWire’s input capabilities. You can find out all about it at the link and you’ll need to make some decisions about validation/sanitization depending on the data you’re dealing with, but the gist is to get stuff from the POST request sent by your user and put it into fields. Let’s say your user submits their e-mail address and you want to save it to a field called email:

/* You see the name “email” three times:
 * 1. The first is the field you set up in the admin area.
 * 2. The second is the sanitizer that makes sure the thing the
 *    user sent you actually looks like an email address.
 * 3. The third is the name of the input from from the form the
 *    user filled out and submitted. */
$p->email = $input->post->email('email');

//Now you will probably want to fill out some more fields the same way:
$p->comment = $input->post->textarea('comment');
$p->title = 'Form submission from ' . date('Y-m-d H:i');

Then you save the page and you’re done. You can go to the admin backend and check out the newly created page.

$p->save();

However, we haven’t talked about the frontend bits yet.

 

Creating a frontend form and sending submissions to ProcessWire
Once again much depends on what you actually want to do, but for simplicity’s sake, let’s say this all happens on the same page. You have a ProcessWire template associated with a template file and all the above code is in it. Now we put the form into the same file. Basically the form is sent to the same page it’s coming from, but as you’ve seen above, you can still create the new page wherever you want. So here’s a simple HTML form that submits to the same page:

<form method="POST" action="<?php echo $page->url; ?>">
  <label for="email">Your e-mail address</label>
  <input name="email" type="email" />
  
  <label for="comment">Your comment (no swearing!!!)</label>
  <textarea name="comment" rows="5"></textarea>
  
  <input type="submit" value="Send"/>
</form>

Note how the names of the input fields match the names we accessed earlier using $input->post().

 

Putting it together
If you simply copy all my code blocks into your template file, you’ll probably notice that it tries to create a new page ever time the page is loaded. You’ll need to figure out if there is a form submission at all before you deal with it, and otherwise just skip that part and show the blank form. You may just check if there is anything in the comment variable. So here is your complete template file:

<?php namespace ProcessWire;

    $thanks = "";
    
    if ($input->post('comment')) {
        $p = new Page();
        $p->template = 'form-submission'; //or whatever your template is called
        $p->parent = wire('pages')->get('/submissions/'); //or whatever the parent page is called

        $p->email = $input->post->email('email');
        $p->comment = $input->post->textarea('comment');
        $p->title = 'Form submission from ' . date('Y-m-d H:i');

        $p->save();
        
        $thanks = "Thanks a bunch, we value your feedback!"
    }
?>

<!doctype html>
<html>
<head>
    <title>Post a comment</title>
</head>
<body>
    
    <?php
        if ($thanks !== "") {
            echo "<h1>{$thanks}</h1>";
        }    
    ?>

    <form method="POST" action="<?php echo $page->url; ?>">
      <label for="email">Your e-mail address</label>
      <input name="email" type="email" />
      
      <label for="comment">Your comment (no swearing!!!)</label>
      <textarea name="comment" rows="5"></textarea>
      
      <input type="submit" value="Send"/>
    </form>
    
</body>
</html>

Now I’m not saying you should put this exact code on your website, but it’s a demonstration of the most bare-bones things you’ll need to get input from users: A HTML form that generates a POST request and some PHP code to receive it. It doesn’t matter where these things are or what they’re called or how they’re generated. In this example we’ve written the form by hand because it’s easy, but you could just as well generate it from ProcessWire’s fields.

  • Like 10
Link to comment
Share on other sites

On 11/14/2021 at 1:31 PM, Jan Romero said:

Hi, welcome to the ProcessWire forums!

The questions in your recent threads are kind of broad and it’s difficult to tell what exactly you’re struggling with and what you already know. I’m assuming you have ProcessWire installed and working, and you want to save some user inputs from the frontend into the fields you have created in PW’s admin area.

Saving fields using the ProcessWire API
First of all, you need a page to hold the data. Perhaps this page already exists, then you just get it using selectors, or maybe it’s the page you’re already on. Likely you want to save a new page for every time a user fills out the form, so let’s create a page:

$p = new Page();
$p->template = 'form-submission'; //or whatever your template is called
$p->parent = wire('pages')->get('/submissions/'); //or whatever the parent page is called

Nice. Now, to get the information from the form you’re going to need ProcessWire’s input capabilities. You can find out all about it at the link and you’ll need to make some decisions about validation/sanitization depending on the data you’re dealing with, but the gist is to get stuff from the POST request sent by your user and put it into fields. Let’s say your user submits their e-mail address and you want to save it to a field called email:

/* You see the name “email” three times:
 * 1. The first is the field you set up in the admin area.
 * 2. The second is the sanitizer that makes sure the thing the
 *    user sent you actually looks like an email address.
 * 3. The third is the name of the input from from the form the
 *    user filled out and submitted. */
$p->email = $input->post->email('email');

//Now you will probably want to fill out some more fields the same way:
$p->comment = $input->post->textarea('comment');
$p->title = 'Form submission from ' . date('Y-m-d H:i');

Then you save the page and you’re done. You can go to the admin backend and check out the newly created page.

$p->save();

However, we haven’t talked about the frontend bits yet.

 

Creating a frontend form and sending submissions to ProcessWire
Once again much depends on what you actually want to do, but for simplicity’s sake, let’s say this all happens on the same page. You have a ProcessWire template associated with a template file and all the above code is in it. Now we put the form into the same file. Basically the form is sent to the same page it’s coming from, but as you’ve seen above, you can still create the new page wherever you want. So here’s a simple HTML form that submits to the same page:

<form method="POST" action="<?php echo $page->url; ?>">
  <label for="email">Your e-mail address</label>
  <input name="email" type="email" />
  
  <label for="comment">Your comment (no swearing!!!)</label>
  <textarea name="comment" rows="5"></textarea>
  
  <input type="submit" value="Send"/>
</form>

Note how the names of the input fields match the names we accessed earlier using $input->post().

 

Putting it together
If you simply copy all my code blocks into your template file, you’ll probably notice that it tries to create a new page ever time the page is loaded. You’ll need to figure out if there is a form submission at all before you deal with it, and otherwise just skip that part and show the blank form. You may just check if there is anything in the comment variable. So here is your complete template file:

<?php namespace ProcessWire;

    $thanks = "";
    
    if ($input->post('comment')) {
        $p = new Page();
        $p->template = 'form-submission'; //or whatever your template is called
        $p->parent = wire('pages')->get('/submissions/'); //or whatever the parent page is called

        $p->email = $input->post->email('email');
        $p->comment = $input->post->textarea('comment');
        $p->title = 'Form submission from ' . date('Y-m-d H:i');

        $p->save();
        
        $thanks = "Thanks a bunch, we value your feedback!"
    }
?>

<!doctype html>
<html>
<head>
    <title>Post a comment</title>
</head>
<body>
    
    <?php
        if ($thanks !== "") {
            echo "<h1>{$thanks}</h1>";
        }    
    ?>

    <form method="POST" action="<?php echo $page->url; ?>">
      <label for="email">Your e-mail address</label>
      <input name="email" type="email" />
      
      <label for="comment">Your comment (no swearing!!!)</label>
      <textarea name="comment" rows="5"></textarea>
      
      <input type="submit" value="Send"/>
    </form>
    
</body>
</html>

Now I’m not saying you should put this exact code on your website, but it’s a demonstration of the most bare-bones things you’ll need to get input from users: A HTML form that generates a POST request and some PHP code to receive it. It doesn’t matter where these things are or what they’re called or how they’re generated. In this example we’ve written the form by hand because it’s easy, but you could just as well generate it from ProcessWire’s fields.

Hello !

First of all thanks a lot for this post, as a beginner in php and PW I was very happy to find it. But I was wondering if you could direct me to a solution in my case. Because I have applied your code and it works well, but I have one issue with "Confirm Form Resubmission" dialog. 


What I want:

-possibility to add new pages to database of certain template (and it works)

Frontend: 

1400697200_ScreenRecording2021-11-18at11_53_47.gif.8ac97b31bfeb315c94b1ba3714b3386e.gif

Code example (top of the page): 

<?php
if ($input->post('title_doc')) {
    $p = new Page();
    $p->template = 'Document'; 
    $p->parent = wire('pages')->get('/Documents/'); 

    $p->title = $input->post->name('title_doc');
    $title_format = str_replace("_", " ",    $p->title);
    $p->title = $title_format;

    $p->save();
}
if ($input->post('title_org')) {
    $p = new Page();
    $p->template = 'Organisation'; 
    $p->parent = wire('pages')->get('/Organisations/'); 

    $p->title = $input->post->name('title_org');
    $title_format = str_replace("_", " ", $p->title);
    $p->title = $title_format;

    $p->save();
}

Form example: 

<div class="pf-sub-column doc_c_light">
    <h2 class="pf-title "> Documents
    <input class="add_document doc" onClick="$('.doc_add').toggleClass('display')" type=button value="+"/>
        <form class="doc_add add_document_form " method="POST" action="<?php echo $page->url; ?>">
            <label  for="title_doc">Title</label>
            <input name="title_doc" type="title" />
            <input type="submit" value="add"/>
        </form>
    </h2>
    <?php include('./checkbox_pf_docs.php')?>
</div>

My issue is not the creation of the page, but that if you open the page and want to press "back" , it shows this window, because my form is not cleaned or refreshed somehow. I was wondering if there is a simple solution I am not aware of due to my nubeeness. 

1966220899_ScreenRecording2021-11-18at11_58_45.gif.85e53876df889ec2e6202364244abe8e.gif

Best,

Ksenia

  • Like 1
Link to comment
Share on other sites

Hello @Ksenia! That’s a browser feature that’s supposed to prevent users from submitting the same form twice. I believe the quickest way to get rid of it would be to add a redirect to the same page after saving:

$session->redirect('./', 303);

That sends a 303 HTTP status code telling the browser to reload the page using a GET request, which MDN recommends for this purpose, as I understand it. Be aware that ProcessWire exits after a call to $session->redirect(), so no code below that line will get executed. Hope it works for you, I haven’t tested it though!

  • Like 3
Link to comment
Share on other sites

On 11/19/2021 at 1:46 AM, Jan Romero said:

Hello @Ksenia! That’s a browser feature that’s supposed to prevent users from submitting the same form twice. I believe the quickest way to get rid of it would be to add a redirect to the same page after saving:

$session->redirect('./', 303);

That sends a 303 HTTP status code telling the browser to reload the page using a GET request, which MDN recommends for this purpose, as I understand it. Be aware that ProcessWire exits after a call to $session->redirect(), so no code below that line will get executed. Hope it works for you, I haven’t tested it though!

Sorry for late reply! 

Thanks, that worked well!

  • Like 1
Link to comment
Share on other sites

@Jan Romero thank you. I really appreciated this mini tut. It would be awesome to see more of this. Breaking down a single challenge. And then newbies like me can build upon each and utilize each principle as needed.
 

I don’t know if this repo is open to contributions but it would be a nice inclusion here:

https://github.com/webmanufaktur/processwire-snippets

 

  • Like 1
Link to comment
Share on other sites

  • 5 months later...

is there a way to store the user input (post) in some custom admin page? I don't need a new page for each submission, just one page, not visible to the user, only to me in admin with a list/table of all user submitted data.

Link to comment
Share on other sites

Well, once you have the submitted data, you can do with it whatever you want. It really depends on what the data is and where you want it. In my comment above the example is one email address and one comment. So if you want to store those things in your admin page, its template would need a way to store multiple email-comment pairs. That could be a Repeater or a ProFieldsTable (👌) or a custom fieldtype. You could also store one new page per submission as a child of your admin page (that’s essentially what a repeater would do behind the scenes anyway, it just looks different in the page tree and page editor – pretty much a matter of preference). Having a page per submission takes care of some stuff you probably want anyway automatically, such as storing the creation date. It also gives you a url for each submission that you could put into an email notification for yourself, or something.

My comment gives a pretty complete example of how to get the data from the user’s browser into ProcessWire’s database. Are you struggling with anything specific?

  • Like 1
Link to comment
Share on other sites

@Jan Romero thanks, what you're saying makes good sense. Creating pages instead of repeater items for each post input seems a good solution, provided that those pages can be admin only. However, for this particular use case, I prefer to have all user submissions on one page, just would make things much easier for my intentions. So I would need to create a template for that new admin page which includes a repeater field or ProFieldsTable field (I have been using that), right? Do I do that in the templates section of the admin area ("add new template") or programatically? It seems to me like those admin pages and templates are created differently… I think that's what I struggle with mostly. Also, creating a custom fieldtype is something I would love to be able to do, just couldn't wrap my mind around it yet.

Link to comment
Share on other sites

@fruid Admin pages are just pages in the admin branch of the tree. The ones ProcessWire ships with as well as those of some modules (e.g. Adminer) use a special admin template, but you can just put any old page there. So I would just make a new template with the things you need and create a new page under Admin and set it to hidden and unpublished. When the form is submitted you can get the page by its ID, add the submitted data to it and save.

  • Like 1
Link to comment
Share on other sites

OK thanks again. Anyways, I was looking into other modules that seem to use a different approach. Instead of relying on an admin-template with fields or constructing custom fields, they just create plain sql tables in the database via mysql commands (e.g. module ProcessPageViewStat).
It would then render a form or whatever in the admin area to display the data in that database table.

Is that good practice? What are the dangers? 

To be honest, I also struggle with creating custom fields which would go a long way for me in order to create custom modules. I'd like to construct custom fields, possibly also include custom javascript or components of some framework/library (vue.js, jquery, …) I remember having seen a dummy/boilerplate-module that illustrates and walks you through the process of creating a custom field, just cannot remember the name…

thanks for help

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...