Giter Site home page Giter Site logo

element-api's Introduction

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 4.3.0+ or 5.0.0+.

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 plugin/install element-api

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 [
                        'id' => $entry->id,
                        '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',
],

contentType

The content type the endpoint responses should have.

'contentType' => 'application/foo+json',

By default, the content type will be:

  • application/javascript for endpoints that define a JSONP callback
  • application/feed+json for endpoints where the serializer is set to jsonFeed
  • application/json for everything else

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:

  • true (default) – results are cached for the duration specified by the cacheDuration Craft config setting, or until a relevant element is saved or deleted.
  • false – results are never cached.
  • 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

cacheKey

The key that responses should be cached with, if something custom is needed.

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.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),
                'authors' => [
                    ['name' => $entry->author->name],
                ],
                'language' => $entry->getSite()->language,
                '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"
            ]
        },
        // ...
    ]
}

element-api's People

Contributors

aaronbushnell avatar angrybrad avatar benjamindavid avatar brandonkelly avatar carlcs avatar dependabot[bot] avatar freekvr avatar jackmcpickle avatar jeroenlammerts avatar kristoffeys avatar makeilalundy avatar mattandrews avatar olivierbon avatar qrazi avatar sevfurneaux avatar vlradstake avatar yoannisj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

element-api's Issues

install without composer

How do you install this plugin without composer? I looked into how to install composer but now I just want to smash my macbook and everything else within reach.

Securing the API

Brad,

Great work, any best practice for securing access to the API?

Thanks,
Sam

Any suggestions on how to authenticate API calls?

I wrote a client side nodeJS app with a craftCMS backend using the ElementAPI for my REST endpoints. Is it possible to authenticate requests from a separate server? Ideally, I'd be able to send a session token along with my requests.

Most elementTypes don't work

Using V1 with Craft 2.6.2978 only a few elementtypes work, the rest gives me this message.

Argument 1 passed to Craft\ConfigService::Craft{closure}() must be an instance of Craft\EntryModel, instance of Craft\AssetFileModel given

The ones that dont work include Asset, GlobalSet, MatrixBlock, User and my own Element Type, have you any suggestions?

Thanks

Headers not cached

Headers sent by the transformer are not cached when the cache option is enabled for an endpoint:

'cache' => true,
'criteria' => [
    'folderId' => $folder->id,
    'withTransforms' => ['galleryThumb', 'fullscreen']
],
'transformer' => function(AssetFileModel $image) {
    HeaderHelper::setHeader(['Access-Control-Allow-Origin' => '*']);
    // ...
}),

Caching

Adding the possibility to cache the json files would be be great

Missing "HeaderHelper"?

I'm trying to add some CORS headers to my endpoint (ref #4 ), but I can't use the "HeaderHelper" as it looks like it isn't present in Craft 3 helpers? Is there another way if settings headers for endpoints?

At the top:

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

And the relevant part where I'm trying to set the header:

    'api/work/<slug:{slug}>.json' => function($slug) {
      HeaderHelper::setHeader([
        'Access-Control-Allow-Origin' => 'http://example.com'
      ]);

Error thrown:
Class 'craft\helpers\HeaderHelper' not found

Using Craft 3 Beta 18 and Element API plugin 2.4.0

Nested objects containing array

I have an object look wich contains an object categories from type of array. Currently I have to do the following to display the categories proper in the response.

'endpoints' => [
        'looks.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'looks'],
            'transformer' => function(EntryModel $entry) {

                // Create an array of all the photo URLs
                $categories = [];
                foreach ($entry->categories as $category) {
                    $object = (object) ['id' => $category->id, 'title' => $category->title];
                    $categories[] = $object;
                }
                return [
                    'title' => $entry->title,
                    'id' => $entry->id,
                    'categories' => $categories
                ];
            },
        ]
    ]

Is there a more elegant way to doing this? Especially because Ill have a lot of more cases where I have to deal with arrays in objects and arrays in objects and so on.

A structure could looks something like this

