OOP · Encapsulation · The Protected Whale
Encapsulation in WordPress
Hide internal state — expose only what callers need through a controlled API.
WordPress plugins often mix admin UI, REST routes, and database logic in one file. Encapsulation keeps each class responsible for its own data: private properties, public getters, and sanitization at the boundary — the same idea behind WP_Query hiding SQL from theme templates.
Core concept
An object owns its data. External code should not read or mutate internal arrays directly — it calls methods that validate, sanitize, and persist. In WordPress, that boundary is how you avoid scattered update_option() calls and accidental exposure of raw user meta.
WordPress core examples
- WP_Query — themes pass query vars; SQL stays inside the class.
- WP_User — user fields are accessed via methods and caps, not direct DB rows.
- WP_REST_Request — parameters are read through getters with schema validation.
- Transients API — storage backend is hidden; you call
set_transient()/get_transient().
Plugin pattern: theme options
class Theme_Options {
private array $options = [];
public function get( string $key ): ?string {
return $this->options[ $key ] ?? null;
}
public function save( string $key, string $value ): void {
$this->options[ $key ] = sanitize_text_field( $value );
update_option( 'my_theme_options', $this->options );
}
}
User profile wrapper
class User_Profile {
private array $data;
public function __construct( array $data ) {
$this->data = $data;
}
public function get_display_name(): string {
return (string) ( $this->data['display_name'] ?? '' );
}
private function get_password_hash(): string {
return (string) ( $this->data['password'] ?? '' );
}
}
Password hash stays private; templates only receive the display name. Same pattern applies to wrapping WP_User or custom post meta in a small domain object inside your plugin.