Skip to content

Instantly share code, notes, and snippets.

@ozh
Last active January 10, 2026 17:02
Show Gist options
  • Select an option

  • Save ozh/553c2519878984271584939355e91b8e to your computer and use it in GitHub Desktop.

Select an option

Save ozh/553c2519878984271584939355e91b8e to your computer and use it in GitHub Desktop.
YOURLS plugin : Master and Slave Databases (requires YOURLS 1.10.3+)

Master/Slave DB Setup Listed in Awesome YOURLS!

POC plugin: shows how a YOURLS instance using a Master/Slave DB setup would work.

Requirements:

  • a Master (write) / Slave (read) DB setup, obviously.
  • YOURLS 1.10.3 and above

Installation

Edit the settings in the first function of the plugin to match your setup, then activate the plugin as usual.

License

Do whatever the hell you want with it.

<?php
/*
Plugin Name: MySQL Master & Slave for YOURLS 1.10.3+
Plugin URI: https://gist.github.com/ozh/553c2519878984271584939355e91b8e
Description: Uses a MySQL Master & Slave setup
Version: 0.1
Author: Ozh
Author URI: https://ozh.org/
*/
// Init when plugins load
yourls_add_action('plugins_loaded', 'mysql_master_slave_init');
function mysql_master_slave_init() {
// the WRITE connection is the one used for all write operations (insert, update, delete)
// It should probably be the same as the default YOURLS database settings
// If should handle queries by default if the code in YOURLS doesn't specify the type of connection to use
$write = [
'dns' => 'mysql:host=write.db.domain.com;dbname=my_yourls_DB;charset=utf8mb4',
'user' => 'root',
'pass' => '',
];
// the READ connection is used for read-only operations (select)
// Use settings of your SLAVE database
$read = [
'dns' => 'mysql:host=read.db.domain.com;dbname=my_yourls_DB;charset=utf8mb4',
'user' => 'root',
'pass' => '',
];
MySQL_Master_Slave_Manager::init($read, $write);
}
// Handle database connections
class MySQL_Master_Slave_Manager {
private static $connections = null;
public static function init($read, $write) {
self::$connections = new Aura\Sql\ConnectionLocator();
self::$connections->setDefault(function () use ($write) {
$ydb = new \YOURLS\Database\YDB( $write['dns'], $write['user'], $write['pass'], [], [] );
$ydb->init();
yourls_debug_log('Init default connection');
return $ydb;
});
self::$connections->setWrite('master', function () use ($write) {
$ydb = new \YOURLS\Database\YDB( $write['dns'], $write['user'], $write['pass'], [], [] );
$ydb->init();
yourls_debug_log('Init master connection');
return $ydb;
});
self::$connections->setRead('slave', function () use ($read) {
$ydb = new \YOURLS\Database\YDB( $read['dns'], $read['user'], $read['pass'], [], [] );
$ydb->init();
yourls_debug_log('Init slave connection');
return $ydb;
});
}
public static function getConnections() {
return self::$connections;
}
public static function isInitialized() {
return self::$connections !== null;
}
}
// Intercept all yourls_get_db() calls and use the appropriate connection based on the context
yourls_add_filter('get_db', 'mysql_master_slave_get_db');
function mysql_master_slave_get_db($db, $context) {
if (!MySQL_Master_Slave_Manager::isInitialized()) {
return $db;
}
$connections = MySQL_Master_Slave_Manager::getConnections();
// if $context starts with 'read-', use the read connection
if (strpos($context, 'read-') === 0) {
// log context, but not if the context is 'read-debug_log' which is in function yourls_debug_log(), otherwise infinite loop
if ($context != 'read-debug_log') {
yourls_debug_log('DB context : '. $context . ' - Using read connection');
}
return $connections->getRead();
}
// if $context starts with 'write-', use the write connection
if (strpos($context, 'write-') === 0) {
yourls_debug_log('DB context : '. $context . ' - Using write connection');
return $connections->getWrite();
}
// otherwise, use the default connection
return $db;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment