WordPress Path and URL Constants: plugin_dir_path, get_template_directory, home_url Reference

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.