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.