The fetch_data() Method
The fetch_data() method is the core of your custom data source. It fetches your data and returns it in a format that Alpha Insights can understand and display.
Method Signature
public function fetch_data( $filters, $data_warehouse = null )
Parameters
$filters (array)
An array of filters passed from the report configuration. Common filters include:
date_from(string): Start date in Y-m-d format (e.g., ‘2024-01-01’)date_to(string): End date in Y-m-d format (e.g., ‘2024-12-31’)date_format_display(string): Date grouping format – ‘day’, ‘month’, ‘quarter’, or ‘year’- Additional custom filters may be present based on widget configuration
Example:
array(
'date_from' => '2024-01-01',
'date_to' => '2024-12-31',
'date_format_display' => 'month',
// Custom filters specific to your implementation...
)
$data_warehouse (WPD_Data_Warehouse_React|null)
The data warehouse instance provides access to helper methods and other entity data. This parameter is crucial for proper date alignment and accessing shared functionality.
Important: Always validate that the data warehouse is available before using it:
if ( ! $data_warehouse || ! method_exists( $data_warehouse, 'get_data_by_date_range_container' ) ) {
// Return empty structure
return array( ... );
}
See Data Warehouse API Reference for available methods.
Return Value
Must return an array with the following optional keys (all keys are optional, but must match the structure if provided):
array(
'totals' => array(...), // Aggregated totals/metrics
'categorized_data' => array(...), // Data grouped by categories
'data_table' => array(...), // Tabular data for data table widgets
'data_by_date' => array(...), // Time-series data keyed by date
'total_db_records' => 0, // Number of records fetched
'execution_time' => 0.0 // Execution time in seconds
)
Data Structure Details
totals (array)
Aggregated totals/metrics. Keys are metric names, values are numeric values.
'totals' => array(
'total_custom_metric' => 1250.50,
'total_custom_count' => 42,
'average_custom_value' => 29.77,
'custom_percentage' => 15.5,
)
Important: Metric keys here must match keys defined in get_data_mapping() ‘totals’ section.
categorized_data (array)
Data grouped by categories for pie charts, doughnut charts, bar charts, etc. Structure:
'categorized_data' => array(
'category_key' => array(
'label' => 'Category Display Name', // Optional: display name
'total_custom_metric' => 500.25, // Metric values
'total_custom_count' => 15,
// Additional metrics...
),
'another_category' => array(
'label' => 'Another Category',
'total_custom_metric' => 750.75,
'total_custom_count' => 20,
),
)
Notes:
- Category keys (e.g., ‘category_key’) are used in widget configurations
- The ‘label’ key is optional but recommended for better display
- Metric keys inside each category must match ‘value’ keys in
get_data_mapping()‘categorized_data’ ‘metric_fields’
data_table (array)
Tabular data for data table widgets. Structure:
'data_table' => array(
'table_key' => array(
array(
'id' => 1,
'name' => 'Item 1',
'value' => 125.50,
'category' => 'category_a',
'date' => '2024-01-01',
),
array(
'id' => 2,
'name' => 'Item 2',
'value' => 250.75,
'category' => 'category_b',
'date' => '2024-01-02',
),
// More rows...
),
)
Notes:
- Table keys (e.g., ‘table_key’) must match keys in
get_data_mapping()‘data_table’ section - Each array element is a table row
- Column keys should match column definitions in the mapping
- Use data table limits for performance (see Data Warehouse API Reference)
data_by_date (array)
Time-series data keyed by date. This is used for line charts, area charts, and time-based bar charts.
CRITICAL: Always initialize metrics using the date range container from the data warehouse to ensure proper date alignment:
$date_range_container = $data_warehouse->get_data_by_date_range_container();
'data_by_date' => array(
'metric_key' => $date_range_container, // Initialize with container
// Then populate with your data
)
Complete example:
$date_range_container = $data_warehouse->get_data_by_date_range_container();
$data_by_date = array(
'total_custom_metric_by_date' => $date_range_container,
'total_custom_count_by_date' => $date_range_container,
);
// Populate with actual data
foreach ( array_keys( $date_range_container ) as $date_key ) {
// Fetch or calculate your data for this date
$data_by_date['total_custom_metric_by_date'][ $date_key ] = /* your value */;
$data_by_date['total_custom_count_by_date'][ $date_key ] = /* your value */;
}
Why use the date container?
- Ensures all dates are present (even if you have no data for a date)
- Matches date format and range used by other data sources
- Prevents chart rendering issues with missing dates
- Respects date grouping (day, month, quarter, year) from filters
Important: Metric keys must match keys defined in get_data_mapping() ‘data_by_date’ section.
total_db_records (int)
The number of database records processed. Used for performance tracking and debugging.
'total_db_records' => 150
execution_time (float) – AUTOMATICALLY TRACKED
DO NOT include this in your return array. Execution time is automatically measured and added by the data warehouse.
The data warehouse automatically tracks execution time by:
- Recording
microtime(true)before calling yourfetch_data()method - Recording
microtime(true)after your method returns - Calculating the difference and storing it in the data structure
You do not need to manually track or return execution time. If you include it in your return array, it will be ignored and replaced with the automatically calculated value.
memory_usage (int) – AUTOMATICALLY TRACKED
DO NOT include this in your return array. Memory usage is automatically measured and added by the data warehouse (in bytes).
The data warehouse automatically tracks memory usage by:
- Recording
memory_get_usage(true)before calling yourfetch_data()method - Recording
memory_get_usage(true)after your method returns - Calculating the difference (memory used during execution) and storing it in the data structure
This provides accurate memory consumption metrics for performance monitoring and debugging.
Performance Metrics (Automatic)
Important: You do NOT need to manually track performance metrics. The data warehouse automatically tracks:
- execution_time – Execution time in seconds (float)
- memory_usage – Memory consumed during execution in bytes (int)
These metrics are automatically measured before and after your fetch_data() method is called and are automatically added to the stored data structure. Do not include them in your return array.
Best Practices
1. Always Validate Data Warehouse
if ( ! $data_warehouse || ! method_exists( $data_warehouse, 'get_data_by_date_range_container' ) ) {
return array(
'totals' => array(),
'categorized_data' => array(),
'data_table' => array(),
'data_by_date' => array(),
'total_db_records' => 0,
'execution_time' => microtime( true ) - $start_time,
);
}
2. Use Date Range Container for data_by_date
Always initialize time-series metrics with the date range container:
$date_range_container = $data_warehouse->get_data_by_date_range_container();
$data_by_date['my_metric'] = $date_range_container;
// Then populate with data
3. Don’t Track Performance Metrics
Execution time and memory usage are automatically tracked. Do not include them in your return array:
// DON'T do this:
return array(
'totals' => $totals,
'execution_time' => microtime( true ) - $start_time, // ❌ Don't include
'memory_usage' => $memory_used, // ❌ Don't include
);
// DO this instead:
return array(
'totals' => $totals,
// execution_time and memory_usage are automatically added
);
4. Use Prepared Statements for Database Queries
global $wpdb;
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}my_table WHERE date >= %s AND date
5. Handle Errors Gracefully
try {
// Fetch data
$data = fetch_from_api();
} catch ( Exception $e ) {
// Log error and return empty structure
error_log( 'Custom data source error: ' . $e->getMessage() );
return array(
'totals' => array(),
// ... other empty arrays
'execution_time' => microtime( true ) - $start_time,
);
}
Complete Example
public function fetch_data( $filters, $data_warehouse = null ) {
$start_time = microtime( true );
// Validate data warehouse
if ( ! $data_warehouse || ! method_exists( $data_warehouse, 'get_data_by_date_range_container' ) ) {
return array(
'totals' => array(),
'categorized_data' => array(),
'data_table' => array(),
'data_by_date' => array(),
'total_db_records' => 0,
'execution_time' => microtime( true ) - $start_time,
);
}
// Get date range
$date_from = isset( $filters['date_from'] ) ? $filters['date_from'] : date( 'Y-m-d', strtotime( '-30 days' ) );
$date_to = isset( $filters['date_to'] ) ? $filters['date_to'] : date( 'Y-m-d' );
// Get date range container
$date_range_container = $data_warehouse->get_data_by_date_range_container();
// Fetch data from database
global $wpdb;
$results = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}my_table WHERE date >= %s AND date 0,
'total_count' => 0,
);
// Build data_by_date
$data_by_date = array(
'metric_by_date' => $date_range_container,
'count_by_date' => $date_range_container,
);
// Process results
foreach ( $results as $row ) {
// Update totals
$totals['total_metric'] += floatval( $row->metric_value );
$totals['total_count']++;
// Update data_by_date
$date_key = date( 'Y-m-d', strtotime( $row->date ) );
if ( isset( $data_by_date['metric_by_date'][ $date_key ] ) ) {
$data_by_date['metric_by_date'][ $date_key ] += floatval( $row->metric_value );
$data_by_date['count_by_date'][ $date_key ]++;
}
}
// Calculate execution time
$execution_time = microtime( true ) - $start_time;
// Return data structure
// NOTE: execution_time and memory_usage are automatically tracked and added
return array(
'totals' => $totals,
'data_by_date' => $data_by_date,
'total_db_records' => count( $results ),
// execution_time and memory_usage are automatically added - don't include them
);
}
Related Documentation
- The get_data_mapping() Method – Map your data for React display
- Data Warehouse API Reference – Available helper methods
- Examples – Real-world implementation examples