All Projects → craftcms → Element Api

craftcms / Element Api

Licence: mit
Create a JSON API/Feed for your elements in Craft.

Projects that are alternatives of or similar to Element Api

craft-plugin-patrol
Patrol for Craft 3
Stars: ✭ 28 (-94.32%)
Mutual labels:  craftcms, craft-plugin, craft3
Polr
🚡 A modern, powerful, and robust URL shortener
Stars: ✭ 4,147 (+741.18%)
Mutual labels:  api, json-api, json
craft-guide
A CMS Guide for Craft CMS.
Stars: ✭ 62 (-87.42%)
Mutual labels:  craftcms, craft-plugin, craft3
Imager Craft
This plugin has been DEPRECATED. Check out Imager X instead.
Stars: ✭ 351 (-28.8%)
Mutual labels:  craftcms, craft-plugin, craft3
craft-recipe
A comprehensive recipe FieldType for Craft CMS that includes metric/imperial conversion, portion calculation, and JSON-LD microdata support
Stars: ✭ 23 (-95.33%)
Mutual labels:  craftcms, craft-plugin, craft3
craft-connect
Allows you to connect to external databases and perform db queries
Stars: ✭ 16 (-96.75%)
Mutual labels:  craftcms, craft-plugin, craft3
Pyjfuzz
PyJFuzz - Python JSON Fuzzer
Stars: ✭ 342 (-30.63%)
Mutual labels:  json-api, json, json-serialization
craft-entry-instructions
A simple fieldtype to add instructions.
Stars: ✭ 16 (-96.75%)
Mutual labels:  craftcms, craft-plugin, craft3
Json Api Php
JSON-API (http://jsonapi.org) responses in PHP.
Stars: ✭ 426 (-13.59%)
Mutual labels:  api, json-api, json
dospaces
DigitalOcean Spaces integration for Craft CMS
Stars: ✭ 31 (-93.71%)
Mutual labels:  craftcms, craft-plugin, craft3
snipcart-craft-plugin
Craft e-commerce in a day.
Stars: ✭ 20 (-95.94%)
Mutual labels:  craftcms, craft-plugin, craft3
Fractalistic
A framework agnostic, developer friendly wrapper around Fractal
Stars: ✭ 309 (-37.32%)
Mutual labels:  api, json, fractal
seomate
SEO, mate! It's important. That's why SEOMate provides the tools you need to craft all the meta tags, sitemaps and JSON-LD microdata you need - in one highly configurable, open and friendly package - with a super-light footprint.
Stars: ✭ 31 (-93.71%)
Mutual labels:  craftcms, craft-plugin, craft3
query
Run SQL queries as an admin from the Craft CMS control panel.
Stars: ✭ 14 (-97.16%)
Mutual labels:  craftcms, craft-plugin, craft3
contact-form-honeypot
Add a honeypot captcha to your Craft CMS contact form.
Stars: ✭ 24 (-95.13%)
Mutual labels:  craftcms, craft-plugin, craft3
mailgun
Mailgun mailer adapter for Craft CMS.
Stars: ✭ 27 (-94.52%)
Mutual labels:  craftcms, craft-plugin, craft3
craft-grid
A field that lets you content manage CSS Grid in Craft CMS.
Stars: ✭ 18 (-96.35%)
Mutual labels:  craftcms, craft-plugin, craft3
anchors
Add anchor links to headings in your Craft CMS website content.
Stars: ✭ 47 (-90.47%)
Mutual labels:  craftcms, craft-plugin, craft3
craft-plugin-mix
Helper plugin for Laravel Mix in Craft CMS templates
Stars: ✭ 50 (-89.86%)
Mutual labels:  craftcms, craft-plugin, craft3
Contact Form
Add a simple contact form to your Craft CMS site.
Stars: ✭ 294 (-40.37%)
Mutual labels:  craftcms, craft-plugin, craft3

Element API for Craft CMS

This plugin makes it easy to create a JSON API for your entries (and other element types) in Craft CMS.

It’s powered by Phil Sturgeon’s excellent Fractal package.

Requirements

This plugin requires Craft CMS 3.0.0-RC16 or later.

Installation

You can install this plugin from the Plugin Store or with Composer.

From the Plugin Store

Go to the Plugin Store in your project’s Control Panel and search for “Element API”. Then click on the “Install” button in its modal window.

With Composer

Open your terminal and run the following commands:

# go to the project directory
cd /path/to/my-project.test

# tell Composer to load the plugin
composer require craftcms/element-api

# tell Craft to install the plugin
./craft install/plugin element-api

Upgrading from Craft 2

If you’re in the process of upgrading a Craft 2 project to Craft 3, follow these instructions to get Element API back up and running:

  1. Install Element API 2.x.

  2. Move your old craft/config/elementapi.php file to config/, and rename it to element-api.php.

  3. Update your elementType endpoint settings to the new element type class names:

    Old New
    ElementType::Asset or 'Asset' 'craft\elements\Asset'
    ElementType::Category or 'Category' 'craft\elements\Category'
    ElementType::Entry or 'Entry' 'craft\elements\Entry'
    ElementType::GlobalSet or 'GlobalSet' 'craft\elements\GlobalSet'
    ElementType::MatrixBlock or 'MatrixBlock' 'craft\elements\MatrixBlock'
    ElementType::Tag or 'Tag' 'craft\elements\Tag'
    ElementType::User or 'User' 'craft\elements\User'
  4. Replace any 'first' => true endpoint settings to 'one' => true.

Setup

To define your API endpoints, create a new element-api.php file within your config/ folder. This file should return an array with an endpoints key, which defines your site’s API endpoints.

Within the endpoints array, keys are URL patterns, and values are functions that define the endpoint configurations.

<?php

use craft\elements\Entry;
use craft\helpers\UrlHelper;

return [
    'endpoints' => [
        'news.json' => function() {
            return [
                'elementType' => Entry::class,
                'criteria' => ['section' => 'news'],
                'transformer' => function(Entry $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'jsonUrl' => UrlHelper::url("news/{$entry->id}.json"),
                        'summary' => $entry->summary,
                    ];
                },
            ];
        },
        'news/<entryId:\d+>.json' => function($entryId) {
            return [
                'elementType' => Entry::class,
                'criteria' => ['id' => $entryId],
                'one' => true,
                'transformer' => function(Entry $entry) {
                    return [
                        'title' => $entry->title,
                        'url' => $entry->url,
                        'summary' => $entry->summary,
                        'body' => $entry->body,
                    ];
                },
            ];
        },
    ]
];

