PHPackages                             pinkcrab/wp-rest-schema - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. pinkcrab/wp-rest-schema

ActiveLibrary

pinkcrab/wp-rest-schema
=======================

Library for writing WP Json Rest Schema

1.0.0-RC1(2mo ago)18.3k↓15.5%[5 PRs](https://github.com/Pink-Crab/WP_Rest_Schema/pulls)2MITPHPPHP &gt;=8.0.0CI passing

Since Nov 3Pushed 2mo agoCompare

[ Source](https://github.com/Pink-Crab/WP_Rest_Schema)[ Packagist](https://packagist.org/packages/pinkcrab/wp-rest-schema)[ Docs](https://pinkcrab.co.uk)[ RSS](/packages/pinkcrab-wp-rest-schema/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (13)Versions (23)Used By (2)

WP Rest Schema Builder
======================

[](#wp-rest-schema-builder)

A fluent PHP builder for WordPress REST API JSON schemas. Converts verbose nested array definitions into clean, chainable method calls.

[![Latest Stable Version](https://camo.githubusercontent.com/8020d937e2cb498da49a7753627d0896f4715843cea62550f4b5820e267bcdd5/687474703a2f2f706f7365722e707567782e6f72672f70696e6b637261622f77702d726573742d736368656d612f76)](https://packagist.org/packages/pinkcrab/wp-rest-schema) [![Total Downloads](https://camo.githubusercontent.com/9b6c5035a5a25de2463195da4aeb400061c61f4659133a1d188bde1e3e2b542c/687474703a2f2f706f7365722e707567782e6f72672f70696e6b637261622f77702d726573742d736368656d612f646f776e6c6f616473)](https://packagist.org/packages/pinkcrab/wp-rest-schema) [![Latest Unstable Version](https://camo.githubusercontent.com/bc426fb507e97012c4876e0f2741349928b069aff717b92dbe5eefee592511b2/687474703a2f2f706f7365722e707567782e6f72672f70696e6b637261622f77702d726573742d736368656d612f762f756e737461626c65)](https://packagist.org/packages/pinkcrab/wp-rest-schema) [![License](https://camo.githubusercontent.com/518ce9045c9e3fff81af9729e22dec943035fc42f8dffc4025a745972d4be00e/687474703a2f2f706f7365722e707567782e6f72672f70696e6b637261622f77702d726573742d736368656d612f6c6963656e7365)](https://packagist.org/packages/pinkcrab/wp-rest-schema) [![PHP Version Require](https://camo.githubusercontent.com/11b13a6282d9d61a73f02c4431e166726eeb12f41f2fb1ca90dcccda8d498a12/687474703a2f2f706f7365722e707567782e6f72672f70696e6b637261622f77702d726573742d736368656d612f726571756972652f706870)](https://packagist.org/packages/pinkcrab/wp-rest-schema)[![GitHub contributors](https://camo.githubusercontent.com/d5ba0ee4e87a64e38e7a08641542a460f1071bf6884672e977fe9d6f868a9de9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732f50696e6b2d437261622f57505f526573745f536368656d613f6c6162656c3d436f6e7472696275746f7273)](https://camo.githubusercontent.com/d5ba0ee4e87a64e38e7a08641542a460f1071bf6884672e977fe9d6f868a9de9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6e7472696275746f72732f50696e6b2d437261622f57505f526573745f536368656d613f6c6162656c3d436f6e7472696275746f7273)[![GitHub issues](https://camo.githubusercontent.com/04f6b1cf35e41bd9c6fb41cdd8e48d2c159695ed06837120afa89fb3b0f7bc75/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d7261772f50696e6b2d437261622f57505f526573745f536368656d61)](https://camo.githubusercontent.com/04f6b1cf35e41bd9c6fb41cdd8e48d2c159695ed06837120afa89fb3b0f7bc75/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732d7261772f50696e6b2d437261622f57505f526573745f536368656d61)[![WordPress 6.6 Test Suite [PHP8.0-8.4]](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_6.yaml/badge.svg)](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_6.yaml)[![WordPress 6.7 Test Suite [PHP8.0-8.4]](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_7.yaml/badge.svg)](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_7.yaml)[![WordPress 6.8 Test Suite [PHP8.0-8.4]](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_8.yaml/badge.svg)](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_8.yaml)[![WordPress 6.9 Test Suite [PHP8.0-8.4]](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_9.yaml/badge.svg)](https://github.com/Pink-Crab/WP_Rest_Schema/actions/workflows/WP_6_9.yaml)

---

Why?
----

[](#why)

Defining valid JSON rest schema in WordPress means writing deeply nested associative arrays. It's easy to make mistakes, hard to read, and painful to maintain. This library provides a fully fluent, type-safe builder API that mirrors every keyword from WordPress's `rest_get_allowed_schema_keywords()`.

**Instead of this:**

```
register_post_meta( 'post', 'fixed_in', array(
    'type'         => 'string',
    'single'       => true,
    'show_in_rest' => array(
        'schema' => array(
            'type'        => 'string',
            'minLength'   => 10,
            'maxLength'   => 42,
            'required'    => true,
            'description' => 'Required string, 10-42 chars.',
        ),
    ),
) );
```

**Write this:**

```
register_post_meta( 'post', 'fixed_in', array(
    'type'         => 'string',
    'single'       => true,
    'show_in_rest' => array(
        'schema' => Argument_Parser::for_meta_data(
            String_Type::field( 'fixed_in' )
                ->min_length( 10 )
                ->max_length( 42 )
                ->required()
                ->description( 'Required string, 10-42 chars.' )
        ),
    ),
) );
```

---

Setup
-----

[](#setup)

```
$ composer require pinkcrab/wp-rest-schema
```

**Requirements:** PHP &gt;= 8.0 | WordPress &gt;= 6.6

---

Available Types
---------------

[](#available-types)

TypeClassType-Specific MethodsString`String_Type``min_length()`, `max_length()`, `pattern()`Integer`Integer_Type``minimum()`, `maximum()`, `exclusive_minimum()`, `exclusive_maximum()`, `multiple_of()`Number`Number_Type``minimum()`, `maximum()`, `exclusive_minimum()`, `exclusive_maximum()`, `multiple_of()`Boolean`Boolean_Type`*No type-specific methods*Null`Null_Type`*No type-specific methods*Array`Array_Type``string_item()`, `integer_item()`, `min_items()`, `max_items()`, `unique_items()`, `any_of()`, `one_of()`Object`Object_Type``string_property()`, `integer_property()`, `additional_properties()`, `pattern_properties()`, `min_properties()`, `max_properties()`> `Boolean_Type` and `Null_Type` inherit all shared methods from the base `Argument` class but have no additional type-specific methods. See [Argument](docs/Argument.md) for the full shared API.

All types share a common set of methods for `description`, `default`, `required`, `readonly`, `title`, `format`, `expected` (enum), `context`, `validation`, `sanitization`, and `union types`. See [Argument (Base Class)](docs/Argument.md) for details.

---

Quick Examples
--------------

[](#quick-examples)

### Post Meta Schema

[](#post-meta-schema)

```
use PinkCrab\WP_Rest_Schema\Argument\String_Type;
use PinkCrab\WP_Rest_Schema\Parser\Argument_Parser;

register_post_meta( 'post', 'color', array(
    'type'         => 'string',
    'single'       => true,
    'show_in_rest' => array(
        'schema' => Argument_Parser::for_meta_data(
            String_Type::field( 'color' )
                ->format( String_Type::FORMAT_HEX )
                ->required()
                ->description( 'A hex colour value.' )
        ),
    ),
) );
```

### REST Route Arguments

[](#rest-route-arguments)

```
use PinkCrab\WP_Rest_Schema\Argument\String_Type;
use PinkCrab\WP_Rest_Schema\Argument\Integer_Type;
use PinkCrab\WP_Rest_Schema\Parser\Argument_Parser;

register_rest_route( 'my/v1', '/search', array(
    'methods'  => 'GET',
    'callback' => 'handle_search',
    'args'     => Argument_Parser::for_route(
        String_Type::field( 'query' )->required()->min_length( 1 ),
        Integer_Type::field( 'page' )->minimum( 1 )->default( 1 ),
        String_Type::field( 'order' )->expected( 'asc', 'desc' )->default( 'desc' )
    ),
) );
```

### Full Item Schema (for `WP_REST_Controller::get_item_schema()`)

[](#full-item-schema-for-wp_rest_controllerget_item_schema)

```
use PinkCrab\WP_Rest_Schema\Schema;
use PinkCrab\WP_Rest_Schema\Argument\String_Type;
use PinkCrab\WP_Rest_Schema\Argument\Integer_Type;

public function get_item_schema() {
    return Schema::on( 'post' )
        ->description( 'A blog post object.' )
        ->integer_property( 'id', function( Integer_Type $id ) {
            return $id->readonly()
                ->description( 'Unique identifier.' )
                ->context( 'view', 'edit', 'embed' );
        } )
        ->string_property( 'title', function( String_Type $t ) {
            return $t->required()
                ->description( 'The post title.' )
                ->context( 'view', 'edit' );
        } )
        ->string_property( 'status', function( String_Type $s ) {
            return $s->expected( 'publish', 'draft', 'pending' )
                ->context( 'view', 'edit' );
        } )
        ->additional_properties( false )
        ->to_array();
}
```

### Nested Object with Array

[](#nested-object-with-array)

```
use PinkCrab\WP_Rest_Schema\Argument\Object_Type;
use PinkCrab\WP_Rest_Schema\Argument\String_Type;
use PinkCrab\WP_Rest_Schema\Argument\Integer_Type;
use PinkCrab\WP_Rest_Schema\Argument\Array_Type;

Object_Type::field( 'metadata' )
    ->string_property( 'title', fn( String_Type $t ) => $t->required() )
    ->integer_property( 'score', fn( Integer_Type $i ) => $i->minimum( 0 )->maximum( 100 ) )
    ->array_property( 'tags', fn( Array_Type $a ) => $a->string_item()->unique_items() )
    ->additional_properties( false )
```

---

Documentation
-------------

[](#documentation)

PageDescription[Argument (Base Class)](docs/Argument.md)Shared methods available on all types: description, default, required, readonly, title, format, expected, context, validation, sanitization, union types, and all constants[String Type](docs/String-Type.md)`String_Type` — minLength, maxLength, pattern[Number Types](docs/Number-Type.md)`Number_Type` and `Integer_Type` — minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf[Array Type](docs/Array-Type.md)`Array_Type` — typed items, minItems, maxItems, uniqueItems, element relationships[Object Type](docs/Object-Type.md)`Object_Type` — properties, additionalProperties, patternProperties, minProperties, maxProperties, element relationships[Schema Builder](docs/Schema.md)Top-level `Schema` class for building `get_item_schema()` output[Parser](docs/Parser.md)`Argument_Parser` — converting builders to arrays for WordPress---

Perique Integration
-------------------

[](#perique-integration)

This library can be used with the [Perique Registerable](https://github.com/Pink-Crab/Perique-Registerables) library:

```
$meta_data = ( new Meta_Data( 'fixed_in' ) )
    ->post_type( 'post' )
    ->type( 'string' )
    ->rest_schema(
        Argument_Parser::for_meta_data(
            String_Type::field( 'fixed_in' )
                ->min_length( 10 )
                ->max_length( 42 )
                ->required()
                ->description( 'Required string, 10-42 chars.' )
        )
    );
```

---

License
-------

[](#license)

### MIT License

[](#mit-license)

Change Log
----------

[](#change-log)

- 1.0.0-RC1 - Added Schema builder, readonly/title support, field() alias, for\_route() helper, additionalProperties redesign, FORMAT\_URI fix, PHPStan level 9, WPCS 3, PHP 8.0+/WP 6.6+
- 0.1.0 - Initial version

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance94

Actively maintained with recent releases

Popularity25

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~520 days

Total

4

Last Release

64d ago

Major Versions

0.0.1-beta3 → 1.0.0-RC12026-03-05

PHP version history (2 changes)0.0.1-betaPHP &gt;=7.1.0

1.0.0-RC1PHP &gt;=8.0.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/d82b9e8ef7816d3d0b9812ad233f61f6a313f529e0ac85721781b46ad292e1ea?d=identicon)[glynnquelch](/maintainers/glynnquelch)

---

Top Contributors

[![gin0115](https://avatars.githubusercontent.com/u/28779094?v=4)](https://github.com/gin0115 "gin0115 (46 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/pinkcrab-wp-rest-schema/health.svg)

```
[![Health](https://phpackages.com/badges/pinkcrab-wp-rest-schema/health.svg)](https://phpackages.com/packages/pinkcrab-wp-rest-schema)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
