Installation
composer require atlantic18/coral-core-bundle
Add to config/bundles.php:
Atlantic18\CoralCoreBundle\Atlantic18CoralCoreBundle::class => ['all' => true],
First Use Case: Content Aggregation
Coral excels at aggregating microservices. Start by defining a content type (e.g., Article) via YAML/JSON in config/coral/content_types/:
# config/coral/content_types/article.yml
Article:
fields:
title: { type: string }
body: { type: markdown }
Register the type in services.yaml:
coral.content_types:
article: '@Atlantic18\CoralCoreBundle\ContentType\Article'
Fetching Content
Use the ContentManager service to retrieve content:
$content = $this->get('coral.content_manager')->get('article', 1);
Define API Endpoints
Coral assumes microservices expose REST/GraphQL APIs. Configure connectors in config/coral/connectors/:
# config/coral/connectors/user_service.yml
user_service:
endpoint: 'https://api.users.example.com'
auth: { type: 'bearer', token: '%env(USER_API_TOKEN)%' }
Aggregate Data
Use the ConnectorManager to fetch remote data:
$userData = $this->get('coral.connector_manager')->call('user_service', 'GET', '/users/1');
Compose Content Merge local and remote data into a unified content type:
$content = $this->get('coral.content_composer')->compose([
'local' => $localArticle,
'remote' => $userData,
]);
Field Transformations Use field resolvers to transform data before rendering:
// src/Resolver/MarkdownResolver.php
class MarkdownResolver implements FieldResolverInterface {
public function resolve($value) {
return Markdown::parse($value);
}
}
Register in services.yaml:
coral.field_resolvers.markdown: '@App\Resolver\MarkdownResolver'
Event-Driven Workflows
Listen to content events (e.g., ContentUpdatedEvent) to trigger actions:
// src/EventListener/ContentSyncListener.php
class ContentSyncListener {
public function onContentUpdated(ContentUpdatedEvent $event) {
$this->get('coral.connector_manager')->call('sync_service', 'POST', '/sync', [
'content_id' => $event->getId(),
]);
}
}
Bind in services.yaml:
coral.event_listener.content_sync: '@App\EventListener\ContentSyncListener'
Custom Storage Backends
Extend StorageInterface to support non-database storage (e.g., S3, Dropbox):
class DropboxStorage implements StorageInterface {
public function save($content) {
// Use Dropbox SDK to upload
}
}
Configure in config/coral/storage.yml:
default: dropbox
storages:
dropbox: '@App\Storage\DropboxStorage'
Connector Timeouts
user_service:
timeout: 5 # seconds
coral:debug:connectors to inspect active connections.Content Type Caching
content_types/*.yml may not reflect immediately.php bin/console cache:clear
coral:dump:content-types to validate configurations.Field Resolver Conflicts
Event Subscriber Overrides
tags:
- { name: kernel.event_listener, event: ContentUpdatedEvent, method: onContentUpdated, priority: 255 }
Log Connector Calls
Enable debug mode in config/coral/connectors.yml:
debug: true
Logs will appear in var/log/coral.log.
Validate Content Structure
Use the coral:validate:content command to check for missing fields or invalid types.
Inspect Active Content Dump all loaded content types:
php bin/console coral:dump:content-types
Custom Content Types
Extend AbstractContentType to add business logic:
class BlogPost extends AbstractContentType {
public function isPublished() {
return $this->get('status') === 'published';
}
}
Dynamic Field Resolution
Use DynamicFieldResolver to resolve fields at runtime:
$resolver = new DynamicFieldResolver([
'author' => function($content) {
return $this->get('coral.connector_manager')->call('user_service', 'GET', '/users/' . $content['user_id']);
}
]);
Headless Mode Disable the Symfony framework entirely by configuring Coral as a standalone service:
# config/packages/coral.yaml
coral:
framework: false
storage: 'dropbox'
Useful for CLI tools or serverless functions.
Webhook Triggers Expose Coral content via webhooks for real-time updates:
// src/EventListener/WebhookListener.php
class WebhookListener {
public function onContentUpdated(ContentUpdatedEvent $event) {
$this->sendWebhook($event->getContent());
}
private function sendWebhook($content) {
// Use Guzzle or Symfony HttpClient
}
}
How can I help you explore Laravel packages today?