Endpoint Configuration Settings

Endpoint configuration arrays can contain the following settings:

class

The class name of the Fractal resource that should be used to serve the request. If this isn’t set, it will default to craft\elementapi\resources\ElementResource. (All of the following configuration settings are specific to that default class.)

elementType (Required)

The class name of the element type that the API should be associated with. Craft’s built-in element type classes are:

  • craft\elements\Asset
  • craft\elements\Category
  • craft\elements\Entry
  • craft\elements\GlobalSet
  • craft\elements\MatrixBlock
  • craft\elements\Tag
  • craft\elements\User
'elementType' => craft\elements\Entry::class,

criteria

An array of parameters that should be set on the Element Query that will be fetching the elements.

'criteria' => [
    'section' => 'news',
    'type' => 'article',
],

transformer

The transformer that should be used to define the data that should be returned for each element. If you don’t set this, the default transformer will be used, which includes all of the element’s direct attribute values, but no custom field values.

// Can be set to a function
'transformer' => function(craft\elements\Entry $entry) {
    return [
        'title' => $entry->title,
        'id' => $entry->id,
        'url' => $entry->url,
    ];
},

// Or a string/array that defines a Transformer class configuration
'transformer' => 'MyTransformerClassName',

// Or a Transformer class instance
'transformer' => new MyTransformerClassName(),

Your custom transformer class would look something like this:

<?php

use craft\elements\Entry;
use League\Fractal\TransformerAbstract;

class MyTransformerClassName extends TransformerAbstract
{
    public function transform(Entry $entry)
    {
        return [
            // ...
        ];
    }
}

one

Whether only the first matching element should be returned. This is set to false by default, meaning that all matching elements will be returned.

'one' => true,

paginate