[
    {
      name: "ads"
      categories: [
         {
            name: "asdasda"
            subCategories: [
                name: "asdasdsa"
           ]
          }
      ]
    }
]

how to load custom transformer in craft 3

I see in the docs how to write one, and how to use one in the config file but im a little confused on how to load the transformer class into the element api's config file?

currently i have it working by adding this to the top of the element-api.php config file, is this the right way?

require Craft::$app->path->getConfigPath().'/transformers/default.php';

Removing header

Hey,

I'm trying to remove some headers.

'api/looks' => function () {
            HeaderHelper::setHeader([
                'Cache-Control' => 'that works'
            ]);
            HeaderHelper::removeHeader("Cache-Control");
            HeaderHelper::removeHeader("Pragma");
            return Custom_ElementApiHelper::getParams([
                'criteria' => ['section' => 'looks'],
                'transformer' => 'looks'
            ]);
        },

But it does not work. Any idea?

Craft 3 bug

The plugin looks like it installed properly but when I go into setting it see the following:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'staging.craft_cpnav_layout' doesn't exist
The SQL being executed was: SELECT *
FROM craft_cpnav_layout

I used the Plugin Store to install.

After logout the session-information is still available.

Hey,

i am using the element-api 1.x with Craft 2.6.2986 to fetch user details.
When i log me out and fetch the user/info.json it still has the information in it.

Is this what you want?

Here is the element-api config.php:

<?php
namespace Craft;
return [
    'defaults' => [],
    'endpoints' => [
        'user/info.json' => [
            'elementType' => 'User',
            'criteria' => [
                'id' => craft()->userSession->getId()
            ],
            'first' => true,
            'transformer' => function (UserModel $user) {
                return [
                    'email' => $user->email,
                    'firstName' => $user->firstName,
                    'lastName' => $user->lastName
                ];
            },
        ]
    ]
];

thx for answering

Feature Request: Support drafts and live preview with element api

We are working on a site that's built in VueJs and loads all its data via the element api. The big downside that we have found is there doesn't seem to be a way to support sharable draft urls or live preview which is a big bummer for our clients

Would there be anyway to support the same sort of "token?=" params for the for the element api? We could do the work to handle the rest assuming there was some way to get the preview and/or draft data via the api

Transformer Instance: Cannot use object of type MyTransformerName as array

Less of an issue, more of a documentation update.

The docs make mention of using a class instance for a transformer.

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

Having no experience with Fractal, I found this a bit confusing, and was always getting an error returned reading: "Fatal error: Cannot use object of type Craft\MyTransformerClassName as array in /Users/george/myCraftApp/craft/app/framework/YiiBase.php on line 183".
I figured it out in the end - but not sure if my solution was the best way tackle it. Would love your feedback, and a possible docs update.

In my custom class transformer, I had to extend League\Fractal\TransformerAbstract as follows:

In /craft/config/MyTransformerClassName.php:


    require craft()->path->getPluginsPath().'elementapi/vendor/autoload.php';
    use League\Fractal\TransformerAbstract;
    class MyTransformerClassName extends TransformerAbstract{
        public function transform(EntryModel $entry) {
            return [
                'slug' => $entry->slug,
                //... more custom props
            ];
        }
    }

Multilanguage support?

Hi,

is it possible to send language in the request? Example I have mobile app that talks with element-api and user (not logged in) would be able to choose the language that he wants to see.

thanks

Feature request: Api wrapper class

Hey there, I'm quite new to Craft, so if this won't fit in the conventions, be free to close this issue.
Coming mainly from Laravel, the syntax to define endpoints seems a little off to me. I'd favor to use something like $api->addEndpoint(string $uri, Closure $handler);. On the one hand, that'd make IDE hints a tad more useful. On the other, it'd be nice to have a $api->addCollection(string $uri, Closure $endpointsCallback);, too. Within this $endpointsCallback, one could define additional endpoints sharing the collection URI as a prefix. That'd allow for conveniently splitting the elementapi.php into multiple files once the number of endpoints grows.
I've made a little proof of concept class which you'll find in in this gist, including usage examples. This could obviously be extended in functionality.

