4

I am working on a plugin the needs to create a database and insert data into it, I have the table creating part done, but there is an error whenever I try and use $wpdb to insert data saying that insert() could not be called on a null object.

Here is a minimal version:

<?php
/*
Plugin Name: Test
*/

function activation() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'testing';
    $charset_collate = $wpdb->get_charset_collate();

    # create table
    if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
        $sql = "CREATE TABLE " . $table_name . " (
          id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
          name TEXT NOT NULL,
          PRIMARY KEY  (id)
        ) " . $charset_collate . ";";

        require_once(ABSPATH . "wp-admin/includes/upgrade.php");
        dbDelta($sql);
    }
}

function html($atts) {
    $out = "";
    return "<form action='wp-content/plugins/test/submit.php' method='post'><input type='text' name='name'><input type='submit' name='submit'></form>";
}

# setup and cleanup hooks
register_activation_hook(__FILE__, "activation");
add_shortcode('testing', 'html');

Here is the form submit file:

<?php

function handle() {
    global $wpdb;

    if (isset($_POST['submit'])) {
        $wpdb->insert('wp_testing', array('name' => "test"));
    }
}

handle();

I read this question: $wpdb is null even after 'global $wpdb and it is pretty unclear, but seems to indicate that $wpdb must be used within a function, so I wrapped it in one. Any ideas on why this is?

Community
  • 1
  • 1
Jacob Morris
  • 75
  • 1
  • 6

1 Answers1

7

fix If you post a form directly to a PHP file without loading WordPress, none of its functions will be available unless you require wp-load.php. This is why add_action and $wpdb were undefined.

See the comments below and the original answer for details and other ways to post forms in WordPress.

original answer You don't seem to have the handle() function tied to any hook so it's loading and running as WordPress is including the necessary files, but before it actually loads up $wpdb. That's why $wpdb is not defined - it doesn't exist yet. Try this:

<?php
function handle() {
  global $wpdb;

  if( isset( $_POST[ 'submit' ] ) ){
    $wpdb->insert( 'wp_testing', array( 'name' => 'test' ) );
  }
}

//handle();
add_action( 'init', 'handle' );

I'd also consider prefixing the handle() function (or better yet, wrap it in a class) to avoid naming collisions. Something like:

<?php
function jacob_morris_handle() {
  global $wpdb;

  if( isset( $_POST[ 'submit' ] ) ){
    $wpdb->insert( 'wp_testing', array( 'name' => 'test' ) );
  }
}

//handle();
add_action( 'init', 'jacob_morris_handle' );

or

<?php
class JacobMorris {
  function handle() {
    global $wpdb;

    if( isset( $_POST[ 'submit' ] ) ){
      $wpdb->insert( 'wp_testing', array( 'name' => 'test' ) );
    }
  }

  function __construct(){
    add_action( 'init', array( $this, 'handle' ) );
  }
}
new JacobMorris();
I'm Joe Too
  • 5,468
  • 1
  • 17
  • 29
  • The names are just for this minimal example, I have more unique names in the actual project. Do that gives me this error `Call to undefined function add_action() `. This file should only ever be run whenever the form is submitted, so wouldn't the global be loaded at that point? – Jacob Morris Feb 17 '17 at 02:20
  • If `add_action` is undefined, WordPress isn't loading up and it's an issue elsewhere. And yes - using the hook would mean that it's LISTENING globally on every page load, but your if statement is what would tell it to RUN when the form is submitted. The only way to not listen globally would be to switch it to an ajax call and post your form via ajax. – I'm Joe Too Feb 17 '17 at 02:24
  • 1
    so by adding `require('path/to/wp-load.php') and switching back to just running `handle()` I got it to work. If I tried it with the `add_action` the function was never getting executed. – Jacob Morris Feb 17 '17 at 02:40
  • That means WordPress isn't loading up properly. Is this a plugin you're creating and, if so, are you testing it through WordPress or trying to visit the php file directly? – I'm Joe Too Feb 17 '17 at 02:44
  • I have WampServer setup and I am running WordPress on it – Jacob Morris Feb 17 '17 at 02:52
  • Question: is your form posting directly to the PHP file? – I'm Joe Too Feb 17 '17 at 02:59
  • Yes, it posts directly to it – Jacob Morris Feb 17 '17 at 03:19
  • That's the problem. If you post directly to a PHP file, it's direct - it's not being called through WordPress. That's why `add_action` and `$wpdb` (and any other WordPress function) do not exist and why your solution with the `require` is needed. I don't know what your plugin is doing so I can't say where you should post it, but this at least explains why you were having trouble. – I'm Joe Too Feb 17 '17 at 03:23
  • That makes sense, do you want to update your answer so I can accept it? – Jacob Morris Feb 17 '17 at 04:04