PHPackages                             funkhaus/rest-easy - 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. [API Development](/categories/api)
4. /
5. funkhaus/rest-easy

ActiveWordpress-plugin[API Development](/categories/api)

funkhaus/rest-easy
==================

14181[12 issues](https://github.com/funkhaus/Rest-Easy/issues)PHP

Since Nov 15Pushed 7y ago5 watchersCompare

[ Source](https://github.com/funkhaus/Rest-Easy)[ Packagist](https://packagist.org/packages/funkhaus/rest-easy)[ RSS](/packages/funkhaus-rest-easy/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependenciesVersions (1)Used By (0)

Rest-Easy is a Wordpress plugin designed to Rest-ify your site with zero effort and powerful customization.

Table of Contents
-----------------

[](#table-of-contents)

1. [Installation](#installation)
2. [Tutorial](#tutorial)
    1. [Basics](#basics)
    2. [Custom Filters](#custom-filters)
3. [Core Concepts](#core-concepts)
4. [Reference](#reference)
    1. [Filters](#filters)
        1. [Builder Filters](#builder-filters)
            1. [Site Data](#site-data)
            2. [Meta Data](#meta-data)
            3. [Loop Data](#loop-data)
        2. [Serializer Filters](#serializer-filters)
            1. [Serialize Object](#serialize-object)
            2. [Serialize Attachment](#serialize-attachment)
            3. [Serialize Menu](#serialize-menu)
            4. [Serialize Nav Item](#serialize-nav-item)
            5. [Serialize Post](#serialize-post)
            6. [Gather Related](#gather-related)
    2. [Utility Functions](#utility-functions)
    3. [Integrations](#integrations)

Installation
------------

[](#installation)

Rest-Easy was built as a companion to [Vuepress](https://github.com/funkhaus/vuepress), so if you're using VP, Rest-Easy will be installed automatically.

If you're not using Vuepress, or would otherwise like to install the plugin manually, follow these steps:

1. Download the [latest version of the plugin](https://github.com/funkhaus/Rest-Easy/archive/master.zip).
2. Go to your site's plugin installation page (`[your-site.com]/wp-admin/plugin-install.php`).
3. Click "Upload Plugin," then upload the .zip file from step 1.
4. Go to your site's Plugins page (`[your-site.com]/wp-admin/plugins.php`) then click "Activate" on the Rest Easy plugin.

That's it!

Tutorial
--------

[](#tutorial)

Take a look at the [visual docs](https://codepen.io/SanderMoolin/full/JMLvBb) to see a step-by-step roadmap of a Rest-Easy response. If you're using Vuepress, the Basics section is handled automatically - you can continue reading for an idea of how Rest-Easy works, or head down to [Custom Filters](#custom-filters) for the next steps.

### Basics

[](#basics)

Once you've installed Rest-Easy, navigate to any page on your site with `?contentType=json` added at the end of the URL.

You'll see a serialized JSON object with the data of the page you requested - a lightweight and thorough summary of the current page, with zero setup on your end!

To fetch this JSON-serialized version of a page programmatically, you can do something like this in your site's JS:

```
fetch(myUrl + '?contentType=json')
    .then(res => {
        return res.json()
    })
    .then(json => console.log(json))
```

This example [fetches](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) the requested page of your site and returns the same JSON object that you got with the `?contentType=json` query parameter. Right away, you've got a working RESTful API with plenty of detailed information at your disposal.

[![Diagram showing flow of Rest-Easy data construction](https://camo.githubusercontent.com/a60d3653c4234cf1e443980b58a01c98b57ed752a6acfe91ff3320c664fc834f/68747470733a2f2f692e696d6775722e636f6d2f474b64574251752e706e67)](https://camo.githubusercontent.com/a60d3653c4234cf1e443980b58a01c98b57ed752a6acfe91ff3320c664fc834f/68747470733a2f2f692e696d6775722e636f6d2f474b64574251752e706e67)

### Custom Filters

[](#custom-filters)

Rest-Easy makes some assumptions about how you'd want a page to be serialized - but what if you want to change that serialization?

Let's say you want to have a custom field called `_my_custom_field` that you want to make available in the data. Add the following to your theme's `functions.php` file:

```
function add_custom_field($input) {
    global $post;
    $input['myCustomField'] = $post->_my_custom_field;

    return $input;
}
add_filter('rez_serialize_post', 'add_custom_field');
```

Let's go through that line-by-line.

- `function add_custom_field($input) {`

    Rest-Easy will run its default serialization on a post first, then pass the result to your custom filters as an associative array (`$input` in this example). Your filter will add, remove, or edit information, then pass the modified result to the next custom filter or, if there are none left, to the final JSON output.
- `global $post;`

    This is a reference to the WP object with which you're currently working.
- `$input['myCustomField'] = $post->_my_custom_field;`

    This line saves the value of `$post->_my_custom_field` to the `$input` array. You can give the data any name you want - here, it's camel-cased as `myCustomField`.
- `return $input;`

    This line passes the modified array along to the next custom filter or to the final JSON output.
- `add_filter('rez_serialize_post', 'add_custom_field');`

    Rest-Easy needs to know where your custom filters are defined, so we're using WordPress's `add_filter` function add the `add_custom_field` method (whose name was defined in the first line of this example) to Rest-Easy's `rez_serialize_post` filter.

Now, whenever you load a post with `_my_custom_field` defined, you'll see your custom field in `jsonData.loop[0]._my_custom_field`!

Core Concepts
-------------

[](#core-concepts)

(This is under-the-hood information - don't stress about this if you're not actually developing Rest-Easy!)

To avoid infinite loops in page serialization, Rest-Easy uses two main concepts: **builders** and **serializers**.

A **builder** will run once on a page. It combines the output of several serializers and returns that data as an associative array, which is then JSON-encoded to form `jsonData`.

(Note that builders are also the only functions that can gather related posts - if anything else could do so, related posts would keep building on top of themselves without staying one level deep like they do in the Loop builder.)

A **serializer** will take one piece of data from Wordpress and translate it into an associative array. For example, a serializer will take a post and turn it into an array with that post's title, content, permalink, and so on.

Rest-Easy's entry point is `rest-easy.php`, where it:

1. Runs the serializers in `builders.php`'s `rez_build_all_data` function
2. Determines how to send the requested output to the user by:
    - checking the request's `CONTENT_TYPE` and query strings for a JSON request, echoing the `jsonData` object if one was found
    - dumping the `jsonData` object onto the page with `wp_localize_script` otherwise

Reference
---------

[](#reference)

### Filters

[](#filters)

Add custom filters to build your own data:

```
function custom_function_name($input){
    // modify $input here...
    return $input;
}
add_filter('desired_rest_easy_filter', 'custom_function_name');
```

Default values are shown below.

#### Builder Filters

[](#builder-filters)

Builders run once per page. They're designed to collect serialized data, add some high-level site/meta information, and output the resulting JSON object. Most of the time, you'll only use builders when adding very general site information - region detecting, custom site-wide taglines, etc.

- `rez_build_all_data` - Highest level data builder - this is the top-level structure of the resulting JSON object. Returns: ```
    array(
        // key      => filter
        'site'      => rez_build_site_data,
        'meta'      => rez_build_meta_data,
        'loop'      => rez_build_loop_data
    )
    ```

##### Site Data

[](#site-data)

- `rez_build_site_data` - Builds general information about the site: ```
    array(
        'themeUrl'      => 'URL of current WordPress theme',
        'url'           => 'URL of site'
        'name'          => 'Site name',
        'description'   => 'Site description',
        'menus'         => array(
            // Array of all menus on the site
        ),
        'isMobile'      => 'Boolean - result of wp_is_mobile()'
    )
    ```

##### Meta Data

[](#meta-data)

- `rez_build_meta_data` - Builds meta information about the current page. ```
    array(
        'self'          => 'permalink to current page',
        'is404'         => /* bool - did this request return a 404 error? */,
        'nextPage'      => 'permalink to next page in pagination, if present',
        'previousPage'  => 'permalink to previous page in pagination, if present'
    )
    ```

##### Loop Data

[](#loop-data)

- `rez_build_loop_data` - Serializes all pages currently in [The Loop](https://codex.wordpress.org/The_Loop). ```
    array(
        // Array of serialized posts, pages, etc.
        // By default, each element in the array will be the result of
        // combining 'rez_serialize_object' and 'rez_gather_related'
    )
    ```

#### Serializer Filters

[](#serializer-filters)

Serializers are designed to take any WordPress object and translate it into JSON data. Serializers should be customized when you want to change the information that comes back from a single post, page, media item, etc. Post authors, media upload dates, and custom meta fields are great candidates for custom serializers.

##### Serialize Object

[](#serialize-object)

- `rez_serialize_object` - Generic serializer. Knows how to serialize any object. ```
    * Runs rez_serialize_attachment filter if a media attachment
    * Runs rez_serialize_menu filter if a menu
    * Runs rez_serialize_nav_item filter if a menu item
    * Runs rez_serialize_post filter, then adds `_wshop_product_id` as `productId`, if a `wps-product` (see https://github.com/funkhaus/wp-shopify)
    * Runs rez_serialize_post filter if any other object type
    ```

##### Serialize Attachment

[](#serialize-attachment)

- `rez_serialize_attachment` - Serializes a media attachment:

    ```
    array(
        'ID'                => /* int - attachment ID */,
        'title'             => 'title of attachment',
        'alt'               => 'alt text - looks for Alt Text, then Caption, then attachment title',
        'caption'           => 'caption from WordPress',
        'description'       => 'description from WordPress',

        // This section only runs if the Funky Colors plugin is installed
        'primaryColor'      => 'primary image color from Funky Colors',
        'secondaryColor'    => 'secondary image color from Funky Colors'
        // End Funky-Colors-only section

        'postType'          => 'post type',
        'sizes' => array(
            // Runs for each image size defined in WP (https://developer.wordpress.org/reference/functions/add_image_size/)
            'size-slug' => array(
                'url'       => 'url to image at given size',
                'width'     => /* int - width in px */,
                'height'    => /* int - height in px */
            )
        )
    )
    ```

##### Serialize Menu

[](#serialize-menu)

- `rez_serialize_menu` - Serializes a menu and its items: ```
    array(
        'name'      => 'menu name',
        'slug'      => 'menu slug',
        'postType'  => 'post type',
        'items'     => array(
            // Array of all items in this menu run through `rez_serialize_object` filter
        )
    )
    ```

##### Serialize Nav Item

[](#serialize-nav-item)

- `rez_serialize_nav_item` - Serializes a menu item: ```
    array(
        'title'         => 'menu item title',
        'classes'       => 'menu item classes',
        'permalink'     => 'permalink to target',
        'relativePath'  => 'relative path to target',
        'isExternal'    => /* bool - true if type label == 'Custom Link' */,
        'ID'            => 'int - menu item ID',
        'children'      => 'object - results of serialize_nav_menu on submenus',
        'postType'      => 'post type'
    )
    ```

##### Serialize Post

[](#serialize-post)

- `rez_serialize_post` - Generic serializer for any post type: ```
    array(
        'id'            => /* int - post ID */,
        'title'         => 'post title',
        'content'       => 'content with "the_content" filters applied',
        'excerpt'       => 'post excerpt',
        'rawExcerpt'    => 'post excerpt - only if set manually',
        'permalink'     => 'post permalink',
        'slug'          => 'post slug',
        'relativePath'  => 'relative path to post',
        'meta'          => array(
            // Contains all meta fields without leading underscore
            // $post->this_will_be_included_automatically
            // $post->_this_will_not
        ),
        'date'          => /* int - Unix timestamp of post date */,
        'attachedMedia' => 'serialized array of media uploaded to this page',
        'featuredAttachment'    => 'serialized featured image',
        'isFront'       => /* boolean - is this the front page? */,
        'isBlog'        => /* boolean - is this the page for posts? */,
        'isCategory'    => /* boolean - is this a category archive page? */,
        'terms'         => 'Array of all terms this post contains',
        'postType'      => 'post type'
    )
    ```

##### Gather Related

[](#gather-related)

- `rez_gather_related($related, $target_post)` - Gets related data for a given object:

    ```
    $related == array(
        'featuredAttachment'    => 'the serialized featured attachment, if this object has one',
        'ancestors' => array(
            // ancestors of this page, if applicable, serialized with rez_serialize_post and ordered from farthest -> nearest (ie [great-grandparent, grandparent, parent])
        ),
        'children'  => array(
            // children of this page, if applicable, serialized with rez_serialize_post
        ),
        'parent'    => /* object - the parent of this page, serialized with rez_serialize_post */,
        'next'      => /* object - the next page in menu order, if applicable, serialized with rez_serialize_post */,
        'prev'      => /* object - the previous page in menu order, if applicable, serialized with rez_serialize_post */
    );

    $target_post == /* The target $post object */
    ```

### Utility functions

[](#utility-functions)

- `rez_get_next_page_id($target_post)` - Get the ID of the page/post following the `$target_post`.
- `rez_get_previous_page_id($target_post)` - Get the ID of the page/post before the `$target_post`.
- `set_attachment_serialization($target_post, $value)` - Set whether or not a target post should automatically serialize its attached media. (Can save time when serializing pages with large amounts of attachments, for example.)

Integrations
------------

[](#integrations)

Rest-Easy is built to work well with other [Funkhaus](http://funkhaus.us) plugins:

- [Funky Colors](https://github.com/funkhaus/funky-colors), which determines an image's main colors
- [WP-Shopify](https://github.com/funkhaus/wp-shopify), which simplifies connecting Shopify to a Wordpress store

---

**Rest-Easy**

###  Health Score

19

—

LowBetter than 10% of packages

Maintenance3

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 96.2% 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.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5344587?v=4)[SaFrMo](/maintainers/safrmo)[@SaFrMo](https://github.com/SaFrMo)

---

Top Contributors

[![SaFrMo](https://avatars.githubusercontent.com/u/5344587?v=4)](https://github.com/SaFrMo "SaFrMo (50 commits)")[![cyrusdean](https://avatars.githubusercontent.com/u/31431358?v=4)](https://github.com/cyrusdean "cyrusdean (1 commits)")[![drewbaker](https://avatars.githubusercontent.com/u/475015?v=4)](https://github.com/drewbaker "drewbaker (1 commits)")

### Embed Badge

![Health badge](/badges/funkhaus-rest-easy/health.svg)

```
[![Health](https://phpackages.com/badges/funkhaus-rest-easy/health.svg)](https://phpackages.com/packages/funkhaus-rest-easy)
```

###  Alternatives

[stripe/stripe-php

Stripe PHP Library

4.0k143.3M480](/packages/stripe-stripe-php)[twilio/sdk

A PHP wrapper for Twilio's API

1.6k92.9M272](/packages/twilio-sdk)[knplabs/github-api

GitHub API v3 client

2.2k15.8M187](/packages/knplabs-github-api)[facebook/php-business-sdk

PHP SDK for Facebook Business

90121.9M34](/packages/facebook-php-business-sdk)[meilisearch/meilisearch-php

PHP wrapper for the Meilisearch API

73813.7M114](/packages/meilisearch-meilisearch-php)[google/gax

Google API Core for PHP

263103.1M454](/packages/google-gax)

PHPackages © 2026

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