What's your opinion on this?

Example for matrix field

Could you set up a more elaborate example with matrix fields and asset retrieval? I have an entry with a matrix field that has multiple block types (images and text). I got it working so that I can already see the text but I can't get the assets. Just one working example would be a great help. Then I wouldn't have to go through the entire templating docs when I just want to use this plugin.

IP Whitelist

I am trying to restrict access to the API. Where do you think would be the best place to add a whitelisting? Could it technically be possible to add the logic directly to the elementapi.php file?

Auth

Hey guys.

Any way to implement a auth layer over the element api? Even if it's just Basic Auth?

Craft 3: Pagination leads to Exception

Description

I have the following endpoint set up:

'api/countries.json' => [
    'elementType' => Tag::class,
    'criteria' => [
        'group' => 'blogCountries',
    ],
    'paginate' => true,
    'elementsPerPage' => 10,
    'pageParam' => 'pg',
    'transformer' => function (Tag $tag) {
        return [
            'title' => $tag->title,
            'id' => $tag->id,
        ];
    },
],

Accessing the endpoint at https://uwcblogs.dev/api/countries.json?pg=1 returns an exception:

2017-04-18 19:50:05 [192.168.10.1][1][vtdovftj2juuhu89hgnnken79d][error][yii\base\ErrorException:2] yii\base\ErrorException: Illegal string offset 'page' in /home/vagrant/sites/uwcblogs.com/vendor/craftcms/element-api/src/PaginatorAdapter.php:133
Stack trace:
#0 /home/vagrant/sites/uwcblogs.com/vendor/league/fractal/src/Scope.php(265): League\Fractal\Serializer\ArraySerializer->paginator()
#1 /home/vagrant/sites/uwcblogs.com/vendor/craftcms/element-api/src/controllers/DefaultController.php(89): League\Fractal\Scope->toArray()
#2 /home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/base/InlineAction.php(57): craft\elementapi\controllers\DefaultController->actionIndex()
#3 /home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/base/InlineAction.php(57): ::call_user_func_array:{/home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/base/InlineAction.php:57}()
#4 /home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/base/Controller.php(156): yii\base\InlineAction->runWithParams()
#5 /home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/base/Module.php(523): yii\base\Controller->runAction()
#6 /home/vagrant/sites/uwcblogs.com/vendor/craftcms/cms/src/web/Application.php(246): yii\base\Module->runAction()
#7 /home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/web/Application.php(102): craft\web\Application->runAction()
#8 /home/vagrant/sites/uwcblogs.com/vendor/craftcms/cms/src/web/Application.php(211): yii\web\Application->handleRequest()
#9 /home/vagrant/sites/uwcblogs.com/vendor/yiisoft/yii2/base/Application.php(380): craft\web\Application->handleRequest()
#10 /home/vagrant/sites/uwcblogs.com/public/index.php(22): yii\base\Application->run()
#11 {main}

The exception is only thrown when the number of countries exceeds the allowed 'elementsPerPage', i.e. when there would be multiple pages.
Turning pagination off also removes the issue.

Additional info

  • Craft version: Craft 3-beta.12
  • PHP version: 7.1.4
  • Database driver & version: MySQL 5.7.17
  • Plugins & versions: Element Api 2.0.1

Breaks with nested arrays in GET

Since #6, there is now a "Array to string conversion" notice if you try and pass an array in the GET.
E.g. ?criteria[section]=foo

It looks like UrlHelper/getUrl/_normalizeParams doesn't play nice with nested arrays.

A little more clarity please, will help transfer api from Craft 2

I had a usual session of tracing though what Craft was actually doing with its abstractions last night, to get this plugin running, which it actually does.

