The big picture
A WordPress site is made of three parts:
- Files: the WordPress core (PHP), plus your themes, plugins and uploads.
- A database: MySQL or MariaDB, holding content, settings and users.
- A web server with PHP, which runs the code for each request.
When a browser asks for a page, the web server runs WordPress, WordPress reads from the database, and the active theme turns the result into HTML.
Following one request
Suppose someone visits http://localhost:8080/hello-world/, the sample post every new site has. Here is what happens:
- The web server cannot find a real file called
hello-world, so it passes the request to WordPress'sindex.php. index.phploadswp-config.php, which holds the database settings, and then the core (wp-settings.php).- WordPress loads active plugins and then the active theme, letting both attach their code to hooks (covered later in the course).
- WordPress parses the URL. Using the permalink settings, it works out that
/hello-world/means "the post whose slug ishello-world". - It runs a database query for that post.
- It chooses a template from the theme, following the template hierarchy (a later lesson): for a single post, something like
single.htmlorsingle.php. - The template outputs HTML, which goes back to the browser.
You can watch the outcome. This request fetches the page and shows only its title and h1 elements:
GET /hello-world/Hello world! – My WordPress SiteGET /hello-world/Hello world!The browser tab shows "Hello world! – My WordPress Site": the post title, a separator and the site title, produced by the theme. On each page in this course, the site runs at http://localhost:8080, like the local site you will set up in the next lesson.
The files
A WordPress folder looks like this:
wordpress/
├── index.php the front door for every request
├── wp-config.php database settings and site-wide constants (yours)
├── wp-login.php the login screen
├── wp-admin/ the dashboard (core)
├── wp-includes/ the core libraries (core)
└── wp-content/ everything that is yours
├── themes/
├── plugins/
└── uploads/ images and files added through the media libraryThe rule that keeps sites healthy: never edit core files in wp-admin, wp-includes or the root (apart from wp-config.php). Updates replace them, so your changes would vanish, and a mistake there can take the whole site down. Customise WordPress with themes and plugins instead.
wp-config.php is created during installation. Its key lines look like this (with your own values):
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wp_user' );
define( 'DB_PASSWORD', 'a-strong-password' );
define( 'DB_HOST', 'localhost' );
$table_prefix = 'wp_';It also holds security keys and salts used to protect logins, and optional settings such as WP_DEBUG. Treat it like a password file: never share it or commit it to a public repository.
The database
WordPress creates about a dozen tables. This code, run inside WordPress, lists them with the global $wpdb object you will use later in the course:
<?php
global $wpdb;
foreach ( $wpdb->tables() as $name => $table ) {
echo str_pad( $name, 20 ), $table, "\n";
}users wp_users
usermeta wp_usermeta
posts wp_posts
comments wp_comments
links wp_links
options wp_options
postmeta wp_postmeta
terms wp_terms
term_taxonomy wp_term_taxonomy
term_relationships wp_term_relationships
termmeta wp_termmeta
commentmeta wp_commentmetaThe ones you will meet most:
| Table | Holds |
|---|---|
wp_posts |
posts, pages, attachments, menus, templates and custom post types, told apart by post_type |
wp_postmeta |
extra fields attached to posts (custom fields) |
wp_users, wp_usermeta |
accounts and their settings |
wp_options |
site settings, from the site title to plugin options |
wp_terms, wp_term_taxonomy, wp_term_relationships |
categories, tags and other taxonomies |
wp_comments, wp_commentmeta |
comments |
The wp_ part is the table prefix from wp-config.php. Many sites use a different prefix, so code should never assume wp_; $wpdb knows the real names.
Everything in wp_posts
A surprise for many people: much more than blog posts lives in wp_posts. A fresh site already holds several kinds:
<?php
global $wpdb;
$rows = $wpdb->get_results( "SELECT ID, post_type, post_status, post_title FROM {$wpdb->posts} ORDER BY ID" );
foreach ( $rows as $row ) {
printf( "%d %-14s %-8s %s\n", $row->ID, $row->post_type, $row->post_status, $row->post_title );
}1 post publish Hello world!
2 page publish Sample Page
3 page draft Privacy Policy
4 wp_navigation publish NavigationA post, a page, a draft privacy policy page, and a navigation menu (wp_navigation). Nobody created that menu by hand: the theme's header contains a Navigation block, and the first time the front end was displayed (the request earlier in this lesson), WordPress created a menu for it automatically. As you add content, images (attachment), templates and reusable patterns (wp_template, wp_block) will appear here too, each with its own post_type.
Settings live in wp_options
Site settings are rows in wp_options. WordPress reads them with get_option():
<?php
foreach ( [ 'blogname', 'blogdescription', 'siteurl', 'permalink_structure', 'template', 'posts_per_page' ] as $option ) {
echo str_pad( $option, 22 ), var_export( get_option( $option ), true ), "\n";
}blogname 'My WordPress Site'
blogdescription ''
siteurl 'http://localhost:8080'
permalink_structure '/%postname%/'
template 'twentytwentyfive'
posts_per_page '10'template holds the active theme's folder name. When you change a setting in the dashboard, you are changing one of these rows.
Common mistakes
- Editing core files instead of using a theme or plugin.
- Sharing or committing
wp-config.phpwith real passwords. - Assuming the
wp_prefix in code or SQL. - Changing the database by hand when the dashboard or WP-CLI would do it safely.
Exercise
Using the tables above, answer: where is the site title stored, where is a blog post's text stored, and where would an image's file name be recorded?
Show one possible answer
The site title is the blogname row in wp_options. A post's text is the post_content column of its row in wp_posts. An image is an attachment row in wp_posts, and its file path is stored in wp_postmeta under the key _wp_attached_file; the file itself is in wp-content/uploads.
Key points
- Every front-end request goes through index.php, which loads wp-config.php, the core, plugins and the theme.
- WordPress turns the URL into a database query, fetches the matching posts, and picks a theme template to show them.
- Your own work lives in wp-content (themes, plugins, uploads); never edit core files in wp-admin or wp-includes.
- Content is stored in about a dozen tables such as wp_posts, wp_postmeta, wp_users, wp_options and the taxonomy tables.