Installation:
composer require atolye15/contentful-bundle
Ensure your composer.json requires twig/twig (for Twig integration).
Register the Bundle:
config/bundles.php:
return [
// ...
Atolye15\ContentfulBundle\ContentfulBundle::class => ['dev' => true],
];
AppKernel.php:
new Atolye15\ContentfulBundle\ContentfulBundle(),
Configure Contentful:
Create config/packages/contentful.yaml (Symfony 4) or app/config/config.yml (Symfony 3):
contentful:
delivery:
main:
space: "YOUR_SPACE_ID"
token: "YOUR_DELIVERY_TOKEN"
default: true
First Use Case: Fetch content in a controller:
use Contentful\Delivery\ClientInterface;
class PageController extends AbstractController
{
public function show(ClientInterface $client)
{
$entry = $client->getEntry('YOUR_ENTRY_ID');
return $this->render('page.html.twig', ['entry' => $entry]);
}
}
ClientInterface in services/controllers to leverage autowiring:
public function __construct(ClientInterface $client) { ... }
default: true in config to specify which client is autowired when multiple are defined.Fetching Entries:
$entry = $client->getEntry('entryId');
$fields = $entry->getFields();
Querying Content:
$entries = $client->getEntries([
'content_type' => 'blogPost',
'limit' => 10,
]);
Handling Assets:
$asset = $client->getAsset('assetId');
$url = $asset->getFields()->get('file')->getUrl();
Preview Mode:
Configure a separate client in config/packages/contentful.yaml:
contentful:
delivery:
preview:
space: "YOUR_SPACE_ID"
token: "YOUR_PREVIEW_TOKEN"
api: preview
Inject the preview client where needed:
public function __construct(ClientInterface $previewClient) { ... }
Caching: Enable caching in config:
contentful:
delivery:
main:
cache: true
Use cache:clear command to purge cached data.
Pass Contentful data to Twig templates:
return $this->render('template.html.twig', [
'entries' => $entries,
]);
Access fields in Twig:
{% for entry in entries %}
<h1>{{ entry.fields.title }}</h1>
{% for field in entry.fields %}
{{ dump(field) }}
{% endfor %}
{% endfor %}
php bin/console contentful:delivery:debug
php bin/console contentful:delivery:info
Breaking Changes in v4:
delivery is the top-level key:
contentful:
delivery: # <-- Correct
main: ...
Preview Mode:
api: preview in config. Without it, the client defaults to delivery.Caching:
contentful:
delivery:
main:
cache: true
space, locale, and content_type. Clear cache with:
php bin/console cache:clear
Locale Handling:
default_locale in config to avoid errors when fetching entries without a specified locale:
contentful:
delivery:
main:
default_locale: "en-US"
Web Profiler:
dev mode).Common Errors:
InvalidSpaceId: Verify space and token in config.InvalidEntryId: Ensure the entry ID exists in Contentful.AuthenticationError: Check token permissions (e.g., preview tokens can’t access delivery content).Logging:
contentful:
delivery:
main:
request_logging: true
Custom HTTP Client: Override the default Guzzle client:
contentful:
delivery:
main:
http_client: "@your_custom_guzzle_service"
URI Override: Useful for testing or custom endpoints:
contentful:
delivery:
main:
uri_override: "https://api.contentful.com"
Event Listeners:
Subscribe to Contentful events (e.g., Contentful\Delivery\Event\EntryFetchedEvent) via Symfony’s event dispatcher:
services:
App\EventListener\ContentfulListener:
tags:
- { name: kernel.event_listener, event: Contentful\Delivery\Event\EntryFetchedEvent, method: onEntryFetched }
Batch Requests:
Use getEntries() with limit and sys.id pagination to avoid fetching all entries at once:
$entries = $client->getEntries(['limit' => 100, 'sys.id' => ['in' => ['entry1', 'entry2']]]);
Selective Field Loading: Reduce payload size by specifying fields:
$client->getEntries(['content_type' => 'blogPost', 'fields' => ['title', 'summary']]);
Avoid Redundant Calls: Cache responses in your application layer if needed (e.g., using Symfony’s cache system):
$cache = $this->get('cache.app');
$cached = $cache->get('contentful_entries');
if (!$cached) {
$entries = $client->getEntries(...);
$cache->set('contentful_entries', $entries, 3600);
}
bundles.php from AppKernel.php.app/config/config.yml to config/packages/contentful.yaml.atolye15/contentful and contentful/contentful-bundle versions align (e.g., 4.2.* for SDK v4).%env%:
contentful:
delivery:
main:
token: "%env(CONTENTFUL_DELIVERY_TOKEN)%"
content_delivery_api or content_preview_api).
How can I help you explore Laravel packages today?