Whether the results should be paginated. This is set to true by default, meaning that only a subset of the matched elements will be included in each response, accompanied by additional metadata that describes pagination information.

'paginate' => false,

elementsPerPage

The max number of elements that should be included in each page, if pagination is enabled. By default this is set to 100.

'elementsPerPage' => 10,

pageParam

The query string param name that should be used to identify which page is being requested. By default this is set to 'page'.

'pageParam' => 'pg',

Note that it cannot be set to 'p' because that’s the parameter Craft uses to check the requested path.

resourceKey

The key that the elements should be nested under in the response data. By default this will be 'data'.

'resourceKey' => 'entries',

meta

Any custom meta values that should be included in the response data.

'meta' => [
    'description' => 'Recent news from Happy Lager',
],

serializer

The serializer that should be used to format the returned data.

Possible values are:

includes

The include names that should be included for the current request, if any.

'includes' => (array)Craft::$app->request->getQueryParam('include'),

Note that this setting requires a custom transformer class that’s prepped to handle includes:

class MyTransformerClassName extends TransformerAbstract
{
    protected $availableIncludes = ['author'];

    public function includeAuthor(Entry $entry)
    {
        return $this->item($entry->author, function(User $author) {
            return [
                'id' => $author->id,
                'name' => $author->name,
            ];
        });
    }

    // ...
}

excludes

The include names that should be excluded for the current request, which would otherwise have been included (e.g. if they were listed as a default include), if any.

'excludes' => 'author',

Like includes, this setting requires a custom transformer class.

callback

If this is set, a JSONP response will be returned with an application/javascript content type, using this setting value as the callback function.

For example, if you set this to:

'callback' => 'foo',

Then the response will look like:

foo({ /* ... */ });

Note that if you set this, the jsonOptions and pretty settings will be ignored.

jsonOptions

The value of the $options argument that will be passed to json_encode() when preparing the response. By default JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE will be passed.

'jsonOptions' => JSON_UNESCAPED_UNICODE,

pretty

Shortcut for adding JSON_PRETTY_PRINT to jsonOptions.

'pretty' => true,

cache

Whether the output should be cached, and for how long.

Possible values are:

  • false (default) – results are never cached
  • true – results are cached for the duration specified by the cacheDuration Craft config setting
  • an integer – results are cached for the given number of seconds
  • a interval spec string – results are cached for the duration specified

Note that the onBeforeSendData event does not get triggered when the cache is warm.

'cache' => 'PT1M', // one minute

Dynamic URL Patterns

URL patterns can contain dynamic subpatterns in the format of <subpatternName:regex>, where subpatternName is the name of the subpattern, and regex is a valid regular expression. For example, the URL pattern “news/<entryId:\d+>.json” will match URLs like news/100.json. You can also use the tokens {handle} and {slug} within your regular expression, which will be replaced with the appropriate regex patterns for matching handles and element slugs.

Any subpattern matches in the URL pattern will be mapped to the endpoint config function’s arguments. For example, if a URL pattern contains an entryId subpattern, then you can add an $entryId argument to your endpoint config function, and whatever matches the URL subpattern will be passed to $entryId.

'news/<entryId:\d+>.json' => function($entryId) {
    return [
        'elementType' => craft\elements\Entry::class,
        'criteria' => ['id' => $entryId],
        'one' => true,
    ];
},

Setting Default Configuration Settings

You can specify default values for your endpoint configuration settings by adding a defaults key alongside your endpoints key (not within it).

use craft\elements\Entry;

return [
    'defaults' => [
        'elementType' => Entry::class,
        'elementsPerPage' => 10,
        'pageParam' => 'pg',
        'transformer' => function(Entry $entry) {
            return [
                'title' => $entry->title,
                'id' => $entry->id,
                'url' => $entry->url,
            ];
        },
    ],

    'endpoints' => [
        'news.json' => function() {
            return [
                'criteria' => ['section' => 'news'],
            ]
        },
        'news/<entryId:\d+>.json' => function($entryId) {
            return [
                'criteria' => ['id' => $entryId],
                'one' => true,
            ];
        },
    ]
];

Examples

Here are a few endpoint examples, and what their response would look like.

