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 Laravel Package

ejtj3/teams

Simple PHP 7.2+ connector for sending Microsoft Teams messages via Incoming Webhooks. Build and send MessageCards with fluent syntax: add text, title, theme color, sections with facts/images, and interactive actions/inputs. Includes Symfony bundle option.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package:
    composer require ejtj3/teams
    
  2. Create a Teams Incoming Webhook:
    • Navigate to your Teams channel → Manage ChannelConnectorsIncoming Webhook.
    • Configure and copy the generated webhook URL.
  3. Send a Basic Message:
    use EJTJ3\Teams\Card;
    use EJTJ3\Teams\Client;
    
    $client = new Client('YOUR_WEBHOOK_URL');
    $card = (new Card('Hello Teams!'))
        ->setText('This is a test message from Laravel.');
    $client->send($card);
    
  4. Verify in Teams: Check your configured channel for the message.

First Use Case: CI/CD Notifications

Trigger a notification when a GitHub Actions workflow completes:

// In your Laravel job or event listener
public function handle()
{
    $client = new Client(config('teams.webhook_url'));
    $card = (new Card('Build Status'))
        ->setText('Pipeline completed with ' . $this->status)
        ->setThemeColor($this->status === 'success' ? Card::STATUS_SUCCESS : Card::STATUS_CRITICAL);

    $client->send($card);
}

Implementation Patterns

Core Workflows

1. Card Construction

Use a builder pattern for reusable card templates:

// app/Services/TeamsCardBuilder.php
class TeamsCardBuilder
{
    public static function buildAlert(string $title, string $message, string $status): Card
    {
        return (new Card($title))
            ->setText($message)
            ->setThemeColor(self::mapStatusToColor($status))
            ->addSection((new Section($message))
                ->addFact('Status', $status)
                ->addFact('Time', now()->format('Y-m-d H:i:s')));
    }

    private static function mapStatusToColor(string $status): string
    {
        return match ($status) {
            'critical' => Card::STATUS_CRITICAL,
            'warning' => Card::STATUS_WARNING,
            default => Card::STATUS_SUCCESS,
        };
    }
}

Usage:

TeamsCardBuilder::buildAlert('Server Alert', 'High CPU usage detected', 'warning');

2. Actionable Cards

For approval workflows, use ActionCard with HttpPostAction:

// app/Services/ApprovalCardBuilder.php
class ApprovalCardBuilder
{
    public static function buildApproval(string $title, string $description, string $callbackUrl): Card
    {
        $card = (new Card($title))
            ->setText($description);

        $actionCard = (new ActionCard('Approve/Reject'))
            ->addAction(new HttpPostAction('Approve', $callbackUrl . '?action=approve'))
            ->addAction(new HttpPostAction('Reject', $callbackUrl . '?action=reject'));

        $card->addPotentialAction($actionCard);
        return $card;
    }
}

Handle Callback in Laravel:

// routes/web.php
Route::post('/teams/callback', function (Request $request) {
    $action = $request->query('action');
    // Process approval/rejection logic
});

3. Dynamic Sections

Fetch data from Laravel models and populate sections:

// In a controller or service
$section = (new Section('New User Created'))
    ->setActivityTitle('User Registration')
    ->addFact('Name', $user->name)
    ->addFact('Email', $user->email)
    ->addFact('Role', $user->role);

$card->addSection($section);

Laravel-Specific Patterns

1. Service Provider Integration

Register the Client in AppServiceProvider:

// app/Providers/AppServiceProvider.php
public function register()
{
    $this->app->singleton(TeamsClient::class, function () {
        return new Client(config('teams.webhook_url'));
    });
}

Usage in Controllers:

use Illuminate\Support\Facades\App;

public function notify(TeamsClient $client)
{
    $client->send((new Card('Test'))->setText('Hello from Laravel!'));
}

2. Queueable Notifications

Avoid blocking requests by queuing webhook sends:

