Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Teams Bundle Laravel Package

ejtj3/teams-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require ejtj3/teams-bundle
    

    Register the bundle in config/bundles.php:

    return [
        EJTJ3\TeamsBundle\EJTJ3TeamsBundle::class => ['all' => true],
    ];
    
  2. Configuration: Add your Teams webhook endpoint in config/packages/ejtj3_teams.yaml:

    ejtj3_teams:
        endpoint: 'https://your-teams-webhook-url.com'
    
  3. 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);
        }
    }
    

Implementation Patterns

Core Workflows

  1. Card Creation: Use the Card class to structure messages:

    $card = new Card('Title');
    $card->addSection('Content', 'Details here');
    $card->addFact('Key', 'Value');
    
  2. 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);
    }
    
  3. 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
        }
    }
    
  4. 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);
        }
    }
    
  5. 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');
        }
    });
    

Gotchas and Tips

Common Pitfalls

  1. Endpoint Configuration:

    • Ensure endpoint in config/packages/ejtj3_teams.yaml is correct and HTTPS.
    • Test with a dummy endpoint first to avoid production issues.
  2. Card Validation:

    • Microsoft Teams webhooks reject malformed payloads silently. Use try-catch for InvalidPayloadWebHookException:
      try {
          $this->client->send($card);
      } catch (InvalidPayloadWebHookException $e) {
          $this->logger->error('Teams card failed validation', ['error' => $e->getMessage()]);
      }
      
  3. Rate Limiting:

    • Microsoft Teams enforces rate limits (~100 requests/minute). Implement retries with exponential backoff:
      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
              }
          }
      }
      
  4. Debugging:

    • Enable debug mode in the Client to log raw payloads:
      ejtj3_teams:
          endpoint: 'https://your-endpoint'
          debug: true  # Logs payloads to Symfony's debug toolbar
      
  5. Card Complexity:

    • Avoid overly complex cards (e.g., nested sections with >50 elements). Microsoft Teams may truncate or reject them.
    • Use the Teams card validator to test cards before sending.

Extension Points

  1. 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;
        }
    }
    
  2. 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);
        }
    }
    
  3. 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');
                }
            }
        }
    }
    
  4. 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');
        }
    }
    
  5. 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)%'
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky