Installation:
composer require ejtj3/teams-bundle
Register the bundle in config/bundles.php:
return [
EJTJ3\TeamsBundle\EJTJ3TeamsBundle::class => ['all' => true],
];
Configuration:
Add your Teams webhook endpoint in config/packages/ejtj3_teams.yaml:
ejtj3_teams:
endpoint: 'https://your-teams-webhook-url.com'
First Use Case:
Inject the Client service into a controller/service and send a simple card:
use EJTJ3\Teams\Client;
use EJTJ3\Teams\Card;
class NotificationController
{
public function __construct(private Client $client) {}
public function sendAlert()
{
$card = new Card('Alert!');
$this->client->send($card);
}
}
Card Creation:
Use the Card class to structure messages:
$card = new Card('Title');
$card->addSection('Content', 'Details here');
$card->addFact('Key', 'Value');
Dynamic Card Generation: Build cards dynamically in controllers/services:
public function generateReportCard(array $data)
{
$card = new Card('Report Summary');
foreach ($data as $item) {
$card->addSection($item['title'], $item['content']);
}
$this->client->send($card);
}
Webhook Handling:
Use the Webhook class to validate and process incoming messages:
use EJTJ3\Teams\Webhook;
public function handleWebhook(Request $request)
{
$webhook = new Webhook($request->getContent());
if ($webhook->isValid()) {
// Process message
}
}
Service Integration: Create a dedicated service for Teams interactions:
namespace App\Service;
use EJTJ3\Teams\Client;
use EJTJ3\Teams\Card;
class TeamsNotifier
{
public function __construct(private Client $client) {}
public function notifyUsers(string $message): void
{
$card = new Card('Notification');
$card->addSection($message);
$this->client->send($card);
}
}
Event-Driven Notifications: Trigger Teams messages from Symfony events:
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
$dispatcher->addListener(KernelEvents::REQUEST, function (RequestEvent $event) {
if ($event->isMainRequest()) {
$this->teamsNotifier->notifyUsers('New request received');
}
});
Endpoint Configuration:
endpoint in config/packages/ejtj3_teams.yaml is correct and HTTPS.Card Validation:
try-catch for InvalidPayloadWebHookException:
try {
$this->client->send($card);
} catch (InvalidPayloadWebHookException $e) {
$this->logger->error('Teams card failed validation', ['error' => $e->getMessage()]);
}
Rate Limiting:
use Symfony\Component\Stopwatch\Stopwatch;
public function sendWithRetry(Card $card, int $maxRetries = 3): void
{
$stopwatch = new Stopwatch();
$event = $stopwatch->start('teams_send');
for ($i = 0; $i < $maxRetries; $i++) {
try {
$this->client->send($card);
$event->stop();
return;
} catch (Exception $e) {
if ($i === $maxRetries - 1) throw $e;
sleep(2 ** $i); // Exponential backoff
}
}
}
Debugging:
Client to log raw payloads:
ejtj3_teams:
endpoint: 'https://your-endpoint'
debug: true # Logs payloads to Symfony's debug toolbar
Card Complexity:
Custom Card Factories: Create reusable card templates:
class AlertCardFactory
{
public static function create(string $title, string $message): Card
{
$card = new Card($title);
$card->addSection($message);
$card->setTheme('dark');
return $card;
}
}
Middleware for Webhooks: Add validation middleware for incoming webhooks:
namespace App\Middleware;
use EJTJ3\Teams\Webhook;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class TeamsWebhookValidator
{
public function handle(Request $request, HttpKernelInterface $kernel)
{
if ($request->getPathInfo() === '/teams/webhook') {
$webhook = new Webhook($request->getContent());
if (!$webhook->isValid()) {
return new Response('Invalid webhook', 400);
}
}
return $kernel->handle($request);
}
}
Event Listeners: Listen for Symfony events to trigger Teams notifications:
namespace App\EventListener;
use App\Service\TeamsNotifier;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\Common\EventSubscriber;
class EntitySaveListener implements EventSubscriber
{
public function __construct(private TeamsNotifier $notifier) {}
public function getSubscribedEvents(): array
{
return ['onFlush'];
}
public function onFlush(OnFlushEventArgs $args): void
{
$entityManager = $args->getEntityManager();
foreach ($entityManager->getUnitOfWork()->getScheduledEntityInsertions() as $entity) {
if ($entity instanceof CriticalEntity) {
$this->notifier->notifyUsers('New critical entity created');
}
}
}
}
Testing:
Mock the Client service in tests:
use EJTJ3\Teams\Client;
use PHPUnit\Framework\TestCase;
class TeamsNotifierTest extends TestCase
{
public function testNotifyUsers()
{
$mockClient = $this->createMock(Client::class);
$notifier = new TeamsNotifier($mockClient);
$mockClient->expects($this->once())
->method('send')
->with($this->isInstanceOf(Card::class));
$notifier->notifyUsers('Test message');
}
}
Environment-Specific Config: Use Symfony’s parameter bag for environment-specific endpoints:
# config/packages/dev/ejtj3_teams.yaml
ejtj3_teams:
endpoint: '%env(TEAMS_DEV_ENDPOINT)%'
How can I help you explore Laravel packages today?