// app/Jobs/SendTeamsNotification.php
class SendTeamsNotification implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle(TeamsClient $client)
    {
        $client->send($this->card);
    }
}

Dispatch:

SendTeamsNotification::dispatch($card)->onQueue('teams');

3. Configuration

Define webhook URLs in config/teams.php:

return [
    'webhook_url' => env('TEAMS_WEBHOOK_URL'),
    'default_theme' => \EJTJ3\Teams\Card::STATUS_DEFAULT,
];

Access via config('teams.webhook_url').

4. Event Listeners

Trigger notifications on Laravel events (e.g., created, updated):

// app/Listeners/SendUserRegisteredNotification.php
public function handle(UserRegistered $event)
{
    $card = (new Card('New User Registered'))
        ->addSection((new Section('Details'))
            ->addFact('Name', $event->user->name)
            ->addFact('Email', $event->user->email));

    SendTeamsNotification::dispatch($card);
}

5. Testing

Mock the Client in PHPUnit:

// tests/Feature/TeamsNotificationTest.php
public function test_notification_is_sent()
{
    $mock = Mockery::mock(TeamsClient::class);
    $mock->shouldReceive('send')->once();

    $this->app->instance(TeamsClient::class, $mock);

    // Trigger event or controller
    $this->assertTrue(true); // Mock verified
}

Advanced Patterns

1. Adaptive Cards (Limited Support)

While the package doesn’t natively support adaptive cards, you can embed JSON payloads:

$client->send(json_encode([
    '@type' => 'MessageCard',
    '@context' => 'http://schema.org/extensions',
    'themeColor' => '0076D7',
    'sections' => [[
        'activityTitle' => 'Hello world!',
        'activitySubtitle' => 'Sub-title here',
        'text' => 'This is a plain-text section.',
    ]],
]));

2. Multi-Channel Notifications

Store multiple webhook URLs and route dynamically:

// app/Services/MultiTeamsClient.php
class MultiTeamsClient
{
    public function __construct(private array $webhookUrls) {}

    public function sendToAll(Card $card)
    {
        foreach ($this->webhookUrls as $url) {
            (new Client($url))->send($card);
        }
    }
}

Usage:

$client = new MultiTeamsClient(config('teams.channels'));
$client->sendToAll($card);

3. Retry Logic

Handle transient failures with retries:

// app/Services/ResilientTeamsClient.php
class ResilientTeamsClient
{
    public function sendWithRetry(Card $card, int $retries = 3): bool
    {
        $client = new Client(config('teams.webhook_url'));
        $attempts = 0;

        while ($attempts < $retries) {
            try {
                $client->send($card);
                return true;
            } catch (Exception $e) {
                $attempts++;
                if ($attempts === $retries) throw $e;
                sleep(2 ** $attempts); // Exponential backoff
            }
        }
        return false;
    }
}

Gotchas and Tips

Pitfalls

  1. Webhook URL Validation:

    • Gotcha: Teams webhooks must use HTTPS. HTTP URLs will fail silently or throw errors.
    • Fix: Ensure your Laravel app uses HTTPS (e.g., via trustedproxy middleware or reverse proxy like Nginx).
  2. Payload Size Limits:

    • Gotcha: Teams webhooks have a payload size limit (~10KB). Large cards (e.g., with images or long text) may fail.
    • Fix: Use shortened URLs for images/text and lazy-load content if needed.
  3. Character Encoding:

    • Gotcha: Special characters (e.g., emojis, non-Latin scripts) may render incorrectly.
    • Fix: Ensure your card text is UTF-8 encoded and test with diverse character sets.
  4. Rate Limiting:

    • Gotcha: Microsoft throttles webhook sends (~100 requests/minute). Rapid-fire notifications (e.g., from a loop) may be blocked.
    • Fix: Implement queueing and exponential backoff (see Retry Logic pattern).
  5. Deprecated Methods:

    • Gotcha: The package is archived (2021), so some methods
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui