better-data Documentation
better-data is a PHP 8.3+ DTO and Presenter library for WordPress. Typed, immutable DTOs hydrated from any WordPress shape; symmetric write sinks; contextual output rendering; attribute-driven validation; and explicit security primitives.
Status
- Baseline documentation target:
v1.0.0 - Latest release:
v1.0.0 - Packagist/package index release: not published yet — install via VCS repository
What you get
- DataObject —
final readonly classDTOs declared via constructor promotion; hydrate from arrays, posts, users, terms, options,$wpdbrows, or REST requests - Sources —
PostSource,UserSource,TermSource,OptionSource,RowSource,RequestSource; bulk hydration with cache prewarming; request guards (nonce, capability, body/query/URL routing, no-collision) - Sinks —
PostSink,UserSink,TermSink,OptionSink,RowSink; projection-first API (toArgs/toMeta/toArray) for unit tests + convenience methods (save,insert,update) withwp_slash()baked in - Presenter — context-aware output shaping for REST / admin / email / CSV; field whitelist, computed fields, locale-aware
formatDate/formatCurrency,Secretand#[Sensitive]redaction - Validation — attribute-driven rules (
Required,Email,Url,Uuid,Regex,Min/Max,MinLength/MaxLength,OneOf); pluggableValidationEngineInterface - Security primitives —
Secretleak-proof container;#[Sensitive]for PII redaction;#[Encrypted]AES-256-GCM at-rest with rotation - Registration —
MetaKeyRegistry::register()drivesregister_meta()from DTO shape;toJsonSchema()/toRestArgs()for REST endpoints - better-route bridge —
BetterData\Route\BetterRouteBridgewires DTOs into abetter-routeRouterfor hydration, validation, OpenAPI metadata, and Presenter response shaping
Who this is for
- WordPress plugin and theme teams that want typed, contract-first data instead of hand-rolled
$_POSTparsing - Teams already standing up REST APIs that want to drop their fragile array conversions
- Codebases with sensitive data (API keys, tokens, PII) that need explicit handling rather than
wp_optionsplaintext
What this is NOT
- Not an ORM. No relationships, no query builder, no migrations. Use
WP_Query/get_users/$wpdband hand the results to a source. - Not a form renderer. Data shaping only — HTML is the consumer's problem.
- Not a DI container or service bus. Sibling library
better-routehandles routing. - Not a secrets manager.
#[Encrypted]provides at-rest AES-256-GCM; key distribution and rotation policy are the consumer's responsibility.
Documentation map
Getting Startedfor install and a working DTO in five minutesCoreforDataObject, attributes, validation, type coercionSourcesfor read paths (posts / users / terms / options / rows / REST requests)Sinksfor write pathsPresenterfor context-aware output renderingSecurityforSecret,#[Sensitive],#[Encrypted]Registrationfor WordPress meta key registration and JSON Schema exportReferencefor API tables and FAQAI Agent Skillsfor structured skills an AI agent can useRelease Notesfor what changed in each version
Composition with better-route
BetterRouteBridge is the optional adapter:
use BetterData\Route\BetterRouteBridge;
BetterRouteBridge::post(
$router,
'/products',
ProductDto::class,
fn (ProductDto $dto) => $dto->saveAsPost(),
['tags' => ['Products']],
);
See Composition for the full pattern.