WordPress stores its data in a MySQL database — posts, pages, users, settings. But what if your business data lives somewhere else? Maybe you have a CRM running on a separate MySQL server, inventory in PostgreSQL, or a custom application with its own database.
This guide covers three methods to connect WordPress to external databases.
Why Connect to an External Database?
Common use cases:
- Business reporting — Display sales data, inventory levels, or customer metrics on your WordPress dashboard
- Data portals — Let customers or partners view their own data through your WordPress site
- Legacy system integration — Connect to existing databases without migrating data
- Multi-system dashboards — Combine data from CRM, ERP, and other systems in one place
The key challenge: WordPress doesn't natively support connecting to external databases. The built-in $wpdb object only connects to your WordPress database.
Method 1: Custom PHP Code (PDO)
PDO (PHP Data Objects) is the modern way to connect to databases in PHP. It supports MySQL, PostgreSQL, SQLite, and more.
<?php
function get_external_db_connection() {
static $pdo = null;
if ($pdo === null) {
try {
$pdo = new PDO(
'mysql:host=your-server.com;dbname=your_database;charset=utf8mb4',
'username',
'password',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
} catch (PDOException $e) {
error_log('External DB connection failed: ' . $e->getMessage());
return null;
}
}
return $pdo;
}
function get_external_customers() {
$pdo = get_external_db_connection();
if (!$pdo) return [];
$stmt = $pdo->query('SELECT * FROM customers ORDER BY created_at DESC LIMIT 100');
return $stmt->fetchAll();
}
For PostgreSQL, change the DSN:
'pgsql:host=your-server.com;dbname=your_database'
Display Data with a Shortcode
function external_customers_shortcode() {
$customers = get_external_customers();
if (empty($customers)) {
return '<p>No customers found.</p>';
}
$html = '<table><thead><tr>';
$html .= '<th>Name</th><th>Email</th><th>Joined</th>';
$html .= '</tr></thead><tbody>';
foreach ($customers as $customer) {
$html .= sprintf(
'<tr><td>%s</td><td>%s</td><td>%s</td></tr>',
esc_html($customer['name']),
esc_html($customer['email']),
esc_html($customer['created_at'])
);
}
$html .= '</tbody></table>';
return $html;
}
add_shortcode('external_customers', 'external_customers_shortcode');
Pros: Complete control, no plugin dependencies
Cons: Requires PHP knowledge, you handle security, maintenance burden
Method 2: Use a Reporting Plugin (No Code)
If you want external database connections without writing code, a WordPress reporting plugin handles the complexity:
- Visual query builder
- Multiple database type support
- Charts and visualizations
- Built-in security (encrypted credentials, SQL injection prevention)
EverNext Reporting is designed for this. Connect to MySQL, MariaDB, or PostgreSQL, build queries visually or with SQL, and embed reports anywhere with shortcodes.
Pros: No coding, visual builder, built-in security, charts included
Cons: Plugin dependency
Method 3: REST API Integration
If your external system has a REST API, fetch data without a direct database connection:
function fetch_external_api_data() {
$response = wp_remote_get('https://api.example.com/customers', [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY',
],
'timeout' => 30,
]);
if (is_wp_error($response)) {
return [];
}
$body = wp_remote_retrieve_body($response);
return json_decode($body, true);
}
Security Best Practices
1. Use a Read-Only Database User
CREATE USER 'wordpress_reader'@'%' IDENTIFIED BY 'secure_password';
GRANT SELECT ON your_database.* TO 'wordpress_reader'@'%';
2. Use Prepared Statements
// WRONG - vulnerable to SQL injection
$pdo->query("SELECT * FROM users WHERE id = $user_id");
// CORRECT - safe
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
Which Method Should You Choose?
- Custom PHP — Full control, for developers
- Reporting plugin — No-code, with charts and dashboards
- REST API — When direct database access isn't available
Originally published at evernextsolutions.com