跳到正文
cccskills
免费在 GitHub 公开

wp-plugin-dto

Design and review native DTOs in WordPress plugins without requiring better-data - immutable data carriers, explicit from_array hydration, strict coercion instead of unchecked casts, WP_Error validation failures, sensitive-field discipline, nested DTO arrays, and clear separation from repositories, WP models, presenters, REST controllers, and HTML views. Use when a plugin introduces FooDto, request DTOs, settings DTOs, value objects, admin-row data shapes, REST response source objects, or when reviewing code that passes raw arrays, stdClass, WP_Post, WC_Order, $_POST, post meta, or option arrays through multiple layers. Mentions better-data only as an optional higher-level library; this skill is for native implementations.

中文简介正在准备中。当前显示原文说明。

集成工具WordPress
查看安装方法

包含的文件(3)

  • SKILL.md10.0 KB
  • references/before-after-raw-array.md3.7 KB
  • references/native-dto-patterns.md8.0 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

WordPress plugin: native DTOs

For plugin code that moves structured data between request input, options, meta, custom tables, external APIs, REST controllers, admin screens, cron jobs, and presenters. A DTO gives that data one named shape instead of leaking raw arrays across the plugin.

This skill is intentionally better-data-free. If the project already uses better-data, run bd-data-object; otherwise use this native pattern.

When to load references

Misconception this skill corrects

"A DTO is just an array with nicer comments."

Wrong direction. A DTO is a small immutable boundary object with a named schema, explicit defaults, and one hydration path. It prevents common AI mistakes: unchecked (int) casts, empty() swallowing 0, isset() hiding intentional null, dynamic properties, leaking secrets through to_array(), and passing $_POST or raw post meta directly to business logic.

When to use this skill

Trigger when ANY of the following is true:

  • Introducing FooDto, FooData, SettingsData, RequestData, Payload, or a value object.
  • A repository, REST controller, admin page, cron job, or WooCommerce hook currently passes large associative arrays around.
  • Data comes from $_GET, $_POST, REST params, options, post meta, user meta, term meta, custom tables, WP_Post, WP_User, or WooCommerce objects.
  • Reviewing hydration / normalization code with casts like (int), (bool), intval, settype, empty, isset, get_object_vars, or dynamic property assignment.
  • Presenter or REST response code needs a stable input object.

Layer boundaries

LayerResponsibility
Source / repositoryRead WP objects, options, meta, request params, API responses. Knows WordPress.
DTOHold normalized values. No DB writes, no HTML, no hooks, no global reads.
ValidatorDecide whether the DTO is acceptable. Returns true or WP_Error.
PresenterConvert DTO to arrays / JSON-ready values for REST, admin, JS config, email.
View / templateEscape and echo HTML.

The DTO may contain small normalization helpers, but it should not call get_post_meta(), update_option(), wp_remote_get(), add_action(), or echo anything.

Minimal class shape

Prefer PHP 7.4-compatible immutable objects unless the plugin has a higher minimum PHP version. Use PHP 8.1 readonly only when the plugin declares PHP 8.1+.

namespace MyPlugin\Dto;

use WP_Error;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

final class ProductDto {
    private int $id;
    private string $title;

    public function __construct( int $id = 0, string $title = '' ) {
        $this->id    = $id;
        $this->title = $title;
    }

    /** @param array<string,mixed> $data @return self|WP_Error */
    public static function from_array( array $data ) {
        $errors = new WP_Error();
        $id     = self::to_int( $data['id'] ?? 0, 'id', $errors );
        $title  = self::to_string( $data['title'] ?? '', 'title', $errors );

        if ( '' === $title ) {
            $errors->add( 'missing_title', 'Product title is required.' );
        }
        if ( $errors->has_errors() ) {
            return $errors;
        }

        return new self( $id, $title );
    }

    /** @return array<string,mixed> */
    public function to_array(): array {
        return array(
            'id'    => $this->id,
            'title' => $this->title,
        );
    }

    public function id(): int { return $this->id; }
    public function title(): string { return $this->title; }

    private static function to_int( $value, string $field, WP_Error $errors ): int {
        if ( is_int( $value ) ) {
            return $value;
        }
        if ( is_string( $value ) && preg_match( '/^-?\d+$/', $value ) ) {
            return (int) $value;
        }
        $errors->add( 'invalid_' . $field, sprintf( '%s must be an integer.', $field ) );
        return 0;
    }

    private static function to_string( $value, string $field, WP_Error $errors ): string {
        if ( is_string( $value ) ) {
            return $value;
        }
        if ( is_scalar( $value ) ) {
            return (string) $value;
        }
        $errors->add( 'invalid_' . $field, sprintf( '%s must be a string.', $field ) );
        return '';
    }
}

Use references/native-dto-patterns.md for the full pattern: floats, booleans, DateTime, nested DTO collections, secrets, with(), and PHP 8.1 variants.

