This is the official Storyblok PHP client to easily access the Content Delivery API and Management API.
With the Storyblok PHP client you can integrate two kinds of Storyblok APIs:
- Management API: typically used for managing data, like creating data, blocks, settings etc.
- Content Delivery API: typically used for retrieving data, for example when you want to build your public Web application.
In this README file you will find information for using the Storyblok PHP client, like:
- Installing Storyblok PHP client
- Using the Management API
- Using the Content Delivery API
- Retrieving Draft or Published content
- Managing cache
- Resolve Relations and Links
You can install the Storyblok PHP Client via composer. Storyblok's PHP client requires PHP version 7.3 to 8.3. The suggestion is to use an actively supported version of PHP (8.2 and 8.3).
If you want to install the stable release of Storyblok PHP client you can launch:
composer require storyblok/php-client
If you want to install the current development release, you can add the version dev-master
:
composer require storyblok/php-client dev-master
For executing the command above, you need to have composer installed on your development environment. If you need to install Composer, you can follow the official Composer documentation:
- Install Composer on GNU Linux / Unix / macOS
- Install Composer on Windows
We suggest using the latest version of PHP.
Now we are going to see how to initialize the Storyblok Management Client for the Management API](https://www.storyblok.com/docs/api/management) with your Personal OAuth Token.
The Personal OAuth token is taken from the "My Account" section. This token is used for read and write operations.
The class for using the Management API is the Storyblok\ManagementClient
class. When you are going to instance a new ManagementClient
object you can use the Personal OAuth Token as a parameter.
<?php
// Require composer autoload
require 'vendor/autoload.php';
// Use the Storyblok\ManagementClient class
use Storyblok\ManagementClient;
// Use the ManagementClient class
$managementClient = new ManagementClient('your-storyblok-oauth-token');
Now, you have the ManagementClient
object ($managementClient
), you can start to manage your Storyblok data.
If you need to retrieve data, you have to perform an HTTP request with the GET
method.
The ManagementClient provides a get()
method for performing the HTTP request.
The mandatory parameter is the path of the API ( for example spaces/<yourSpaceId/stories
). The path defines which endpoint you want to use.
For retrieving a list of Stories:
$spaceId = 'YOUR_SPACE_ID';
$result = $managementClient->get('spaces/' . $spaceId . '/stories')->getBody();
print_r($result['stories']);
With getBody()
method you can access the body response, and then access the stories
key, to access the story list.
If you need to create data, you have to perform an HTTP request with the POST
method.
The ManagementClient provides a post()
method for performing the HTTP request.
The mandatory parameter is the path of the API ( for example spaces/<yourSpaceId/stories/
), and the Story payload.
For creating a new story:
$spaceId = 'YOUR_SPACE_ID';
$story = [
"name" => "New Page",
"slug" => "page-1",
"content" => [
"component" => "page",
"body" => []
]
];
$result = $managementClient->post(
'spaces/' . $spaceId . '/stories/',
[ 'story' => $story ]
)->getBody();
print_r($result);
If you need to update data, you have to perform an HTTP request with PUT
method.
The ManagementClient provides a put()
method for performing the HTTP request.
The mandatory parameter is the path of the API ( for example spaces/<yourSpaceId/stories/<storyId>
), and the Story payload.
For updating the story:
$spaceId = 'YOUR_SPACE_ID';
$storyId= 'theStoryId';
$story = [
"name" => "Update Home Page"
];
$result = $managementClient->put(
'spaces/' . $spaceId . '/stories/' . $storyId,
[ 'story' => $story ]
)->getBody();
print_r($result);
If you need to delete data, you have to perform an HTTP request with the DELETE
method.
The ManagementClient provides a delete()
method for performing the HTTP request.
The mandatory parameter is the path of the API, defining also the identifier of the entry you want to delete ( for example spaces/<yourSpaceId/stories/<storyId>
).
For deleting a story:
$spaceId = 'YOUR_SPACE_ID';
$storyId = 'YOUR_STORY_ID';
$result = $managementClient->delete('spaces/' . $spaceId . '/stories/' . $storyId)->getbody();
print_r($result);
When creating a Space, you can select the EU, US, CA, AP region. The default region is EU.
EU: api.storyblok.com
US: api-us.storyblok.com
CA: api-ca.storyblok.com
AP: api-ap.storyblok.com
For example:
If you want to access a Space created in US region, you need to define the apiEndpoint
parameter with api-us.storyblok.com
value, and forcing the ssl
option for using HTTPS protocol:
use Storyblok\ManagementClient;
$client = new ManagementClient(
apiKey: 'your-storyblok-oauth-token',
apiEndpoint: "api-us.storyblok.com",
ssl : true
);
Now you have the Storyblok\ManagementClient
instance, you can start managing data.
Now we are going to see how to initialize the Storyblok Client class for consuming the Content Delivery API V2, with the Access Token. You can retrieve the access token from the "Settings > Access Tokens" tab (in your space, in Stroyblok UI).
<?php
// Require composer autoload
require 'vendor/autoload.php';
// Use the Storyblok\Client class
use Storyblok\Client;
// Use the Client class
$client = new Client('your-storyblok-readonly-accesstoken');
If you want to use an alias to refer to the Storyblok\Client
class, you can use the use ... as ...
statement:
require 'vendor/autoload.php';
use Storyblok\Client as StoryblokClient;
// Use the Storyblok\Client class via alias
$client = new StoryblokClient('your-storyblok-readonly-accesstoken');
When you create a Space, you can select the region: EU, US, CA or AP.
For example:
If you want to access a Space created in US region, you need to define the apiRegion
parameter with the us
value (or US
):
use Storyblok\Client;
$client = new Client(
apiKey: 'your-storyblok-readonly-accesstoken',
apiRegion: 'us'
);
If you are still using PHP 7.x, you have to use the old notation (without named arguments):
use Storyblok\Client;
$client = new Client(
'your-storyblok-readonly-accesstoken',
null,
'v2',
false,
'us'
);
Now you have the Storyblok\Client
instance you can start consuming data.
require 'vendor/autoload.php';
use Storyblok\Client as StoryblokClient; // you can use also an alias
$client = new StoryblokClient('your-storyblok-readonly-accesstoken');
$data = $client->getStoryBySlug('home')->getBody();
// access to the body response...
print_r($data["story"]);
echo $data["cv"] . PHP_EOL;
print_r($data["rels"]);
print_r($data["links"]);
If are using the field-level translation, you can retrieve a story for a specific language via the language()
method. The language method requires a string as a parameter with the code of the language.
require 'vendor/autoload.php';
use Storyblok\Client;
$client = new Client('your-storyblok-readonly-accesstoken');
$client->language('it');
$data = $client->getStoryBySlug('home')->getBody();
// access to the body response...
print_r($data["story"]);
If you need to access some space information like space identifier, space name, the latest version timestamp, or the list of configured languages you can use the spaces
endpoint.
<?php
require 'vendor/autoload.php';
use Storyblok\Client as StoryblokClient; // you can use also an alias
$client = new StoryblokClient('your-storyblok-readonly-accesstoken');
$space = $client->get('spaces/me/' , $client->getApiParameters());
$data = $space->getBody();
print_r($data);
// Array of the language codes:
print_r($data["space"]["language_codes"]);
// The latest version timestamp:
echo "Last timestamp : " . $data["space"]["version"] . PHP_EOL;
// The space name:
echo "Space name : " . $data["space"]["name"] . PHP_EOL;
// The space id:
echo "Space id : " . $data["space"]["id"] . PHP_EOL;
Because the PHP Client, with the current version, doesn't provide an helper for retrieving data from the space endpoint you can use the get()
method for accessing the spaces/me
path of the Content Delivery API. The only thing you need to remember is to set the second parameter for the get()
method injecting the API parameters. Even if you didn't set any parameters, you have to send getApiParameters()
as the second parameter for the get()
method because the PHP client manages for you some core parameters like the token. This is because you are using the low-level method get()
.
require 'vendor/autoload.php';
use Storyblok\Client as StoryblokClient; // you can use also an alias
$client = new StoryblokClient('your-storyblok-readonly-accesstoken');
$client->getStoryByUuid('0c092d14-5cd4-477e-922c-c7f8e330aaea');
$data = $client->getBody();
The structure of the data returned by the getBody()
of the getStoryByUuid()
method, has the same structure of the getStoryBySlug()
so: story
, cv
, rels
, links
.
If you need to retrieve a list of stories you can use the getStories()
method.
You can use the parameter to filter the stories.
For example, if you want to retrieve all entries from a specific folder you can use starts_with
option in this way:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
// Get all Stories from the article folder
$client->getStories(['starts_with' => 'article']);
$data = $client->getBody();
print_r($data["stories"]);
echo $data["cv"] . PHP_EOL;
print_r($data["rels"]);
print_r($data["links"]);
Under the hood, the starts_with
option, filters entries by full_slug
.
Because the response from Storyblok API could be paginated, you should walk through all the pages to collect all the entries.
The Storyblok PHP Client provides you a helper named getAll()
for retrieving all the entries.
Under the hood, the getAll()
method performs all the API call according to the pagination data (total, per page etc).
Example, retrieving all stories:
$client = new Client('your-storyblok-readonly-accesstoken');
$options = $client->getApiParameters();
$options['per_page'] = 3;
$stories = $client->getAll('stories/', $options);
If you want to retrieve the array of the responses for each call:
$client = new Client('your-storyblok-readonly-accesstoken');
$options = $client->getApiParameters();
$options['per_page'] = 3;
$response = $client->getAll('stories/', $options, true);
With the Storyblok\Client
you have also the getDatasourceEntries()
method for retrieving the list of key/values of the datasource:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
// Get category entries from datasource
$client->getDatasourceEntries('categories');
// will return as ['name']['value'] Array for easy access
$nameValueArray = $client->getAsNameValueArray();
// instead, if you want to retrieve the whole response, you can use getBody() method:
$data = $client->getBody();
If you want to receive also the dimension values besides the default values in one datasource entry you can use the option dimension when you call getDatasourceEntries() method. You could use dimensions for example when you are using datasource for storing a list of values and you want a translation for the values. In this case, you should create one dimension for each language.
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
// Get product entries with dimension 'de-at'
$client->getDatasourceEntries('products', ['dimension'=> 'de-at']);
// show the dimension values:
foreach ($client->getBody()['datasource_entries'] as $key => $value) {
echo $value['dimension_value'] . PHP_EOL;
}
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
// Get all Tags
$client->getTags();
// will return the whole response
$data = $client->getBody();
// will return as ['tagName1', 'tagName2'] Array for easy access
$stringArray = $client->getAsStringArray();
When you perform a request to Content Delivery API, you can access the headers of the HTTP response.
For example, after you call the getStories()
method (for retrieving a list of stories) you can access to the HTTP response headers via getHeaders()
method:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$result = $client->getStories();
$headersData = $client->getHeaders();
print_r($headersData);
In a Web application where the query string is available, the content delivery client checks automatically the GET parameters:
_storyblok
to get the draft version of a specific story_storyblok_published
to clear the cache.
If you want to override this "default" behavior, or you are in a non-web context (for example you are implementing a command line tool), to retrieve the draft content (for example a not yet published story) you have to use the editMode()
method.
If you want to retrieve the published content (for example a published story) you have to use the editMode(false)
method with false
parameter.
require 'vendor/autoload.php';
use Storyblok\Client as StoryblokClient; // you can use also an alias
$client = new StoryblokClient('your-storyblok-readonly-accesstoken');
$client->editMode(); // forcing draft mode
$data = $client->getStoryBySlug('home')->getBody();
// access to the body response...
print_r($data["story"]);
echo $data["cv"] . PHP_EOL;
print_r($data["rels"]);
print_r($data["links"]);
When you perform an API request you can use the caching mechanism provided by the Storyblok PHP client.
When you initialize the Storyblok\Client
you can set the cache provider.
For example, using the setCache()
method you can define the provider (for example filesystem) and an array of options. In case you are using the filesystem as storage of cache items, you can set the path with path
option:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$client->setCache('filesystem', [ 'path' => 'cache']);
$result = $client->getStories();
print_r($result);
You can set a TTL value for the cache via default_lifetime
option.
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$client->setCache('filesystem',
[
'path' => 'cache',
'default_lifetime' => 3600
]);
$result = $client->getStories();
print_r($result);
The caching mechanism uses under the hood the Symfony Cache package. So, you can use the Adapter supported the Symfony Cache. For example, for using a MySql database as cache storage, you can setup the connection via the PHP PDO class:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$pdo = new PDO('mysql:host=127.0.0.1;dbname=db_php-client;charset=utf8mb4;', "root");
$client->setCache('mysql', ['pdo' => $pdo]);
$result = $client->getStories();
print_r($result);
In order to flush the cache when the user clicks publish, you need to listen to the published event in javascript or define a webhook in the space settings that clears the cache on your server.
<script type="text/javascript" src="//app.storyblok.com/f/storyblok-latest.js"></script>
<script type="text/javascript">
storyblok.init()
storyblok.on('published', function() {
$.ajax({
url: '/clear.php'
})
})
</script>
In clear.php:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$client->setCache('filesystem', array('path' => 'cache'));
// Flush the whole cache when a story has been published
$client->flushCache();
// Or empty the cache for one specific item only
$client->deleteCacheBySlug('home');
$tree = $client->editMode()->getLinks()->getAsTree();
echo '<ul>';
foreach ($tree as $item) {
echo '<li>' . $item['item']['name'];
if (!empty($item['children'])) {
echo '<ul>';
foreach ($item['children'] as $item2) {
echo '<li>' . $item2['item']['name'] . '</li>';
}
echo '</ul>';
}
echo '</li>';
}
echo '</ul>';
Use the following script if you have Nginx SSI enabled and experience issues with printing the _editable html comments directly to manually parse the Storyblok HTML editable comments: https://gist.github.com/DominikAngerer/ca61d41bae3afcc646cfee286579ad36
In order to resolve relations you can use the resolveRelations
method of the client passing a comma separated list of fields:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$client->resolveRelations('component_name1.field_name1,component_name2.field_name2')
$client->getStoryBySlug('home');
Another example:
use Storyblok\Client;
$client = new Client('your-storyblok-readonly-accesstoken');
$client->resolveRelations('popular-articles.articles');
$result = $client->getStoryBySlug("home")->getBody();
In order to resolve links, you can use the resolveLinks
method passing the specific type of resolving you want to perform among url
, story
or link
:
$client = new \Storyblok\Client('your-storyblok-readonly-accesstoken');
$client->resolveLinks('url')
$client->getStoryBySlug('home');
When using the CDN API V1, you can't resolve relationships of resolved entries and the resolved entries are injected in the field of the relationship. The same happens with links resolving.
When using the CDN API V2 you can resolve also nested relationships in the resolved entries (just 2 levels deep), but the resolved entries are not injected in the fields, they are inserted in an array called rels
which is in the root object. The resolved links will be placed in an array called links
.
In case you are using the API V2, to keep a consistent behaviour with the API V1, this client will inject the resolved entries and links inside the fields for you.
The package includes tools for tests and code formatting:
- PestPHP
- PHP CS Fixer To execute the code quality suite you can use:
composer run all-check
that executes:
- vendor/bin/php-cs-fixer fix
- vendor/bin/pest
- Storyblok & PHP on GitHub: Check all of our PHP open source repos;
- Storyblok PHP Richtext Renderer: This package allows you to get an HTML string from the richtext field of Storyblok;
- Storyblok Laravel Tutorial : Add a Headless CMS to Laravel in 5 minutes.
-
Bugs or Feature Requests? Submit an issue;
-
Do you have questions about Storyblok or do you need help? Join our Discord Community.
Please see our contributing guidelines and our code of conduct. This project use semantic-release for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check this question about it in semantic-release FAQ.
This repository is published under the MIT license.