Paginated Entry Index Endpoint

'ingredients.json' => function() {
    return [
        'criteria' => ['section' => 'ingredients'],
        'elementsPerPage' => 10,
        'transformer' => function(craft\elements\Entry $entry) {
            return [
                'title' => $entry->title,
                'url' => $entry->url,
                'jsonUrl' => UrlHelper::url("ingredients/{$entry->slug}.json"),
            ];
        },
        'pretty' => true,
    ];
},
{
    "data": [
        {
            "title": "Gin",
            "url": "/ingredients/gin",
            "jsonUrl": "/ingredients/gin.json"
        },
        {
            "title": "Tonic Water",
            "url": "/ingredients/tonic-water",
            "jsonUrl": "/ingredients/tonic-water.json"
        },
        // ...
    ],
    "meta": {
        "pagination": {
            "total": 66,
            "count": 10,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 7,
            "links": {
                "next": "/ingredients.json?p=2"
            }
        }
    }
}

Single Entry Endpoint

'ingredients/<slug:{slug}>.json' => function($slug) {
    return [
        'criteria' => [
            'section' => 'ingredients',
            'slug' => $slug
        ],
        'one' => true,
        'transformer' => function(craft\elements\Entry $entry) {
            // Create an array of all the photo URLs
            $photos = [];
            foreach ($entry->photos->all() as $photo) {
                $photos[] = $photo->url;
            }

            return [
                'title' => $entry->title,
                'url' => $entry->url,
                'description' => (string)$entry->description,
                'photos' => $photos
            ];
        },
        'pretty' => true,
    ];
},
{
    "title": "Gin",
    "url": "/ingredients/gin",
    "description": "<p>Gin is a spirit which derives its predominant flavour from juniper berries.</p>",
    "photos": [
        "/images/drinks/GinAndTonic1.jpg"
    ]
}

JSON Feed

Here’s how to set up a JSON Feed (Version 1) for your site with Element API.

Note that photos, body, summary, and tags are imaginary custom fields.

'feed.json' => function() {
    return [
        'serializer' => 'jsonFeed',
        'elementType' => craft\elements\Entry::class,
        'criteria' => ['section' => 'news'],
        'transformer' => function(craft\elements\Entry $entry) {
            $image = $entry->photos->one();
    
            return [
                'id' => (string)$entry->id,
                'url' => $entry->url,
                'title' => $entry->title,
                'content_html' => (string)$entry->body,
                'summary' => $entry->summary,
                'image' => $image ? $image->url : null,
                'date_published' => $entry->postDate->format(\DateTime::ATOM),
                'date_modified' => $entry->dateUpdated->format(\DateTime::ATOM),
                'author' => ['name' => $entry->author->name],
                'tags' => array_map('strval', $entry->tags->all()),
            ];
        },
        'meta' => [
            'description' => 'Recent news from Happy Lager',
        ],
        'pretty' => true,
    ];
},
{
    "version": "https://jsonfeed.org/version/1",
    "title": "Happy Lager",
    "home_page_url": "http://domain.com/",
    "feed_url": "http://domain.com/feed.json",
    "description": "Craft demo site",
    "items": [
        {
            "id": "24",
            "url": "http://domain.com/news/the-future-of-augmented-reality",
            "title": "The Future of Augmented Reality",
            "content_html": "<p>Nam libero tempore, cum soluta nobis est eligendi ...</p>",
            "date_published": "2016-05-07T00:00:00+00:00",
            "date_modified": "2016-06-03T17:43:36+00:00",
            "author": {
                "name": "Liz Murphy"
            },
            "tags": [
                "augmented reality",
                "futurism"
            ]
        },
        {
            "id": "4",
            "url": "http://domain.com/news/barrel-aged-digital-natives",
            "title": "Barrel Aged Digital Natives",
            "content_html": "<p>Nam libero tempore, cum soluta nobis est eligendi ...</p>",,
            "date_published": "2016-05-06T00:00:00+00:00",
            "date_modified": "2017-05-18T13:20:27+00:00",
            "author": {
                "name": "Liz Murphy"
            },
            "tags": [
                "barrel-aged"
            ]
        },
        // ...
    ]
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].