Quick Start via Standalone App
Run composer project-create crell/planedo to generate a pre-configured Symfony 6 project with PlanedoBundle integrated. This is the fastest way to test functionality.
Manual Integration For existing Symfony 6 apps:
composer require crell/planedo-bundle
Then add to config/bundles.php:
return [
// ...
Crell\PlanedoBundle\PlanedoBundle::class => ['all' => true],
];
First Use Case
Configure feeds via YAML (see config/packages/planedo.yaml in the standalone app). Example:
planedo:
feeds:
- { url: 'https://example.com/feed.xml', title: 'Example Blog' }
Access aggregated content at /planet (default route).
Feed Management
planedo.feed_manager service to programmatically add/remove feeds at runtime.
$feedManager = $container->get('planedo.feed_manager');
$feedManager->addFeed('https://new-blog.com/feed.rss', 'New Blog');
planedo.yaml with custom logic (e.g., filtering feeds by category):
planedo:
filters:
- { key: 'category', value: 'tech' }
Content Processing
planedo.item_processed:
use Crell\PlanedoBundle\Event\ItemProcessedEvent;
$eventDispatcher->addListener(ItemProcessedEvent::class, function (ItemProcessedEvent $event) {
if ($event->getItem()->getCategory() === 'ignored') {
$event->stopPropagation();
}
});
templates/planedo/index.html.twig) or override the controller (src/Controller/PlanetController.php).Scheduling
CronBundle or Symfony\Component\Console to trigger feed updates:
php bin/console planedo:update
crontab (e.g., hourly updates):
0 * * * * cd /path/to/project && php bin/console planedo:update
API Access
use Crell\PlanedoBundle\Service\FeedAggregator;
class ApiController extends AbstractController {
public function __invoke(FeedAggregator $aggregator) {
return $this->json($aggregator->getLatestItems());
}
}
PSR-20 Dependency
composer.json includes the Git repo:
"repositories": [
{ "type": "git", "url": "https://github.com/php-fig/feed.git" }
],
"require": {
"php-fig/feed": "dev-main"
}
Feed Parsing Quirks
try {
$items = $feedManager->fetchFeed($url);
} catch (\Exception $e) {
$this->addFlash('error', 'Failed to fetch feed: ' . $e->getMessage());
}
mb_convert_encoding($content, 'UTF-8', 'auto');
Caching Issues
planedo.yaml:
planedo:
cache_lifetime: 3600 # 1 hour (in seconds)
php bin/console cache:clear
Route Conflicts
/planet route may clash with existing routes. Override in config/routes.yaml:
planedo:
resource: "@PlanedoBundle/Resources/config/routes.yaml"
prefix: "/blog-aggregator"
Log Feed Processing
Enable debug mode and check var/log/dev.log for parsing errors or skipped items.
Inspect Raw Feeds
Use the planedo:debug command to inspect fetched feeds:
php bin/console planedo:debug
Event Debugging Dump event data in listeners:
$event->getItem()->getRawData(); // Inspect original feed item
Custom Feed Types
Extend the FeedInterface to support non-RSS/Atom feeds (e.g., JSON feeds). Implement a custom FeedParser service.
Database Backend The bundle uses in-memory storage by default. Replace with Doctrine by:
FeedItem entity.FeedAggregator to persist items.Authentication for Private Feeds
Use Symfony’s HttpClient with auth headers:
$client = $this->container->get('http_client');
$response = $client->request('GET', $feedUrl, [
'auth_basic' => ['username', 'password']
]);
Testing
Mock the FeedManager in tests:
$feedManager = $this->createMock(FeedManager::class);
$feedManager->method('getItems')->willReturn([$mockItem]);
$this->container->set('planedo.feed_manager', $feedManager);
How can I help you explore Laravel packages today?