You could make this all much easier and accessible by making the following clear:

  • the name of the config file now has to be element-api.php, not elementapi.php as before. No doubt due to the snake-case worldview now present, but mis-stated in your plugin doc. In which case, all you get is 404s.

  • when stating that, very clarifying would be to say that element-api.php is handled by the standard Yii-Craft config system; thus all related patterns apply, and "endpoints" are just an array of routing paths with their dispositions

  • thus, what you put in your given endpoint hard-defines the path that will access its element(s).

  • so, if you want //domain/api/endpoint, specify "api/endpoint.json" as the name. If you want simply //domain/endpoint to be the access, use "/endpoint.json" instead.

  • your example illustrates only the second case, which differs from how Craft 2's elementapi showed it, hence more unnecessary 404s. I'd think including the uri for the api call would be a very good idea, not to say mentioning you're showing a fresh style, adjustable to preference.

Busting cache on endpoint/element changes

Is there any way to turn caching on, but bust the cache when that endpoint/element changes through the cms? At the moment the caching is working great, but I have to manually bust the cache any time anything on the cms side changes. Is this the expected behavior and if not -- am I missing something here?

'api/v2/faqs.json' => [
    'cache' => 'PT1M',
    'elementType' => 'Entry',
    'criteria' => [
        'section' => 'faq'
    ],
    'transformer' => function(EntryModel $entry) {
        $categories = [];
        foreach($entry->faqCategory as $category){
          $categories[] = $category->id;
        }
        return [
            'title' => $entry->title,
            'answer' => (string)$entry->answer,
            'categories' => $categories,
        ];
    },
],

Thanks so much for the absolutely AWESOME plugin.

Best way to split elementary.php

My file gets longer and longer for all the different endpoints I have.

Is there a elegant way to split this. i.e.. For each endpoint a new file for even using the ElementAPI somehow inside a template?

Feature request: querying by EntryRevisions

I want to be able to request a specific revision (or a draft version) of an entry, in order to simulate a live preview feature for my site (a NodeJS app). Is this possible to do currently, or alternatively are there any plans to add this feature?

As far as I can tell, the Entry Query Params don't offer any parameters to query by revision/draft ID, and the EntryRevisionsService isn't available alongside the Entry element type here.

Error when using parameter 'first' => true,

Have been receiving this error when attempting to set a limit to results:
Argument 2 passed to League\Fractal\Serializer\ArraySerializer::item() must be of the type array, object given, called in /var/www/Sites/craft-records/craft/plugins/elementapi/vendor/league/fractal/src/Scope.php on line 286 and defined

It works if I set the object to an array, although the JSON does not return the key "data"
$result = (array) $result;

Commerce Shipping Addresses

I'm trying to pull out the available shipping addresses for the current user during the checkout process. I can't seem to find the proper elementType to use.

I'm currently trying: 'elementType' => 'Commerce_AddressModel'

I'm getting an exception No element type exists by the type “Commerce_AddressModel”.

Is it possible to pull this in?

JSON Feed example errors

I've noticed that when using the JSON Feed example in the docs it throws an error:
"InvalidConfigException" -> 'Endpoint has an invalid elementType'.

This can be rectified by using:

`'elementType' => craft\elements\Entry::class

and also using:

`'transformer' => function(craft\elements\Entry $entry)

Craft Version: Craft CMS 3.0.0-beta.29
Element API Version: 2.4.3

Are `paginate` and `elementsPerPage` really necessary?

When providing an endpoint with an ElementCriteriaModel, it already contains a limit attribute, which to my mind is exactly what elementsPerPage represents. And it would seem that, unless limit were explicitly set to null, that pagination is expected as part of the response.

With that in mind, are these configurations really necessary?

Elements creation

Hi there,

Thanks for creating that plugin, it's really handy in this world of web apps!

I have 2 questions regarding the future of this plugin.
Are you planning to maintain it in the long term?
Are you planning to add a "write" feature ? (elements creation, user registration...)

Thanks and keep up the good work 👍

Publish to packagist

Can this package be publish to packagist so that we can all composer require it without adding the repo to composer.json?

HTTP 404 – Not Found – yii\web\NotFoundHttpException

Please help

