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