• Resolved gshell

    (@gshell)


    I apologize for asking such a basic question, but I am not sure that I am even on a correct path. I want to create an HTML form to update values in a wp database. I have successfully created a wp database using phpmyadmin. I can access that database and use it’s data to place default values in an HTML form, but I do not understand how I can make the HTML form send those values to an external function. I want to pass the array of variables from the form to a function within a .php file that will execute $wpdb to update the database row information. From what I have seen and read, the action parameter of a form defines a page where the form data is sent as a long string of value pairs. I don’t understand how that can be of any use for what I would like to do.

    What am I missing? I would have thought this type of action would be pretty straightforward process using $wpdb. As I said, I think I may be taking a wrong approach.

    Thanks for any help that you can provide.

Viewing 15 replies - 1 through 15 (of 16 total)
  • Is your form on a static HTML page or in WordPress?
    Form handling is always done the way you describe. The action attribute tells the browser where to send the form data(key,value pairs), and there is another attribute that says whether it is in a GET or POST format.
    The program in the file named in the action usually handles both the display of the form and the action that is wanted, because it checks if there are values to show in the form fields that it is displaying.

    When you say

    I would have thought this type of action would be pretty straightforward process using $wpdb.

    it is a little confusing because $wpdb is just a variable name in WordPress.

    Moderator bcworkz

    (@bcworkz)

    Yes, the raw data transmitted over HTTP is essentially a long string of data, but it has a specific structure. You don’t need to decipher this, PHP does it for you. All the form data will be available in either $_POST or $_GET superglobal arrays, keyed by form field name.

    Let us say you have a form that uses POST method, and it has an input field whose name attribute is “first-name”. The PHP code receiving the POSTed data can then get the field input value from $_POST['first-name']. Be sure to sanitize and validate any data coming from forms before you place it into your DB. If you do not, your server will be open to SQL injection attacks.

    After sanitizing and validating, you can indeed use the global $wpdb DB connection object to insert the data into your DB.

    Thread Starter gshell

    (@gshell)

    The PHP code receiving the POSTed data

    That’s really my problem. How do I ‘submit’ the data array of variables to a function included a xxx.php file in the plugin directory so that it can extract the individual variables to feed into $wpdb?

    I’m not really sure ‘submit’ is what I really want to do in the first place. Right now, I have a php function which defines a variable for each data element in the database using $wpdb->get_var. That function then creates an HTML form and fills the default fields with those variables. The user can edit the information in any of the fields. The desire is to ‘Save’ changes to a particular row back into the database using $wpdb->update. I have explored the idea of creating an HTML input button immediately below the HTML form, rather than the ‘submit’ button inside the form, as it can be directed to an internal function via onclick=”myFunction()”. The problem I seem to have encountered with this approach is that it appears this function must be a javascript function rather than a php function and I have even less knowledge of javascript that I do php and HTML.

    Right now I am not worried about sanitizing and validating data as I am working in a localhost environment. That’s for later after I get things working.

    If you just want to learn how to do this, get a plugin that already does form submission and saving, and read the code.
    If you just want it to work, use said plugin instead of writing it yourself.

    Moderator bcworkz

    (@bcworkz)

    Yup, sanitation can come later in the development process. Not everyone realizes how important sanitation can be, I just did not want it to “fall through the cracks”.

    Joy makes a great suggestion in learning from existing plugins. The problem for novice coders with this is the plugin code is often too complex to understand what’s going on. There are a number of simpler tutorials online about handling forms with PHP, but most do not address initializing the WP environment. Which you must do in order to use the $wpdb connection object. There are surprisingly few good ways to do this. One is via Ajax, but if you don’t want to get into JavaScript, it’s not for you. Another is posting through admin-post.php, which is sort of like Ajax, but without the need for JavaScript. But if you don’t know Ajax, admin-post.php can be confusing to use. Your final option is a custom page template. For novice coders, I think this is the most understandable approach.

    The page template can contain both the form code and the handling code. If the form POSTs its data, you can conditionally determine whether to output the form or handle the submittal by the value of $_SERVER['REQUEST_METHOD']. If the value is “POST”, get the form data from $_POST array and save the data, then perhaps output a “Data saved” message or something. Otherwise the value is probably “GET”, in which case get the current DB values and output the form.

    Place your page template file in your theme’s folder (preferably a child theme). Create a WP page based on your template. Users access the form through the page’s permalink. When the page is output, your template code executes.

    Thread Starter gshell

    (@gshell)

    bcworkz,

    Thanks for your detailed reply. I have picked up a lot from existing plug-ins, but as you note, most of them are very complex. I’ve also picked up a lot from W3 Schools, but as you note, it doesn’t deal with the integration within WP. Clearly there is a hole in the learning tools. Many of the generic plugins don’t do exactly what I would like to do, and besides I would rather learn how to do things myself. It gives me a better ability to fix issues when I eventually go live if I understand what is happening. And there will be issues. Actually I feel like I have made a lot of progress working on this in my spare time over the last couple of weeks.

    I think I understand the gist of your recommended page template approach. I’ll work on that method.

    I am just surprised that it was so easy to create the database with phpmyadmin and extract that data via $wpdb->get_var into HTML and there is not as simple a method to do the inverse. Maybe after I understand what is going on, it will also seem simple. It just doesn’t come naturally to me that I need to take data from an input form and send it to a page or post within the website in order to then process it through php back into the database. The web site will likely become cluttered enough without adding temporary storage posts or pages.

    Again, thanks for your input.

    Moderator bcworkz

    (@bcworkz)

    Being able to code your own is very empowering. Don’t get discouraged, it’ll be worth pushing on and working it out. You’re right, it’ll eventually seem simple, but working it out is confusing and frustrating. It’s the nature of learning coding.

    I don’t think you quite grasp the page template concept. The page you add based on the template is not temporary, it has its own “permalink”, it’s permanent until you delete the page. There is only one page handling all form submits. Part of your confusion could be my fault, I don’t fully grasp what you plan is with your form. It makes a difference whether you have simple, small sidebar type of form that appears on every page; or if you have a larger form occurring on a dedicated page. I was imagining the latter. If you have the former, the page template scheme is still valid, except it would not output the form itself, it only processes the submittal and outputs any messages. The form HTML would be a template part or shortcode so it can occur on multiple pages. The form would submit to the page template page containing the handler code.

    As I mentioned, there are a few approaches possible. Perhaps if you were to describe your intended user experience, I could adjust my suggestions to better fit your goals. While the page template approach is always valid, it’s not always the optimal approach.

    Thread Starter gshell

    (@gshell)

    bcworkz,
    Thanks for responding. What I meant by ‘temporary’ is that I don’t understand why I need to create another page/post to submit the form data to. I already have a page with the form filled out with all the variables I need. I just want to submit those variables to another routine that can write them into the database table. They’re already on the page being displayed, why do I need to create another output page for processing? It was relatively simple to pass information from the server side (PHP) to the client side (HTML). But I don’t understand how to pass it back.

    Let me try to explain more of what I am trying to do. I’ll probably have a lot of terminology incorrect, so bear with me. I am trying to build a simple membership website for a small social organization. I have created a new database table called wp_club_members using phpmyadmin with all the column fields we want to track. I have a few ‘members’ added to this database table for testing. When going live, I plan to bulk upload our current members. We only get a couple of new members each year, so there is no pressing need to automate ‘registration’ or the like. I would like the members to be able to edit their membership profile (most of ‘their’ fields in the database table). I can extract their email from their WP user information.
    $member_email = $current_user->user_email;
    Since their email address is also in the wp_club_members table, I can use $wpb to retrieve all of the other values in the table. i.e.:

    $my_profile = $wpdb->get_row("SELECT * FROM $table_name WHERE member_email = '$member_email' ", ARRAY_A, 0 );
    $member_first_name = $my_profile[first_name];
    $member_last_name = $my_profile[last_name];
    . . . etc.

    I know there could be a conflict if the member changes their member email and doesn’t change their WP user email, but it is a very very small organization and not a big deal. Once I get everything working, I suspect I can find a way to check this and handle it.

    I then create a form that inputs all of those variables into the input fields as the default.

    All of the above is in a xxxx.php file that also creates a shortcode for the above function. I created a WP Page titled Edit My Profile and added the shortcode. All is well until it comes time to submit any changes the member has made. So far I have been unable to get the form data to go anywhere that I can view it, edit it, or manipulate it. If I can get the output somewhere, then I believe I can extract it and process the data back into the database table via $wpdb.

    Alternatively, as I mentioned before is to not have a ‘Submit’ function inside the table at all, but rather add a normal HTML input button immediately following the form which can be made to execute a javascript function. I’ve never worked with javascript before, but have been doing some research and it doesn’t seem like a mountain too tall to climb, and I may just bite the bullet and go this direction, although I suspect in time, I will need to learn both approaches. I don’t know if I can use the WP $wpdb object from within javascript, or whether it would just be easier to connect to the database directly and use SQL to update the table values.

    Thanks for your assistance. And if you can recommend any tutorials that explain the ins and outs of simple WP database manipulation it would be greatly appreciated. The coding is rather simple, it’s just another language, the logic is all the same and with time you can get the syntax correct. The big hurdle for me is understanding how to manipulate all the wordpress functions and capabilities.

    Moderator bcworkz

    (@bcworkz)

    The reason for the page template is it is an easy, compatible way to get the WP environment loaded upon a form submit. If this is not done, you cannot use WP resources like $wpdb. If your form is already on its own WP page, you can copy your theme’s page.php template into a new file, then add the form handling code to this new file. Also change the header comment to the format suggested in the article I previously linked. Edit your form page to use this template instead of the default. Your form’s action attribute should be empty so it submits to the same page. This way you can add form handling code without the need to add any extra pages. Additionally, any messages can be displayed on the same page as the form.

    You cannot use $wpdb from JavaScript. JavaScript runs in the browser, $wpdb runs on your server. The two can only communicate over HTTP. If you are going to get into JavaScript, you can submit form data using Ajax techniques (and forget the page template approach). Using Ajax within WP has a few quirks beyond normal Ajax. It’s rather tricky for novices to get working at first, but once you get it working and understand how it works, it’s a very useful technique that makes for a good user experience. I advise starting small with a basic information exchange. Don’t try to handle your entire form the first time through — too many chances for confusing errors that don’t really relate to Ajax itself working.

    A basic overview of Ajax in the WP environment con be found in the Plugin Handbook.

    About email addresses. I would advise that your form handling code simply update the WP version of email and that you do not maintain a separate copy on your table. You need to relate your table’s users to WP users anyway, so queries can include both tables joined. It’s a bad data schema that has redundant data. Each field of data should only appear in one place so different versions don’t have to be synced.

    Thread Starter gshell

    (@gshell)

    bcworkz,
    Thanks for tolerating my lack of knowledge, but I am beginning to understand more things. Since the form code states to ‘post’ data via an ‘action’ = some URL page, I expected to be able to see it. From what I understand now, the submit simply creates an HTTP request on the server that can not be viewed directly. I still can not get it to work. Here is what I’ve done:
    I created a new page in WP called action_php.php. I created a template page called template-with-simple-form.php in my child theme folder. The form code in that template looks like this:
    When I first attempted it I was using action=”/action_php.php”, but I kept getting an error message that said URL not found, so I hardcoded the full URL with what was actually displayed in my browser.

    /* Start the Loop */
    while ( have_posts() ) : the_post();
    get_template_part( 'template-parts/post/content', get_post_format() );
    // If comments are open or we have at least one comment, load up the comment template.
    if ( comments_open() || get_comments_number() ) :
    comments_template();
    endif;
    ?>
    <!DOCTYPE html>
    <html>
    <body>
    <h2>HTML Forms</h2>
    <form action="http://localhost:81/wordpress/action_page-php/">
      First name:<br>
      <input type="text" name="firstname" value="Mickey">
      <br>
      Last name:<br>
      <input type="text" name="lastname" value="Mouse">
      <br><br>
      <input type="submit" value="Submit">
    </form> 
    <p>If you click the "Submit" button, the form-data will be sent to a page called "/action_page.php".</p>
    </body>
    </html>
    <?php
    endwhile; // End of the loop.

    I then created a new page using this template. All looked fine and ‘submit’ seemed to work. At least there were no error messages.

    I added the following function to functions.php in my child theme.

    function my_test_function() {
    ?>
    <!DOCTYPE html>
    <html>
    <body>
    Welcome <?php echo $_POST["firstname"]; ?><br>
    Your last name is: <?php echo $_POST["lastname"]; ?>
    </body>
    </html> 
    <?php
    }
    add_shortcode( 'My-Test-Code', 'my_test_function');

    I placed the shortcode on a new page. It displayed the text strings properly, but did not have any data where the form values of firstname and lastname should have been echoed from $_POST.

    How does $_POST know which URL the submitted data is to be found? Clearly each form can have a different action=URL.

    What am I missing?

    I am not entirely sure the problem is with the code. A while back I installed Ultimate Member on an initial localhost environment and I also had problems getting any of their forms to update data. That may be related or not. This is a completely different install of WP.

    Moderator bcworkz

    (@bcworkz)

    I can tell you are truly interested in learning. I like that 🙂 I’ll do whatever I can to help you along. You are clearly misunderstanding what is going on, but I’m not sure exactly in what way, so it’s hard to set you straight. The best I can do is explain what’s going on and maybe that will help you get to a clearer understanding.

    $_POST itself does not know the URL in which to “find” data. It doesn’t need to because the data is part of the HTTP POST request, not the destination. All $_POST is doing is telling the current script what data was sent by the form. The PHP script can discover its own URL from data in the $_SERVER array, but there is normally no need. The particular code is running because a specific URL was requested. If your form POSTed to a different URL, any code at that location will be running and not the code at the URL we are currently talking about. That different URL still gets the data sent with the request, still contained in $_POST.

    I’m assuming your intention is to eventually save the submitted data somewhere in the WP database. This is not a given, there are forms that relay information that never save the form data. For example, a imperial to metric units converter would only display the calculated result, it wouldn’t save the input data anywhere, it merely acts upon the data. What you have now is merely acting upon the data, but not saving it.

    The reason $_POST isn’t showing submitted data is you do not specify a method in the form tag, so it defaults to GET. Your form tag should be
    <form action="http://localhost:81/wordpress/action_page-php/" method="POST">

    Before you do that, maybe things will make more sense if you stick with your form’s default GET method for a while. The receiving PHP shortcode does not work now because data is not in $_POST. If you change the shortcode occurrences of $_POST to $_REQUEST, it’ll work for either GET or POST requests. $_REQUEST can introduce some security weaknesses if the sever is not well configured, so it’s not always the best choice, but for this, its flexibility is useful.

    When one clicks the submit button on a form using the GET method, the browser assembles a HTTP request that looks something like localhost:81/wordpress/action_page-php/?firstname=Mickey&lastname=Mouse. As you can see, the form data is part of the URL. Look at your browser’s address bar after submitting the form. You might need to scroll to the end to see it all, but you will see that the URL is similar to my example. The same sort of thing happens with a POST request, except the data is not so visible (often an important advantage). Even if you cannot see POSTed data, rest assured it is being sent as part of the HTTP request.

    When PHP starts up when a GET request comes in, it sees the data in the URL’s query string and parses the data into $_GET and $_REQUEST arrays, which your code can then access. A similar thing happens with POST requests, except $_POST is populated instead of $_GET. We have the browser assembling form data into a request and sending it; and PHP receiving the request and parsing data into arrays; this all pretty much happens automatically. You don’t have to do anything except click submit for all this to happen.

    That’s the end of what’s automatic, anything else you want done needs to be coded. Outputting information and/or saving data to the DB must be coded. Once you understand what is happening with GET, you should change the method to POST so we can make use of another POST advantage. From the request type, our code can decide how to proceed. For GET requests, display the form. For POST requests, process the submitted form data. This is how a single PHP template can handle both displaying the form and processing the submittal. There’s nothing wrong with using a different page to process form data. It depends on what the user experience should be.

    Which do you prefer? Everything handled on one template, or submit to a different page having your shortcode? Your intention is to save the data? If so, you should only allow logged in users to do this. We can add that check in later, but don’t forget to do so! Do you have a particular place where you want to save the data? If you require users be logged in and you are collecting user related data, it usually makes sense to save data in usermeta.

    I realize that for now you are only working with hypothetical data as part of the learning process, but you likely have something more specific in mind for the future? If you are going to save data, it may as well be related to your eventual goal. No point in saving to usermeta if your eventual goal is not user related.

    Thread Starter gshell

    (@gshell)

    Viola! Finally got it to work. I don’t know how to thank you. I believe I now understand better what is going on. I was thinking that ‘submit’ or ‘save’ was actually storing data somewhere that could be viewed, edited, or manipulated later. In fact, the data appears to be simply appended to the communication string between the client and server (HTTP request). Since the data values are appended to the request sent to the server, the server (via php) can strip out the data for it’s own processing if needed. Am I even close to right?

    I was confused by the form action=”xxxx” command requiring a ‘valid URL’. That made me think the data was actually going to that URL. It isn’t. It’s just tagging along with a request to display that URL and if you want the data to physically show up in that URL, you can add some php code to process the data that was tagging along and display it, or do whatever you want with it. Now I can trash the output pages and simply use action=”” to return to the current page, have the php code process the data, and append some text to the page content like “Your Profile Has Been Updated”.

    I understand the error about omitting the method statement in the form. If I hadn’t been so frustrated, I should have caught that. Probably came from simply copying working code from W3Schools examples without looking closely at what they were doing. Just lazy on my part.

    Now that I understand more of what is happening with ‘submit’ I want to think about how I process the data. I suspect it will all be in one template. I was just using the shortcode approach to verify that I was getting data somewhere.

    Yes, all of this is being done on pages that are member only. Presently the menus don’t show up unless the user is logged in, but I plan to additional verification check at the beginning of each function later that confirms the user is logged in (just in case someone accesses the pages without being logged in). For this particular task (editing the member’s profile data). I plan to put the data into a database table called wp_club_members that I have created with phpmyadmin. I could have added necessary columns to the wp_users table, or the usermeta table, but I didn’t want to mess around with the WP default tables until I was sure I knew what was going on. I didn’t want to mess things up. Much easier to just dump my own table and start over than screwing up one of the WP default tables. However, there will be similar functions I want to create later that may go into different tables or maybe go directly to a different page.

    I do have one question. What is the advantage of creating a template page for the form input versus simply writing a function that creates the form? Then assign it a shortcode and add that shortcode to a new page. This form page (Edit My Profile) is only going to be used one time on one page. I think of a template as something I plan to use in more than one place for a number of similar pages. For instance I already created a template page that removes the column options and sidebar in the twentyseventeen theme, as any page that needs to display a large table of information needs to use all the space it can whereas a blog post or other pages look much better in the twenty seventeen default format. I suspect I will use that template several times.

    Again, I want to thank you for all the time you have spent on this. I will keep you informed as to my progress. I am sure there will be other hurdles to overcome. I appreciated the link regarding AJAX. Long term I am sure that will become something I want to learn as well. Thank you! Thank you! Thank you!

    Moderator bcworkz

    (@bcworkz)

    🙂 ding ding ding A winner! It’s like a light bulb went on and suddenly all was clear. I’m so happy that you’ve come to an understanding. Struggling at first to understand what’s really happening is common, I’ve had a similar experience and helped a number of others through as well.

    WP elements are assigned names so we can talk about them, but really they are abstract elements to be used as we see fit. Posts don’t have to be blog posts. “Thumbnails” don’t have to be small. Templates are useful even if used once. Think of it as an alternative to shortcodes, though shortcodes were meant to be used multiple times as well. Not my best analogy. Either way is equally valid. I tend to prefer templates for major output, shortcodes for more minor output. Anyway, what templates are is a convenient way to run PHP within the WP environment. Reusable templates are the obvious use, but running custom code for one page is perfectly valid. There aren’t very many correct ways you can make an HTTP request that runs custom code within WP. The others are trickier to code for, templates are the most accessible for understanding IMO.

    Sending requests through wp-admin/admin-post.php is the other choice besides templates and Ajax. It’s a great option, actually, but you almost need to know Ajax to know how to use it, or at least be very comfortable with how WP action hooks work. Even if you were up to speed with actions (maybe you are, IDK), if the response should include all the usual theme chrome — headers, footers, menus, etc., you may as well go the template route anyway.

    Truth be told, Ajax is probably the best approach for your situation, but it’s likely going to result in more frustration before you can get it working for you. I’d advise to first get your code working as a template. At some point most of that code can be converted to Ajax once you are more comfortable with it.

    A precursor to understanding Ajax in WP is understanding WP action and filter hooks. Now that you’re lined out with form data, if you are interested in advancing your WP skills, I’d say getting your head wrapped around hooks is time well spent.

    Thread Starter gshell

    (@gshell)

    I feel like I am learning to play the piano and have found 8 keys in a single octave. I can plunk out a melody, but it isn’t vey rich and there are another 80 keys that I have no idea where they are or what they sound like. Anyway those 8 keys will help me plunk out a few more melodies until I hit the next hurdle or decide to explore what some of the other keys do.

    I wound up using one page for the input form and a second to process the data. Given the page approach I am using, I could make a single page update the database table but it didn’t update the input form page the user was viewing until you refreshed that page. From what I have read, that is where the AJAX approach would be more useful. I’ll read up on that and I also have access to another plugin code, which I understand how it works on the user side, that does something slightly similar (at least it reads and writes to the database tables) that uses the AJAX approach that will be of help in that learning process.

    Anyway, I have the site working functionally where I can retrieve and update values in the SQL database table, and it is not too ‘clunky’ from the user perspective. That will allow me to do a lot of what I want to do near term.

    Again, thank you for all your help explaining how this worked. In all the reading and research I had done, nothing or no one explained it as well as you did.

    Moderator bcworkz

    (@bcworkz)

    You’re welcome! I’m glad my efforts were helpful.

    FWIW, submitting the form to the same page will cause the form to reload, but you have to code the data saves to happen before the form is output so that getting the DB values for the form will be getting updated data. Better yet, if $_POST data exists, populate the form from that, otherwise get it from the DB. It saves DB queries this way.

    It is possible to save data without reloading the form, but you are correct, Ajax is required to avoid reloads. But two pages is fine, nothing wrong with that. It is the most understandable and intuitive approach.

    When you’re ready to explore some of those other piano keys, I’ll leave you with these resources:
    https://developer.wordpress.org/plugins/hooks/
    https://developer.wordpress.org/plugins/javascript/

Viewing 15 replies - 1 through 15 (of 16 total)
  • The topic ‘Submit Form Data to database’ is closed to new replies.