PHP Syntax and Runtime
PHP Tags
<?php
$name = 'WordPress';
Use <?php in normal PHP files. Avoid short tags like <? because they may be disabled. In PHP-only files, omit the closing tag to prevent accidental whitespace output.
<?php
function myplugin_boot(): void {
// Code here.
}
In mixed templates, PHP can be embedded in HTML.
<h1><?php echo esc_html(get_the_title()); ?></h1>
Comments
// Single-line comment
/*
* Multi-line comment.
*/
Use comments to explain intent, constraints, and non-obvious behavior. Do not comment every assignment.
Statements and Semicolons
Most PHP statements end with ;.
$count = 10;
echo $count;
Control structures use braces.
if ($count > 0) {
echo 'Has items';
}
Variables and Constants
$title = 'Hello';
$count = 3;
$enabled = true;
define('MYPLUGIN_VERSION', '1.0.0');
const DEFAULT_LIMIT = 10;
In WordPress plugins, constants are often used for paths, URLs, and versions.
define('MYPLUGIN_FILE', __FILE__);
define('MYPLUGIN_DIR', plugin_dir_path(__FILE__));
define('MYPLUGIN_URL', plugin_dir_url(__FILE__));
Output
echo 'Hello';
print 'Hello';
In WordPress, escape before output.
echo esc_html($title);
Control Flow
if ($score >= 90) {
$grade = 'A';
} elseif ($score >= 80) {
$grade = 'B';
} else {
$grade = 'C';
}
switch ($status) {
case 'draft':
$label = 'Draft';
break;
case 'publish':
$label = 'Published';
break;
default:
$label = 'Unknown';
}
match is strict and returns a value. It requires PHP 8+.
$label = match ($status) {
'draft' => 'Draft',
'publish' => 'Published',
default => 'Unknown',
};
Loops
foreach ($posts as $post) {
echo esc_html($post->post_title);
}
for ($i = 0; $i < 10; $i++) {
echo esc_html((string) $i);
}
while ($query->have_posts()) {
$query->the_post();
the_title('<h2>', '</h2>');
}
Alternative Template Syntax
Common in WordPress templates.
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php endwhile; ?>
<?php endif; ?>
Operators
| Operator | Meaning |
|---|---|
+, -, *, /, % | Arithmetic |
. | String concatenation |
= | Assignment |
==, != | Loose comparison |
===, !== | Strict comparison |
&&, ` | |
?? | Null coalescing |
?: | Ternary shorthand |
Prefer strict comparisons unless type coercion is intentional.
Includes
| Statement | Behavior |
|---|---|
require | Fatal error if missing |
include | Warning if missing |
require_once | Require only once |
include_once | Include only once |
Use require_once for required plugin files.
require_once MYPLUGIN_DIR . 'includes/settings.php';
Magic Constants
| Constant | Meaning |
|---|---|
__FILE__ | Current file path |
__DIR__ | Current directory path |
__LINE__ | Current line number |
__FUNCTION__ | Current function name |
__CLASS__ | Current class name |
__METHOD__ | Current class method |
__NAMESPACE__ | Current namespace |
Runtime Settings
| Setting | Purpose |
|---|---|
memory_limit | Max memory per request |
max_execution_time | Max request runtime |
upload_max_filesize | Max uploaded file size |
post_max_size | Max POST body size |
display_errors | Whether errors are printed |
log_errors | Whether errors are logged |
In WordPress, use debug constants.
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Headers and Redirects
Headers must be sent before output.
header('Content-Type: application/json');
In WordPress, prefer helpers.
wp_safe_redirect(admin_url('options-general.php'));
exit;
Common Pitfalls
- Missing semicolon or mismatched braces.
- Echoing before redirect or header changes.
- Closing PHP tags in plugin files and producing whitespace.
- Using a PHP feature unsupported by the server version.
- Calling WordPress conditional tags before the main query exists.
- Registering post types after
init. - Running expensive code on every request.