Installation
composer require atolye15/contentful
Basic Client Initialization
use Atolye15\Contentful\Client;
$client = new Client([
'space' => env('CONTENTFUL_SPACE_ID'),
'accessToken' => env('CONTENTFUL_ACCESS_TOKEN'),
'host' => env('CONTENTFUL_HOST', 'cdn.contentful.com'),
]);
First Use Case: Fetching an Entry
$entry = $client->getEntry('YOUR_ENTRY_ID');
echo $entry->getField('title');
.env for CONTENTFUL_SPACE_ID, CONTENTFUL_ACCESS_TOKEN, and CONTENTFUL_HOST.Entry class is the primary object for interacting with content.// Single entry
$entry = $client->getEntry('entryId');
// Entries by content type
$entries = $client->getEntriesByContentType('blogPost');
// Entries with a query
$entries = $client->getEntries([
'content_type' => 'blogPost',
'query' => 'laravel',
'limit' => 10,
]);
$asset = $client->getAsset('assetId');
$assetUrl = $asset->getUrl(); // Direct URL to the asset
$entry = $client->getEntry('entryId', 'fr-FR'); // French locale
Service Provider:
$this->app->singleton(Client::class, function ($app) {
return new Client([
'space' => config('contentful.space_id'),
'accessToken' => config('contentful.access_token'),
]);
});
Facade (Optional):
Publish the facade and create ContentfulServiceProvider to bind the client.
Eloquent Model Binding:
use Atolye15\Contentful\Eloquent\HasContentfulEntries;
class BlogPost extends Model
{
use HasContentfulEntries;
protected $contentfulType = 'blogPost';
}
$client = new Client([
'space' => '...',
'accessToken' => '...',
'cache' => new \Atolye15\Contentful\Cache\ArrayCache(), // Or use Laravel's cache
]);
.env for sensitive data like accessToken.Atolye15\Contentful\Exception\ContentfulException.getField() or getFields() for structured data. Example:
$title = $entry->getField('title');
$fields = $entry->getFields(); // All fields as an array
getEntries() with limit and offset for paginated results.Deprecated Methods:
get() directly on Entry or Asset objects. Prefer getField() or getFields() for consistency.// ❌ Avoid
$entry->get('title');
// ✅ Use instead
$entry->getField('title');
Locale Handling:
en-US. Explicitly pass locales for non-English content.$entry = $client->getEntry('entryId', 'es-ES'); // Spanish locale
Caching Quirks:
ArrayCache is in-memory and not persistent. Use Laravel’s cache or a persistent solution (e.g., Redis) for production.Field Type Mismatches:
$entry = $client->getEntry('entryId');
if ($entry->getField('author') instanceof \Atolye15\Contentful\Entry) {
// Handle linked entry
}
Rate Limiting:
Enable Debugging:
$client = new Client([
'space' => '...',
'accessToken' => '...',
'debug' => true, // Enable debug mode
]);
stderr.HTTP Client Inspection:
Client class or using middleware:
$client->getHttpClient()->getEmitter()->attach(
new \GuzzleHttp\Middleware();
);
Common Errors:
space, entryId, or assetId are correct.accessToken permissions in Contentful’s API keys section.Custom Field Types:
Atolye15\Contentful\Field class to handle custom field types or transformations.class CustomField extends \Atolye15\Contentful\Field
{
public function getFormattedValue()
{
return $this->value . ' (custom)';
}
}
Middleware:
$client->getHttpClient()->getEmitter()->attach(
function (callable $handler) {
return function ($request, $options) use ($handler) {
// Modify request or options
return $handler($request, $options);
};
}
);
Event Listeners:
entry.fetched or asset.fetched by extending the Client class and overriding methods.Testing:
ContentfulTestCase base class (if available) or mock the Client in tests:
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('getEntry')->andReturn($mockEntry);
How can I help you explore Laravel packages today?