PHP error_log configuration, Xdebug with VS Code, step debugging, a simple pattern for logging slow queries, and the common error patterns we see across our production sites.
The Debugging Toolkit
When something breaks in production at 2 AM, you need to diagnose and fix it fast. Our debugging toolkit for jekcms has three layers: the PHP error log for catching exceptions, Xdebug for stepping through complex logic, and query timing for finding performance bottlenecks.
PHP Error Log Configuration
jekcms configures error logging based on environment, right in config/config.php:
// Production: log errors, never display
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', LOGS_PATH . '/php-errors.log');
// Development (DEBUG_MODE): display and log
error_reporting(E_ALL);
ini_set('display_errors', 1);
There is no custom logging layer on top of this — jekcms uses plain PHP error_log(), writing to logs/php-errors.log. That file is protected from direct web access. This is deliberately simple: no log rotation daemon, no custom log format to learn, just the standard PHP error log you already know how to read and tail.
Xdebug Setup with VS Code
Xdebug is the standard PHP debugging extension and works with jekcms exactly like it would with any PHP codebase — there is nothing jekcms-specific about the setup:
; php.ini
[xdebug]
zend_extension=xdebug
xdebug.mode=debug,profile
xdebug.start_with_request=trigger
xdebug.client_port=9003
xdebug.client_host=127.0.0.1
In VS Code, install the PHP Debug extension, add a launch configuration for "Listen for Xdebug", set breakpoints in your PHP files, and trigger debugging with the XDEBUG_TRIGGER cookie or query parameter.
Step debugging is invaluable for questions like "why does this post show the wrong category?" Set a breakpoint where the post is queried, step through, inspect variables at each line, and find exactly where the logic diverges from what you expected.
Finding Slow Queries
jekcms's Database class times every query with microtime(true) around the prepare/execute call. If you want production visibility into slow queries beyond what that internal timing gives you for debugging, a simple pattern is to wrap query calls and log anything over your chosen threshold with plain error_log():
$start = microtime(true);
$stmt = $db->query($sql, $params);
$duration = microtime(true) - $start;
if ($duration > 0.5) { // adjust the threshold to your site
error_log(sprintf(
'[SLOW QUERY] %.3fs: %s',
$duration,
$sql
));
}
That writes straight into the same logs/php-errors.log file — no separate log file, no custom logging class, just error_log() with a clear prefix you can grep for.
Common Error Patterns
- 500 Internal Server Error: Usually a PHP syntax error or fatal exception. Check
logs/php-errors.logfirst. - Headers Already Sent: HTML output before a
header()call orsession_start(). Move POST processing before any output. - CSRF Token Mismatch: Session expired or browser back button. Regenerate the token on the form page.
- Session Lost After Login: Cross-site session collision. Check that your session name is unique per site if you run multiple jekcms installs on the same server.
- Images Not Loading: Check file permissions (755 for directories, 644 for files) and verify the uploads path in the database does not have a doubled
uploads/prefix.
Production Monitoring
For production sites, checking logs/php-errors.log regularly catches issues before users report them. A simple approach is a small script — run as a cron job, or scheduled through jekcms's own pseudo-cron if your host does not give you real cron access — that greps the last 24 hours of the log for anything above WARNING level and emails you if it finds something. This is not a built-in jekcms feature; it is a five-minute script worth writing for any production site.