0

I am developing a Wordpress plugin in an object oriented way, and I would like to read data from the wordpress database using the global $wpdb variable.

The global $wpdb variable is called from within one specific Class method. The Class is defined in the plugin editor but the object in itself is instanciated in the header.php file of my theme.

This method successfully echoes HTML I have hard-coded but the data inbetween which should have been readen from the $wpdb is not echoed.

Thank you in advance for your help !

EDIT : here is the code :

Class Custom_Header 
{
public function print_header()
    {
    if ( isset($_SESSION['header']) )
    {
    switch ($_SESSION['header'])
        {
            case 1:
            {
            global $wpdb;
            $wpdbinfo = $wpdb->get_results("SELECT * FROM bo_mytable WHERE id=3");
            $content="<div>".$wpdbinfo->nameinfo."</div>";
            return $content;
            }
        }
     }
     }
}

Then in header.php :

$custom_header = new Custom_Header();
echo $custom_header->print_header();

As mentioned above I can see that the DIV has been correctly echoed but the content inside did not :-(.

  • Going to have to see the code. – Andrew Bartel Oct 2 '14 at 20:18
  • And what do you get if you var_dump $wpdbinfo? – Andrew Bartel Oct 2 '14 at 20:50
4

I think the problem might lie in:

$wpdbinfo = $wpdb->get_results("SELECT * FROM bo_mytable WHERE id=3");

$wpdb->get_results() returns an array of objects, yet you are referencing a property on $wpdbinfo (->nameinfo). You'll either want to loop through the $wpdbinfo array, or if you're certain you'll get only a single record (possibly a safe assumption if id is a primary key), you would instead call your query using $wpdb->get_row().

3

As said in Codex, wpdb::get_results():

the function returns the entire query result as an array

(bold mine)

So, your $wpdbinfo is not an object, but an array, and if you had turn on WP_DEBUG, your code had thrown a warning.

When you need one single row form db, use wpdb::get_row() and when you need a single variable (like in your example) use wpdb::get_var().

Example:

class Custom_Header {

  private $db;

  function __construct() {
    $this->db = $GLOBALS['wpdb'];
  }

  public function print_header() {
    if ( ! isset( $_SESSION['header'] ) ) {
      return;
    }
    switch ( $_SESSION['header'] ) {
      case 1:
        $nameinfo = $this->db->get_var( "SELECT nameinfo FROM bo_mytable WHERE id=3" );
        return printf( "<div>%s</div>", esc_html( $nameinfo ) );
    }
  }
}

If this doesn't work, be sure that $_SESSION['header'] is set and is equal to 1.

Finally, you should avoid hardcoding table names in your code, because db prefix can easily change.

Once you are coding using OOP approach, and seems you are using custom tables, you would mind to create a custom class to wrap wpdb and setup your tables with right prefix.

Example

<?php 
namespace MyPlugin;

class MyDb {

  private static $instance;
  /** @var array $tables Custom table names, without prefix */
  private static $tables = array( 'my_table_1', 'my_table_2', 'my_table_3' );
  private $db;

  /**
   * Makes an instance of this class accessible from anywhere
   */
  static function instance() {
    if ( is_null( static::$instance ) ) {
       $class = get_called_class();
       static::$instance = new $class;
    }
    return static::$instance;
  }

  /**
   * Proxies all method calls to wpdb
   */
  function __call( $name, $args ) {
    return call_user_func_array( array( $this->db, $name ), $args );
  }

  /**
   * Proxies all property access to wpdb
   */
  function __get( $name ) {
    return $this->db->$name;
  }

  function __construct() {
    $this->db = $GLOBALS['wpdb'];
  }

  /**
   * Set custom table names in wpdb
   */
  function prepareTables() {
    foreach ( static::$tables as $table ) {
      $wpdb->$table = $this->db->prefix . $table;
    }
  }
}

Now somewhere in your plugin you can:

add_action( 'plugins_loaded', function() {
   $mydb = MyDb::instance();
   $mydb->prepareTables();
   if ( is_multisite() ) {
     add_action( 'switch_blog', function() use($mydb) {
       $mydb->prepareTables();
     } );
   }
} );

In this way first your custom tables are set as wpdb properties, and in case of multisite the setting is updated when blog is switched.

Now, your custom header class, becomes something like:

<?php 
namespace MyPlugin;

class Custom_Header {

  private $db;

  function __construct( MyDb $db ) {
    $this->db = $db;
  }

  public function print_header() {
    if ( ! isset( $_SESSION['header'] ) ) {
      return;
    }
    switch ( $_SESSION['header'] ) {
      case 1:
        // note how table name is dynamic 
        $q = "SELECT nameinfo FROM {$this->db->mytable} WHERE id=3";
        $nameinfo = $this->db->get_var( $q );
        return printf( "<div>%s</div>", esc_html( $nameinfo ) );
    }
  }
}

And in your header.php

$custom_header = new MyPlugin\Custom_Header( MyPlugin\MyDb::instance() );
echo $custom_header->print_header();

Please note that code above require PHP 5.3+

  • Thank you for your answer (yet it is a little complicated to me at the moment :-D) You said that it can be useful in the case the prefix of my tables have to change ? I see you are using this method in order to handle multisite has well... in my case the site is only "monosite"... is there still a real risk that my tables prefix have to change in the future ? Can you provide me a link in order to learn more about your OOP style in Wordpress ? Thank you :-) – user54952 Oct 6 '14 at 13:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.