craftcms/element-api
Composer 安装命令:
composer require craftcms/element-api
包简介
Create a JSON API for your elements in Craft
README 文档
README
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\Assetcraft\elements\Categorycraft\elements\Entrycraft\elements\GlobalSetcraft\elements\MatrixBlockcraft\elements\Tagcraft\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/javascriptfor endpoints that define a JSONP callbackapplication/feed+jsonfor endpoints where the serializer is set tojsonFeedapplication/jsonfor 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:
'array'(default) – formats data using the ArraySerializer.'dataArray'– formats data using the DataArraySerializer.'jsonApi'– formats data using the JsonApiSerializer.'jsonFeed'– formats data based on JSON Feed V1.1 (see the JSON Feed example below).- A custom serializer instance.
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 thecacheDurationCraft 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" ] }, // ... ] }
craftcms/element-api 适用场景与选型建议
craftcms/element-api 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 710.78k 次下载、GitHub Stars 达 502, 最近一次更新时间为 2017 年 02 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「json」 「api」 「cms」 「yii2」 「craftcms」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 craftcms/element-api 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 craftcms/element-api 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 craftcms/element-api 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Kinikit - PHP Application development framework MVC component
GraphQL authentication for your headless Craft CMS applications.
Set Links with a specific language parameter
Supercharged text field validation.
ext-json wrapper with sane defaults
A package to cast json fields, each sub-keys is castable
统计信息
- 总下载量: 710.78k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 502
- 点击次数: 18
- 依赖项目数: 10
- 推荐数: 1
其他信息
- 授权协议: MIT
- 更新时间: 2017-02-10