WordPress defines a comprehensive set of path and URL constants and helper functions for locating files, building URLs, and retrieving site metadata — and picking the wrong one for a given context is a frequent source of subtle bugs. The most important distinction is between PHP filesystem paths (absolute paths like /var/www/html/wp-content/plugins/my-plugin/, used for include, file_get_contents, and similar PHP operations) and URLs (like https://example.com/wp-content/plugins/my-plugin/, used in HTML output, HTTP redirects, and enqueuing assets). Using a filesystem path where a URL is expected — or vice versa — causes broken links or PHP errors. A second common confusion is between get_template_directory() (parent theme) and get_stylesheet_directory() (active theme, which may be a child theme), and between the ABSPATH constant (WordPress root) and WP_CONTENT_DIR (wp-content directory).
Problem: A plugin needs to include a PHP file from its own directory, enqueue a CSS file from its assets folder, read a file from the uploads directory, and display the site name and home URL in a template — all without hardcoding any paths.
Solution: Use plugin_dir_path() and plugin_dir_url() for plugin files; get_stylesheet_directory() and get_stylesheet_directory_uri() for theme files; wp_upload_dir() for uploads; and get_bloginfo() or constants for site metadata.
<?php
// ══════════════════════════════════════
// PLUGIN paths and URLs
// ══════════════════════════════════════
// __FILE__ = absolute path to the current file
$plugin_path = plugin_dir_path( __FILE__ ); // /var/www/html/wp-content/plugins/my-plugin/
$plugin_url = plugin_dir_url( __FILE__ ); // https://example.com/wp-content/plugins/my-plugin/
// Include a file from within the plugin
require_once $plugin_path . 'includes/class-my-plugin.php';
// Enqueue a CSS file from the plugin
wp_enqueue_style( 'my-plugin-style', $plugin_url . 'assets/style.css' );
// ══════════════════════════════════════
// THEME paths and URLs
// ══════════════════════════════════════
// get_stylesheet_* = ACTIVE theme (child theme if active, else parent)
get_stylesheet_directory(); // /var/www/html/wp-content/themes/my-child-theme/
get_stylesheet_directory_uri(); // https://example.com/wp-content/themes/my-child-theme/
// get_template_* = PARENT theme always
get_template_directory(); // /var/www/html/wp-content/themes/my-parent-theme/
get_template_directory_uri(); // https://example.com/wp-content/themes/my-parent-theme/
// ══════════════════════════════════════
// UPLOADS directory
// ══════════════════════════════════════
$upload = wp_upload_dir();
// $upload['basedir'] = /var/www/html/wp-content/uploads
// $upload['baseurl'] = https://example.com/wp-content/uploads
// $upload['path'] = basedir + /2020/02 (current month subdir)
// $upload['url'] = baseurl + /2020/02
$file_path = $upload['basedir'] . '/my-plugin/data.json';
$file_url = $upload['baseurl'] . '/my-plugin/data.json';
// ══════════════════════════════════════
// WP CONSTANTS (filesystem, no trailing slash)
// ══════════════════════════════════════
ABSPATH; // /var/www/html/ — WordPress root
WP_CONTENT_DIR; // /var/www/html/wp-content — wp-content dir
WP_PLUGIN_DIR; // /var/www/html/wp-content/plugins — plugins dir
WPMU_PLUGIN_DIR; // /var/www/html/wp-content/mu-plugins
// ══════════════════════════════════════
// SITE METADATA with get_bloginfo()
// ══════════════════════════════════════
get_bloginfo( 'name' ); // Site title
get_bloginfo( 'description' ); // Tagline
get_bloginfo( 'url' ); // Site URL (same as home_url())
get_bloginfo( 'wpurl' ); // WordPress address (same as site_url())
get_bloginfo( 'admin_email' ); // Admin email
get_bloginfo( 'version' ); // WordPress version string
// Preferred alternatives for URLs:
home_url( '/my-page/' ); // https://example.com/my-page/
site_url( '/wp-login.php' ); // https://example.com/wp-login.php
admin_url( 'options-general.php' ); // https://example.com/wp-admin/options-general.php
NOTE: Never hardcode the WordPress directory structure in your plugin or theme. Sites can be configured with WordPress installed in a subdirectory (https://example.com/wordpress/) while serving from the root (https://example.com/), and in this configuration home_url() and site_url() return different values. get_bloginfo( 'url' ) returns home_url(), while get_bloginfo( 'wpurl' ) returns site_url() — use the direct functions, they are more readable. Also note that WP_CONTENT_URL is a constant for the wp-content URL but it is not always defined on every WordPress installation — use content_url() as the function equivalent.