1

I have a use case where I need to store user_meta for all users including guests. It is just one fairly complex array to deserialise into one value. My instinct is to try and store an array of guest user_meta arrays for user=0 (the theoretical logged out user) with a cookie-key-value and a date-value so I can do clean up on out-of-date guest meta. The idea is to copy that data across should the guest create an account or log in.

Will WordPress allow me to do this and is there any reason I should not do it (or any danger in doing so)? Is there a better approach I have not considered?

Update: Here is a gist of where I have got to. It looks like abusing user=0 is not a good idea. If I come up with anything better, I will update the gist.

Update 2: I solved the problem by literally extending the meta-data system to apply to guests. It 100% uses internal WordPress methods and adds four new functions following the same metadata naming conventions. Here is my untested draft.

  • 3
    The user meta table is intended for registered users, and the add/update/get/delete_user_meta() functions will fail when the user ID is 0. So you might want to do it like how WooCommerce handle customer's sessions - WC has a custom table which stores the session data and the session ID/key (a unique/random customer ID) is saved in the cookies - see WC_Session_Handler. – Sally CJ Aug 4 at 14:33
  • 1
    As @SallyCJ said, it's not its intended use, so do not use it! Unless you want to be miserable in the long run, then misusing architectural aspects of the system, code you use is a great idea. But joking aside, I don't know about the WC sessions, but I think the wpdb class might be a good entry point for your development. There is the codex article »Creating Tables with Plugins« giving an overview on hot to use it. – Nicolai Aug 4 at 14:57
  • Which one of you is going to post what you have told me as an answer so I can close out this question? – Matthew Brown aka Lord Matt Aug 11 at 4:49
  • 1
    @MatthewBrownakaLordMatt Even better, post your own solution with code as answer, it is encouraged. – Nicolai Aug 11 at 12:33
0

It turns out (via comments) that (ab)using user 0 is a really bad idea. However, WordPress is built to allow new things to get meta-tables. Which led me to make Guest Meta as a plugin.

It's available on GitHub as a gist and below in its current form. I have to point out that this is a conceptual solution rather than a fully tested one. Use with my code with caution (the background principles are quite sound).

  <?php
  /*
  Plugin Name: Guest Meta
  Plugin URI: <https://gist.github.com/lordmatt/3bd8f7787fbbe0950f9228dec92f2f8a>
  Description: Enable storing meta data for guests. Keeps cookies small and simple.
  Author: Matthew Brown
  Author URI: http://matthewdbrown.authorbuzz.co.uk/
  Version: 1.1.0
  License: GPLv3 or later
  Text Domain: guest_meta
  */
  /**
   * This is an idea I had to store meta data about guest users as well as regular
   * registered users. In theory, installing this as a plugin will give your other
   * plugins and themes the ability to store guest metadata against a cookie value
   * and not in the cookie which means the data is tamper proof and more trustable
   * in the main.
   * 
   * This untested draft assumes everything I read in the WordPress' documentation 
   * is 100% accurate.
   * 
   * @package     guest_meta
   * @author      Matthew Brown <https://twitter.com/lordmatt>
   * @copyright   (C) 2019 Matthew Brown.
   * @license     http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 
   * @used-by       storyteller.datastore <https://gist.github.com/lordmatt/e6323ae00a39373841344ebb0b49b8fd> 
   * 
   * VERSION: 1.1.0
   * 
   * =======
   * History
   * =======
   * 1.1.0 - Added pass FALSE or 0 as guest-ID and the ID will autoload
   * 1.0.0 - First version. Not tested, yet.
   * 
   * =======
   * License
   * =======
   * 
   * This file is part of guest_meta.
   * 
   * guest_meta is free software: you can redistribute it and/or modify it under 
   * the terms of the GNU General Public License as published by the Free Software 
   * Foundation, either version 2 of the License, or (at your option) any later 
   * version.
   * 
   * guest_meta is distributed in the hope that it will be useful, but WITHOUT ANY 
   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   * 
   * You should have received a copy of the GNU General Public License along with 
   * guest_meta. If not, see http://www.gnu.org/licenses/.
   */
  function guest_meta_install(){
      global $wpdb;
      $table_name = $wpdb->prefix . "guestmeta"; 
      $charset_collate = $wpdb->get_charset_collate();
      $sql = "CREATE TABLE $table_name (
        `meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        `object_id` bigint(20) unsigned NOT NULL DEFAULT '0',
        `meta_key` varchar(255) DEFAULT NULL,
        `meta_value` longtext,
        `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY  (meta_id)
      ) $charset_collate;";
      $sql2 = "ALTER TABLE $table_name
        ADD KEY `comment_id` (`object_id`),
        ADD KEY `meta_key` (`meta_key`(191));";
      require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
      dbDelta( $sql );
      dbDelta( $sql2 );
  }
  register_activation_hook( __FILE__, 'guest_meta_install' );
  add_action( 'init', 'guest_meta_cookie' );
  function guest_meta_cookie() {
      setcookie( 'guest_meta', guest_meta_get_object_id(), 30 * DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
  }
  function guest_meta_get_object_id(){
      if(!isset($_COOKIE['guest_meta'])) {
          $_COOKIE['guest_meta'] = guest_meta_make_id();
      }
      return $_COOKIE['guest_meta'];
  }
  function guest_meta_make_id(){
      global $wpdb;
      $table_name = $wpdb->prefix . "guestmeta";
      guest_meta_drop_old_rows(); // clean up old stuff first
      $results = $wpdb->get_results( "SELECT MAX(object_id) AS almost FROM {$table_name};", OBJECT );
      $newish = $results->almost+1;
      return $newish;
  }
  function guest_meta_drop_old_rows(){
      global $wpdb;
      $table_name = $wpdb->prefix . "guestmeta";
      $sql = "DELETE FROM $table_name WHERE `ts` < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 28 DAY))";
      require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
      dbDelta( $sql );
  }
  function add_guest_meta($object_id=FALSE, $meta_key=FALSE, $meta_value=FALSE, $unique=FALSE){
      if($object_id==FALSE||$object_id<1){
          $object_id = guest_meta_get_object_id();
      }
      return add_metadata( 'guest', $object_id, $meta_key, $meta_value, $unique );
  }
  function get_guest_meta($object_id=FALSE, $meta_key=FALSE, $single=FALSE){
      if($object_id==FALSE||$object_id<1){
          $object_id = guest_meta_get_object_id();
      }
      get_metadata('guest', $object_id, $meta_key, $single);
  }
  function update_guest_meta($object_id=FALSE, $meta_key=FALSE, $meta_value=FALSE, $prev_value=''){
      if($object_id==FALSE||$object_id<1){
          $object_id = guest_meta_get_object_id();
      }
      update_metadata( 'guest', $object_id, $meta_key, $meta_value, $prev_value );
  }
  function delete_guest_meta($object_id=FALSE, $meta_key=FALSE, $meta_value=FALSE, $delete_all=FALSE){
      if($object_id==FALSE||$object_id<1){
          $object_id = guest_meta_get_object_id();
      }
      delete_metadata ( 'guest', $object_id, $meta_key, $meta_value, $delete_all );
  }

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.