kaiseki / wp-acf-dto
Easily create DTOs from ACF fields
Requires
- php: ^8.2
- ext-ctype: *
- illuminate/contracts: ^11.0 || ^12.0
- illuminate/support: ^11.0 || ^12.0
- jawira/case-converter: ^3.5
- kaiseki/config: ^2.0
- kaiseki/laravel-helper-mocks: ^1.0
- psr/container: ^1.1 || ^2.0
- respect/validation: ^2.2
- spatie/laravel-data: ^4.0
Requires (Dev)
- bnf/phpstan-psr-container: ^1.1
- kaiseki/php-coding-standard: ^1.0
- maglnet/composer-require-checker: ^4.0
- php-stubs/acf-pro-stubs: ^6.0
- php-stubs/wordpress-stubs: ^6.2
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^11.0
- roave/security-advisories: dev-latest
- szepeviktor/phpstan-wordpress: ^2.0
This package is auto-updated.
Last update: 2026-06-03 12:40:16 UTC
README
Easily create DTOs from ACF fields.
Maps Advanced Custom Fields (ACF) data onto typed, immutable
spatie/laravel-data objects. Define a DTO once, then hydrate
it from a post's ACF fields — with casts that turn raw field values into WP_Post/WP_Term/WP_User
objects, DateTimeImmutables, validated e-mails/URLs, and nested DTOs.
Installation
composer require kaiseki/wp-acf-dto
Requires PHP 8.2 or newer.
Usage
Define a DTO
Extend the package's Data base class (a spatie/laravel-data data object with a safe-construction
helper) and annotate properties with the bundled casts. Property names map to ACF field names via
spatie's name mappers.
use DateTimeImmutable; use Kaiseki\WordPress\ACF\Dto\Casts\DateTimeCast; use Kaiseki\WordPress\ACF\Dto\Casts\WpPostCast; use Kaiseki\WordPress\ACF\Dto\Castables\Link; use Kaiseki\WordPress\ACF\Dto\Data; use Spatie\LaravelData\Attributes\MapName; use Spatie\LaravelData\Attributes\WithCast; use Spatie\LaravelData\Mappers\SnakeCaseMapper; use WP_Post; #[MapName(SnakeCaseMapper::class)] class EventData extends Data { public function __construct( public readonly ?string $headline, #[WithCast(DateTimeCast::class)] public readonly ?DateTimeImmutable $startsAt, // Resolves an ACF post-object field to a lazy WP_Post wrapper. #[WithCast(WpPostCast::class, postType: 'page')] public readonly ?WP_Post $relatedPage, // Nested DTO: an ACF link field becomes a Link data object. public readonly ?Link $cta, ) { } }
Build a DTO from a post's ACF fields
AcfDataBuilder reads every field for a post (via ACF's get_fields()), merges in any defaults, and
constructs the DTO:
use Kaiseki\WordPress\ACF\Dto\AcfDataBuilder; use Kaiseki\WordPress\ACF\Dto\AcfGetFields; $builder = new AcfDataBuilder(new AcfGetFields()); $event = $builder->create( EventData::class, postId: get_the_ID(), defaults: ['headline' => 'Untitled'], );
To swallow construction errors (e.g. validation failures) and get null instead of an exception, use
the trait's safeFrom():
$event = EventData::safeFrom(get_fields());
Read single fields with type safety
AcfFieldValue wraps get_field() with a typed accessor per return type, narrowing ACF's loose return
values to the declared PHP type (or null):
use Kaiseki\WordPress\ACF\Dto\AcfFieldValue; $field = new AcfFieldValue(); $title = $field->string('headline'); // ?string $count = $field->int('seats'); // ?int $starts = $field->dateTime('starts_at'); // ?DateTimeImmutable $ids = $field->idList('related_posts'); // list<int> $author = $field->wpUser('author'); // ?WpUser $link = $field->link('cta'); // ?Link
Register the spatie/laravel-data config
ConfigProvider returns the package's spatie/laravel-data configuration (date format, casts,
transformers, normalizers) for laminas-style config aggregators:
use Kaiseki\WordPress\ACF\Dto\ConfigProvider; $config = (new ConfigProvider())();
Development
composer install
composer check # check-deps, cs-check, phpstan
License
MIT — see LICENSE.