Hydration rules

  • One entry point. Use from_array() or named factories like from_post( WP_Post $post ), from_option( array $option ), from_request( WP_REST_Request $request ).
  • Sanitize at the input boundary, validate in/near the DTO. For $_POST, use wp_unslash() first, then a field-specific sanitizer.
  • Use allowlists. Read only known keys. Do not keep unknown keys unless the DTO has a deliberate extra property.
  • Use array_key_exists() when null is meaningful. isset( $data['expires_at'] ) treats explicit null as absent.
  • Avoid empty() for typed fields. empty( '0' ) and empty( 0 ) are true.
  • Coerce deliberately. (int) 'abc' becomes 0; (bool) 'false' becomes true. Reject surprising input with WP_Error.
  • Nested arrays become nested DTOs. Do not leave items as random arrays when the plugin expects item shape.
  • No dynamic properties. PHP 8.2 deprecates them. Declare every property.
  • Defaults are explicit. Every constructor argument has a sensible default or is nullable.

Sensitive fields

DTOs often carry API keys, tokens, customer emails, or internal notes.

  • Keep secrets nullable: absence is null, not an empty secret string.
  • Do not include secrets in to_array() unless the method name says so, e.g. to_private_array().
  • Prefer a tiny value object for credentials; see references/native-dto-patterns.md.
  • Let the presenter decide whether a field is redacted for REST/admin/export.

Critical rules

  • DTO is immutable. No setters. Use with() to produce a changed copy.
  • DTO is not a repository. No get_post_meta(), no update_option(), no $wpdb, no HTTP calls.
  • DTO is not a presenter. No HTML, no escaping, no wp_send_json(), no rest_ensure_response().
  • Hydration is explicit and allowlisted. Never foreach ( $data as $key => $value ) { $dto->$key = $value; }.
  • Validation returns WP_Error or throws only for programmer errors. User input failures are normal and reportable.
  • Use field-specific coercion. Do not use unchecked (int), (bool), intval, settype, or empty()-driven normalization.
  • Keep parameter/property names stable. Renaming created_at to createdAt is a breaking change unless every caller and presenter is updated.
  • For PHP 8.1 enums, use tryFrom() and handle null. For PHP 7.4-compatible plugins, use constants plus explicit in_array( ..., true ).

Common mistakes

// WRONG - unchecked casts hide bad input.
$dto = new ProductDto( (int) $_POST['id'], (float) $_POST['price'] );

// WRONG - dynamic property hydration.
foreach ( $row as $key => $value ) {
    $dto->{$key} = $value;
}

// WRONG - empty() rejects valid values.
if ( empty( $data['quantity'] ) ) {
    return new WP_Error( 'missing_quantity', 'Quantity is required.' );
}

// WRONG - leaking secrets by dumping all object properties.
return get_object_vars( $dto );

Cross-references

  • Run wp-plugin-presenter when converting this DTO into REST/admin/JS/email output.
  • Run wp-plugin-architecture when deciding folder placement, namespaces, or by-feature vs by-type organization.
  • Run wp-plugin-options-storage when the DTO represents an option payload.
  • Run bd-data-object only if the project intentionally uses the better-data library. better-data automates many of these rules; this skill is the native no-library version.

What this skill does NOT cover

  • HTML templates and escaping strategy after presentation.
  • Database schema migrations or custom table repositories.
  • better-data attributes, sources, sinks, or presenter builder APIs.
  • REST route registration; use the REST-specific plugin skill if present.

References

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.

中文简介正在准备中。当前显示原文说明。

nvdigitalsolutions/mcp-ai-wpoos72026年10月22日 更新

Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.

中文简介正在准备中。当前显示原文说明。

nvdigitalsolutions/mcp-ai-wpoos72026年10月22日 更新

Control a headless browser to navigate URLs, click elements, fill forms, extract content from JavaScript-rendered pages, take screenshots, and automate end-to-end web workflows.

中文简介正在准备中。当前显示原文说明。

nvdigitalsolutions/mcp-ai-wpoos72026年10月22日 更新

Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.

中文简介正在准备中。当前显示原文说明。

nvdigitalsolutions/mcp-ai-wpoos72026年10月22日 更新

Review code for quality, simplicity, and maintainability. Identifies unnecessary abstractions, duplicated logic, oversized functions, missing error handling, and naming issues — then fixes them automatically before presenting the result.

中文简介正在准备中。当前显示原文说明。

nvdigitalsolutions/mcp-ai-wpoos72026年10月22日 更新

WooCommerce store operations through NV oOS Pro — product research, catalog cross-referencing, inventory lookups, and Shopify or Flowhub comparisons where integrations are configured.

中文简介正在准备中。当前显示原文说明。

nvdigitalsolutions/mcp-ai-wpoos72026年10月22日 更新

查看 nvdigitalsolutions 的全部技能

报告此技能的问题