This is possible, but you’re going to have to do a lot of custom work to get what you want. If you want all of your postmeta to come from and go to a separate database, you can use these filters:
-
get_{$meta_type}_metadata
– This filter is documented inwp-includes/meta.php
. Returning a non-null value from this filter will short-circuit calls toget_metadata
(used byget_post_meta
). -
update_{$meta_type}_metadata
– This filter is also inwp-includes/meta.php
. Returning a non-null value will short-circuit theupdate_metadata
function, called byupdate_post_meta
. -
add_{$meta_type}_metadata
– Effectively the same asupdate_{$meta_type}_metadata
, except it’s called foradd_post_meta
. -
delete_{$meta_type}_metadata
– Same as all of the above except used to delete metadata.
Using these four filters, you can create a custom connector to another dataset instead of using the wp_postmeta
table.
<?php
class MyCustomData {
public static $instance = null;
private $connection = null;
// Create a singleton instance of our class.
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function __construct() {
$this->init_connection();
$this->hooks();
}
private function init_connection() {
// Do whatever you need to here to create your new database connection.
// For example, you could open a PDO connection... http://php.net/manual/en/pdo.connections.php
$this->connection = new PDO('connection string here');
}
// Define your meta overrides.
private function hooks() {
add_filter( 'add_post_metadata', [ $this, 'add_meta' ], 10, 5 );
update_filter( 'update_post_metadata', [ $this, 'update_meta' ], 10, 5 );
delete_filter( 'delete_post_metadata', [ $this, 'delete_meta' ], 10, 5 );
get_filter( 'get_post_metadata', [ $this, 'get_meta' ], 10, 5 );
}
/**
* From the filter documentation in meta.php
*
* @param null|bool $check Whether to allow adding metadata for the given type.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value. Must be serializable if non-scalar.
* @param bool $unique Whether the specified meta key should be unique
*/
public function add_meta( $check, $object_id, $meta_key, $meta_value, $unique ) {
// There may be cases where you _don't_ want your data going to the remote database.
// If that happens, return null and WP will continue on it's merry way.
if ( ! $this->allow_remote_db_action( $object_id ) ) {
return null;
}
// Whatever logic you need to do here and then...
$result = $this->connection->query('INSERT INTO ...' );
// Returning non-null will stop WP from doing it's own thing.
if ( $result ) {
return $result;
}
// Return null to let WP go on about it's business adding post meta.
return null;
}
/**
* The other three methods are effectively the same structure:
* - Prepare your data
* - Make an action against the remote database.
* - Return null if things didn't go well and you want WP to take over, or non-null
* if you got the result you wanted and don't need WP to do what it was doing.
*/
}
// Kick off our class and set up the filters for post meta.
add_action( 'init', 'MyCustomData::get_instance' );
I strongly advise that you properly “gate” the functions you setup, meaning that you should only be getting and sending what you need to and from the remote database, and allow WordPress to handle the rest of the postmeta. There’s probably some Bad Stuff that can come out of a system like this, so be prepared for headaches and debugging sessions.