A modern PHP SDK for Contentful delivery and management APIs.
Click Here for Laravel facades, a base repository, out-of-the-box caching and cache management, webhook creation by command and more.
New to Contentful? Contentful is an API driven CMS. Check out their website and API documentation.
Install via composer by running:
composer require "incraigulous/contentful-sdk:0.0.*"
Create a new instance of the delivery SDK:
use Incraigulous\ContentfulSDK\DeliverySDK;
$deliverySDK = new DeliverySDK('TOKEN', 'SPACE_ID', $cacher);
Token: Your Contentful API token. You can generate this using the Contentful control panel.
Space ID: (optional) The space to use for calls made by the instance. To use multiple spaces, you should use multiple SDK instances. If you don't provide a space ID, you'll only be able to use the spaces
resource.
Cacher: (optional, Incraigulous\ContentfulSDK\CacherInterface Implementation) An object to handle caching. This is optional (and easy to implement), so don't let it scare you off. Check out the caching section for more details.
$result = $deliverySDK->spaces()->get();
$result = $deliverySDK->spaces()
->find('SPACE_ID')
->get();
$result = $deliverySDK->contentTypes()
->find('CONTENT_TYPE_ID')
->get();
$result = $deliverySDK->contentTypes()
->where('name', '=', 'Blog Post')
->get();
or
$result = $deliverySDK->contentTypes()
->where('name', 'ne', 'Blog Post')
->limit(2)
->get();
See Search Parameters to learn how to search for specific things.
$result = $deliverySDK->entries()
->find('ENTRY ID')
->get();
$result = $deliverySDK->entries()
->limitByType('CONTENT TYPE ID')
->where('fields.title', 'match', 'campus')
->where('fields.location', 'near', '22,23')
->limit(10)
->get();
$result = $deliverySDK
->where('sys.id', '=', 'ENTRY ID')
->includeLinks(3)
->get();
includeLinks
takes the number of link levels you want to include.
$result = $deliverySDK->assets()
->limit(10)
->get();
$deliverySDK->assets()
->find('ASSET ID')
->get();
$result = $deliverySDK->assets()
->where('fields.file.details.size', '>=', 350000)
->limit(5)
->get();
Searching is easy! Just call one or more of the following methods on your resource. The use of where() and limit() on the assets resource as shown above is a great example of searching.
Method | Parameters | Description |
---|---|---|
find | id | Limit results by ID |
where | field, operator, value | Limit results by operator search |
full | search | Alias for query |
query | search | Search all records for text match. See filters below. |
order | orderBy, $reverse = false | Order results by a field |
limit | number | Limit results by a quantity |
skip | number | Skip a quantity of results |
Accepted Values | Produces Contentful Operator | Description |
---|---|---|
= | = | Equality: Search for exact matches |
!=, [ne], ne | [ne] | Inequality: Search for exact matches |
[in], in | [in] | Inclusion: Search for multiple matches |
[nin], nin | [nin] | Exclusion: Search for multiple matches |
<, [lt], lt | [lt] | Less Than: Number & date ranges |
>, [gt], gt | [gt] | Greater Than: Number & date ranges |
>=, [gte], gte | [gte] | Greater Than or Equal To: Number & date ranges |
match, [match] | [match] | Match: Full-text search on a specific field |
near, [near] | [near] | Near: Search for location near position |
within, [within] | [within] | Within: Search for location within bounding rectangle |
Anything not listed | ['YOUR OPERATOR HERE'] | Default |
For more detailed documentation on searching, see Contentful's API documentation.
I recommend you cache all Delivery API GET request results (i.e. Memcached or Redis). If you're working with a low traffic website you might be able to get by without caching, but it will greatly improve performance in any case.
One way would be to wrap all your API GET calls in a cache check, but that could lead to code duplication. Lucky for you, there's a better way.
I've included a cacher interface. Don't worry, it only requires four methods. Just build a class that implements Incraigulous\ContentfulSDK\CacherInterface
and pass it as the third parameter when you instantiate the SDK. The SDK will handle the rest. Each GET request will be cached with a unique key built from the query using your cacher class.
$cacher = new CustomCacher();
$deliverySDK = new DeliverySDK('SPACE_ID', 'TOKEN', $cacher);
Here's an example using Laravel's Cache helper.
Create a new instance of the management SDK:
use Incraigulous\ContentfulSDK\ManagementSDK;
$managementSDK = new ManagementSDK('TOKEN', 'SPACE_ID');
Token: Your Contentful OAuth token.
Space ID: (optional) The space to use for calls made by the instance. To use multiple spaces, you should use multiple SDK instances. If you don't provide a space ID, you'll only be able to use the spaces
resource.
Note that there is a third parameter for the cacher. Management API calls are not currently cached to make sure that
GET
requests are up to date to avoid conflicts when updating records. I still wanted to allow a place to provide the cacher just in case I decide to use it for anything. Feel free to ignore it, or provide a cacher for good measure.
Contentful payloads can be complex, especially when working with entries
or assets
. Payload builders are here to help! They're optional helper classes to assist with building payloads. They take care of building payload arrays for you and let you know what options you have along the way. They're especially helpful if your IDE has hinting.
If you don't want to use them, don't use them. The SDK parases the payload looking for builder objects and turns them into arrays before passing requests on to Contentful. As such, you are free to use standard arrays, or arrays made up of payload builder objects.
The following examples will assume you're using the builders you need:
use Incraigulous\ContentfulSDK\PayloadBuilders\Entry;
use Incraigulous\ContentfulSDK\PayloadBuilders\EntryField;
use Incraigulous\ContentfulSDK\PayloadBuilders\Space;
...
$result = $managementSDK->spaces()
->post(
new Space('My Space')
);
$space = $managementSDK->spaces()
->find('SPACE_ID')
->get();
$space['name'] = 'Outer Space';
$result = $managementSDK->spaces()->put('SPACE_ID', $space);
$result = $managementSDK->spaces()->delete('SPACE_ID');
$result = $managementSDK->contentTypes()
->post(
new ContentType('Blog Post', 'title', [
new ContentTypeField('title', 'Title', 'Text'),
new ContentTypeField('body', 'Body', 'Text'),
])
);
);
$result = $managementSDK->contentTypes()
->post(
new ContentType('Blog Post', 'title', [
new ContentTypeField('title', 'Title', 'Text'),
new ContentTypeField('body', 'Body', 'Text'),
(new ContentTypeField('author', 'Field List', 'Link'))->setLink('Entry'),
(new ContentTypeField('sidebar', 'Field List', 'Array'))->setMultiLink('Entry'),
(new ContentTypeField('category', 'Category', 'Text'))->setValidations((new ContentTypeValidation())->in(['Design', 'Development'])),
])
);
$contentType = $managementSDK->contentTypes()
->find('CONTENT_TYPE_ID')
->get();
$contentType['fields'][0]['name'] = 'Post Title';
$result = $managementSDK->contentTypes()->put('CONTENT_TYPE_ID', $contentType);
$contentType = $managementSDK->contentTypes()
->find('CONTENT_TYPE_ID')
->get();
$result = $managementSDK->contentTypes()->publish('CONTENT_TYPE_ID', $contentType);
$contentType = $managementSDK->contentTypes()
->find('CONTENT_TYPE_ID')
->get();
$result = $managementSDK->contentTypes()->unpublish('CONTENT_TYPE_ID', $contentType);
$result = $managementSDK->contentTypes()->delete('CONTENT_TYPE_ID');
Parameters | Description |
---|---|
name | The content type name |
displayField | the title field key |
contentTypeFields | an array of content type fields. Can be a pure array or an array of ContentTypeField builder objects. |
Parameters | Description |
---|---|
id | The content type field id |
name | The content type field name |
type | The content type field type |
required | (default: false) is the field required |
localized | (default: false) is the field localized |
Methods | Parameters | Description |
---|---|---|
setLink | linkType (default: Entry) | Add a link to the field |
setMultiLink | linkType (default: Entry) | Add multiple links to the field |
setValidations | validations | A validations array or a contentTypeValidations payload builder object |
Takes no parameters.
Methods | Parameters | Description |
---|---|---|
size | min (default: null), max (default: null) | Validates that the size of a text, object or array is within a range. |
in | set (array) | Validates that the value of a field belongs to a predefined set. It's defined specifying the elements that form the valid set. |
regexp | $pattern, $flags (default: null) | Validates that the value of a field matches a Regular Expression. |
dateRange | min (default: null), max (default: null) | Validates that the value of a field is within a date range. |
assetFileSize | min (default: null), max (default: null) | Validates that the size of an asset is within a range. |
assetImageDimensions | height (default: null), width (default: null) | Validates that the dimensions of an image are within a range. |
$result = $managementSDK->entries()->contentType('CONTENT_TYPE_ID')->post(
new Entry([
new EntryField('title', 'Hello, World!'), //Create a field with only the default language
(new EntryField('body'))->addLanguage('en-US', 'Bacon is healthy!') //Add a language to a field.
])
);
Note that you are able to add content to a field without specifying a language. The default default language is en-US
. To specify a different default language, define a CONTENTFUL_DEFAULT_LANGUAGE
constant.
Example:
define('CONTENTFUL_DEFAULT_LANGUAGE', 'de-DE');
$result = $managementSDK->entries()->put('MY_CUSTOM_ID',
new Entry([
new EntryField('title', 'Hello, World!'),
(new EntryField('body'))->addLanguage('en-US', 'Bacon is healthy!')
])
);
$result = $managementSDK->entries()->contentType('CONTENT_TYPE_ID')->post(new Entry([
new EntryField('title', 'Hello, World!'),
(new EntryField('body'))->addLanguage('en-US', 'Bacon is healthy!'),
(new EntryField('sidebar'))->addMultiLink('ENTRY_ID', 'Entry')->addMultiLink('ENTRY_ID', 'Entry'),
(new EntryField('author'))->addLink('ENTRY_ID', 'Entry')
]));
$entry = $managementSDK->entries()
->find('ENTRY_ID')
->get();
$entry['fields']['title'] = new EntryField('title', 'Cheese is Healthy!');
$result = $managementSDK->entries()->put('ENTRY_ID', $entry);
$entry = $managementSDK->entries()->find('ENTRY_ID')->get();
$result = $managementSDK->entries()->publish('ENTRY_ID', $entry);
$entry = $managementSDK->entries()->find('ENTRY_ID')->get();
$result = $managementSDK->entries()->unpublish('ENTRY_ID', $entry);
$result = $managementSDK->entries()->archive('ENTRY_ID');
$result = $managementSDK->entries()->unarchive('ENTRY_ID');
$result = $managementSDK->entries()->delete('ENTRY_ID');
Parameters | Description |
---|---|
fields | An array of entry fields. Can be a pure array or an array of EntryField builder objects. |
Parameters | Description |
---|---|
name | The field name |
content | The field content |
language | (default: en-US or CONTENTFUL_DEFAULT_LANGUAGE constant) The default field language. |
Methods | Parameters | Description |
---|---|---|
addLanguage | languageKey | Add a language to the field. |
addLink | id, linkType (default: Entry), languageKey (default: en-US or CONTENTFUL_DEFAULT_LANGUAGE constant) | Create a relationship to a resource. |
addMultiLink | id, linkType (default: Entry), languageKey (default: en-US or CONTENTFUL_DEFAULT_LANGUAGE constant) | Create relationships to resources. |
$result = $managementSDK->assets()->post(new Asset([
new AssetField('title', 'Bacon Pancakes'),
new File("image/jpeg", "example.jpg", "https://example.com/example.jpg")
])
);
$result = $managementSDK->assets()->put('MY_CUSTOM_ID', new Asset([
new AssetField('title', 'Bacon Pancakes'),
new File("image/jpeg", "example.jpg", "https://example.com/example.jpg")
])
);
$asset = $managementSDK->assets()->find('ASSET_ID')->get();
$asset['fields']['file'] = new File("image/jpeg", "example.jpg", "https://example.com/example.jpg");
$result = $managementSDK->assets()->put('ASSET_ID', $asset);
$result = $managementSDK->assets()->process('ASSET_ID');
$asset = $managementSDK->assets()->find('ASSET_ID')->get();
$result = $managementSDK->assets()->publish('ASSET_ID', $asset);
$asset = $managementSDK->assets()->find('ASSET_ID')->get();
$result = $managementSDK->assets()->unpublish('ASSET_ID', $asset);
$result = $managementSDK->assets()->archive('ASSET_ID');
$result = $managementSDK->assets()->unarchive('ASSET_ID');
$result = $managementSDK->assets()->delete('ASSET_ID');
Parameters | Description |
---|---|
fields | An array of asset fields. Can be a pure array or an array of AssetField builder objects. |
Parameters | Description |
---|---|
name | The field name |
content | The field content |
language | (default: en-US or CONTENTFUL_DEFAULT_LANGUAGE constant) The default field language |
Methods | Parameters | Description |
---|---|---|
addLanguage | languageKey | Add a language to the field. |
Parameters | Description |
---|---|
contentType | The file content type |
fileName | The file name |
upload | The upload path |
language | (default: en-US or CONTENTFUL_DEFAULT_LANGUAGE constant) The language |
$result = $managementSDK->webhooks()->post(
new Webhook('http://www.example.com/')
);
$result = $managementSDK->webhooks()->put('WEBHOOK_ID',
new Webhook('http://www.example.com/')
);
$result = $managementSDK->webhooks()->delete('WEBHOOK_ID');
Parameters | Description |
---|---|
url | The callback URL for the webhook |
See a typo or a bug? Make a pull request.
What a new feature? Make a pull request.
Want a new feature and don't know how to build it? You can always ask, I might be game if I think it's a good enough idea.
I'm going to make issues for features that I would like implemented. I'll assign them to myself if I plan to take to build them out. If I leave them unasigned, please step up and take it!