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 );
}