http://mysteryperutours.com/api/destino.json

HTTP 404 – Not Found – yii\web\NotFoundHttpException
Template not found

index.php:

define('CRAFT_TEMPLATES_PATH', "web/templates");
// Set path constants
define('CRAFT_BASE_PATH', dirname(__DIR__).'/public_html/craft');

craft/config/elementapi.php:

<?php

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

return [
    'endpoints' => [
        'api/destino.json' => [
            'elementType' => Entry::class,
            'criteria' => ['section' => 'destino'],
            'transformer' => function(Entry $entry) {
                return [
                    'title' => $entry->title,
                    'url' => $entry->url,
                ];
            },
        ]
    ]
];

Exception thrown when trying to fetch SproutForms_Entry entries

I'm trying to pull back all sprout form entries using the following elementapi.php file;


<?php

    namespace Craft;

    return [
        "endpoints" => [
            "comp-results/<sourceEntryId:\d+>" => [
                "elementType" => "SproutForms_Entry"
            ]
        ]
    ];

Unfortunately Craft is throwing the following exception;

Internal Server Error

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'entries.entries.dateCreated' in 'order clause'

Using Craft CMS 2.6.2780, Element API 1.2.1, and Sprout Forms 2.2.5

Query string not preserved for prev / next links

My endpoint is set up to return entries conditional on params of my query string, e.g., example.com/api/entries?lat=48.772789&lng=9.154120.

This query string is not preserved for the generated pagination links in the "meta" section. Is there anything I can do to make it preserve the info? Thanks

{"next": "http:\/\/example.com\/api\/entries?page=2"}

Ordering by Category and Title

Is it possible to output the JSON in order by Category (group) and Title? I've managed to find a way using the Group parameter but if I add 'order' => 'Title' it will no longer group by category.

'criteria' => ['section' => 'stockistsListing', 'search' => 'stockistRegion:*', 'group' => 'stockistRegion.first().title'],

Missing CORS Header

Maybe I'm missing some global settings here, but it seems there is no way to set proper CORS headers for the JSON response.

If that's really just an oversight I'd be willing to contribute the necessary PR.

Craft Rich Text and Matrix

Hi

The json nodes work well although I seem to be getting blank data for any Rich Text Fields or Matrix Fields from Craft.
I also dont see any way to pull in locale translation nodes? I am only seeing the English nodes

Exceptions: output html

So I just installed this plugin (v1, 1.4.0) and had an Exception occur because I was trying to use a property on the Entry model that does not exist. To my surprise the output to the browser was the default html output. But since the JSON headers were already output, the browser just shows the html source of what otherwise would be a normal page showing error details.

Did I miss something, or is this an idea for a feature request?

[Help wanted] Element API Cache Key

Hi all,

I'm creating an API for a react native app to consume and would like to do some cache busting in the background, I'm currently able to achieve the results I want with

craft()->cache->flush()

but that clears the entire entry cache, I would like to manually delete the element api cache but can't for the life of me work out what the key is. Is there anyone that can assist me?

Thanks

elementType: Purchasable

Hi, not sure what i'm doing wrong here!

Purchasable is a custom element type in craftcommerce (ref), however I've tried multiple things and tey all error:

'elementType' => 'purchasable',
'elementType' => 'Purchasable',
'elementType' => 'product',

you see where I am going with this ;-)

I can retrieve Entry, Category etc just fine!

any help would be much appreicated

Feature Request: Minify output

Hi guys

It seems like it isn't possible to minify the output from the API. Google pagespeed discovered the issue in my project's API. It could save 75% when compressions would be enabled.

Is this possible and if not can this be added to the next version :)?

Thanks!

Get error on log

Here is the message:

[status code] 404
[reason phrase] Not Found
[url] https://raw.githubusercontent.com/pixelandtonic/ElementAPI/master/releases.json
2017/08/04 12:07:50 [warning] [application] A “Formulare” release was skipped because it is invalid:
 - Missing required attributes (version, downloadUrl, date, notes)```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.