<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
agencelex / notifications-microsoft-teams example snippets
use Lex\Notifications\Notification;
use Lex\Notifications\MicrosoftTeams\Channel\TeamsChannel;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\AdaptiveCard;
use Lex\Notifications\MicrosoftTeams\Message\Action\OpenUrl;
use Lex\Notifications\MicrosoftTeams\Message\Element\TextBlock;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
class HelloTeamsNotification extends Notification
{
use CanSendToTeams;
public function via(object $notifiable): array
{
return [TeamsChannel::CHANNEL];
}
public function toTeams(object $notifiable): TeamsMessage
{
return TeamsMessage::create()
->card(
AdaptiveCard::make()
->body([
TextBlock::make('Hello from TYPO3!')->weight('Bolder')->size('Large'),
TextBlock::make('Your notification system is working.')->wrap(true),
])
->actions([
OpenUrl::make('Visit site', 'https://example.com'),
])
);
}
}
// Inject NotificationDispatcherInterface via constructor
$this->notificationDispatcher->send($frontendUser, new HelloTeamsNotification());
use Lex\Notifications\Notification;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
class MyNotification extends Notification
{
use CanSendToTeams;
// Enforced by the trait — omitting this causes a fatal error
public function toTeams(object $notifiable): TeamsMessage
{
return TeamsMessage::create()->card(AdaptiveCard::make()->body([...]));
}
}
use Lex\Notifications\Domain\Model\Ability\Notifiable;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\HasRouteNotificationForTeams;
class MyFrontendUser extends AbstractEntity
{
use Notifiable;
use HasRouteNotificationForTeams;
public function routeNotificationForTeams(): string
{
return 'https://prod.webhook.office.com/webhookb2/...';
}
}
public function toTeams(object $notifiable): TeamsMessage
{
return TeamsMessage::create()
->webhookUrl('https://prod.webhook.office.com/webhookb2/...')
->card(AdaptiveCard::make()->body([...]));
}
class Department extends AbstractEntity
{
use Notifiable;
use HasRouteNotificationForTeams;
public function routeNotificationForTeams(): string
{
return $this->teamsWebhookUrl; // stored on the entity
}
}
AdaptiveCard::make()
->version('1.6') // optional, default 1.6
->body([...elements...]) // set all body elements at once
->add(TextBlock::make('More text')) // append individual elements
->actions([...actions...]) // card-level action buttons
->addAction(OpenUrl::make('...', '…')) // append individual actions
->minHeight('200px') // optional minimum card height
->verticalContentAlignment('Center') // Top | Center | Bottom
->backgroundImage('https://…/bg.png') // optional background image URL
->rtl(true) // right-to-left text
->speak('Screen reader text'); // accessibility narration
TextBlock::make('Hello, world!')
->size('Large') // Default | Small | Medium | Large | ExtraLarge
->weight('Bolder') // Default | Lighter | Bolder
->color('Accent') // Default | Dark | Light | Accent | Good | Warning | Attention
->horizontalAlignment('Center') // Left | Center | Right
->fontType('Monospace') // Default | Monospace
->isSubtle(true) // reduced emphasis
->wrap(false) // disable wrapping
->maxLines(3) // truncate after N lines
->style('heading') // default | heading | columnHeader
->spacing('Medium') // None | Small | Default | Medium | Large | ExtraLarge | Padding
->separator(true); // draw a line above this element
// Single image
Image::make('https://example.com/logo.png')
->altText('Company logo')
->size('Medium') // Auto | Stretch | Small | Medium | Large
->style('Person') // Default | Person (renders as a circle avatar)
->horizontalAlignment('Center')
->backgroundColor('#f0f0f0') // CSS colour for transparent PNGs
->width('80px') // explicit pixel width
->selectAction(OpenUrl::make('Visit', 'https://example.com'));
// Collection of images
ImageSet::make([
Image::make('https://example.com/a.png'),
Image::make('https://example.com/b.png'),
Image::make('https://example.com/c.png'),
])->size('Small');
Container::make([
TextBlock::make('Section Title')->weight('Bolder'),
TextBlock::make('Body text goes here.')->wrap(true),
FactSet::make([Fact::make('Key', 'Value')]),
])
->style('emphasis') // default | emphasis | good | attention | warning | accent
->bleed(true) // extend to cover surrounding padding
->minHeight('100px')
->verticalContentAlignment('Top') // Top | Center | Bottom
->selectAction(OpenUrl::make('Open', 'https://example.com'));
ActionSet::make([
OpenUrl::make('View in browser', 'https://example.com'),
Submit::make('Acknowledge', ['action' => 'ack']),
]);
use Lex\Notifications\MicrosoftTeams\Message\Action\OpenUrl;
OpenUrl::make('View Order', 'https://example.com/orders/123')
->style('positive') // default | positive | destructive
->iconUrl('https://example.com/icons/view.png')
->tooltip('Opens the order detail page');
use Lex\Notifications\MicrosoftTeams\Message\Action\Submit;
Submit::make('Approve', ['action' => 'approve', 'orderId' => 123])
->style('positive')
->associatedInputs('Auto'); // Auto | None
use Lex\Notifications\MicrosoftTeams\Message\Action\ShowCard;
ShowCard::make('Show Details',
AdaptiveCard::make()->body([
TextBlock::make('Here are the full details…')->wrap(true),
])
);
use Lex\Notifications\MicrosoftTeams\Message\Action\ToggleVisibility;
// Toggle by element id
ToggleVisibility::make('Toggle Details', ['detailsContainer']);
// Force a specific state
ToggleVisibility::make('Show Details', [
['elementId' => 'detailsContainer', 'isVisible' => true],
['elementId' => 'summaryContainer', 'isVisible' => false],
]);
use Lex\Notifications\Notification;
use Lex\Notifications\MicrosoftTeams\Channel\TeamsChannel;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\Action\OpenUrl;
use Lex\Notifications\MicrosoftTeams\Message\AdaptiveCard;
use Lex\Notifications\MicrosoftTeams\Message\Element\Fact;
use Lex\Notifications\MicrosoftTeams\Message\Element\FactSet;
use Lex\Notifications\MicrosoftTeams\Message\Element\TextBlock;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
class OrderPlacedNotification extends Notification
{
use CanSendToTeams;
public function __construct(private readonly Order $order) {}
public function via(object $notifiable): array
{
return [TeamsChannel::CHANNEL];
}
public function toTeams(object $notifiable): TeamsMessage
{
return TeamsMessage::create()
->card(
AdaptiveCard::make()
->body([
TextBlock::make('New Order Received')
->size('Large')
->weight('Bolder')
->color('Accent'),
TextBlock::make('Order #' . $this->order->getNumber())
->isSubtle(true)
->spacing('None'),
FactSet::make([
Fact::make('Customer', $this->order->getCustomerName()),
Fact::make('Items', (string) $this->order->getItemCount()),
Fact::make('Total', $this->order->getFormattedTotal()),
Fact::make('Payment', $this->order->getPaymentMethod()),
Fact::make('Shipping', $this->order->getShippingMethod()),
])->spacing('Medium'),
])
->actions([
OpenUrl::make('View Order', $this->order->getBackendUrl())
->style('positive'),
OpenUrl::make('View Customer', $this->order->getCustomerUrl()),
])
);
}
}
class FulfilmentChannel extends AbstractEntity
{
use Notifiable;
use HasRouteNotificationForTeams;
public function routeNotificationForTeams(): string
{
return $this->teamsWebhookUrl;
}
}
$this->notificationDispatcher->send($fulfilmentChannel, new OrderPlacedNotification($order));
use Lex\Notifications\Notification;
use Lex\Notifications\MicrosoftTeams\Channel\TeamsChannel;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\Action\OpenUrl;
use Lex\Notifications\MicrosoftTeams\Message\AdaptiveCard;
use Lex\Notifications\MicrosoftTeams\Message\Element\Fact;
use Lex\Notifications\MicrosoftTeams\Message\Element\FactSet;
use Lex\Notifications\MicrosoftTeams\Message\Element\TextBlock;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
class ServerAlertNotification extends Notification
{
use CanSendToTeams;
public function __construct(
private readonly string $serverName,
private readonly string $metric,
private readonly string $value,
private readonly string $threshold,
private readonly string $dashboardUrl,
private readonly string $webhookUrl,
) {}
public function via(object $notifiable): array
{
return [TeamsChannel::CHANNEL];
}
public function toTeams(object $notifiable): TeamsMessage
{
return TeamsMessage::create()
->webhookUrl($this->webhookUrl) // URL embedded directly — no notifiable routing needed
->card(
AdaptiveCard::make()
->body([
TextBlock::make('CRITICAL — ' . $this->serverName)
->size('Large')
->weight('Bolder')
->color('Attention'),
TextBlock::make('Threshold exceeded. Immediate attention
// Dispatch from a Scheduler task — no special notifiable needed
$this->notificationDispatcher->send(new \stdClass(), new ServerAlertNotification(
serverName: 'prod-web-01',
metric: 'CPU Usage',
value: '98%',
threshold: '85%',
dashboardUrl: 'https://grafana.internal/d/servers',
webhookUrl: 'https://prod.webhook.office.com/webhookb2/...',
));
use Lex\Notifications\Notification;
use Lex\Notifications\MicrosoftTeams\Channel\TeamsChannel;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\Action\OpenUrl;
use Lex\Notifications\MicrosoftTeams\Message\AdaptiveCard;
use Lex\Notifications\MicrosoftTeams\Message\Element\Column;
use Lex\Notifications\MicrosoftTeams\Message\Element\ColumnSet;
use Lex\Notifications\MicrosoftTeams\Message\Element\Fact;
use Lex\Notifications\MicrosoftTeams\Message\Element\FactSet;
use Lex\Notifications\MicrosoftTeams\Message\Element\Image;
use Lex\Notifications\MicrosoftTeams\Message\Element\TextBlock;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
class UserRegisteredNotification extends Notification
{
use CanSendToTeams;
public function __construct(private readonly FrontendUser $user) {}
public function via(object $notifiable): array
{
return [TeamsChannel::CHANNEL];
}
public function toTeams(object $notifiable): TeamsMessage
{
$avatarUrl = sprintf(
'https://ui-avatars.com/api/?name=%s&size=128&background=0D3880&color=fff',
urlencode($this->user->getName()),
);
return TeamsMessage::create()
->card(
AdaptiveCard::make()
->body([
TextBlock::make('New User Registered')
->size('Large')
->weight('Bolder'),
ColumnSet::make([
Column::make([
Image::make($avatarUrl)
->style('Person')
->size('Small'),
])->width('auto'),
Column::make([
TextBlock::make($this->user->getName())
->weight('Bolder'),
TextBlock::make($this->user->getEmail())
->isSubtle(true)
->spacing('None'),
])->width('stretch'),
])->spacing('Medium'),
FactSet::make([
Fact::make('Username', $this->user->getUsername()),
Fact::make('Registered', (new \DateTimeImmutable())->format('d/m/Y H:i')),
Fact::make('User group', $this->user->getUsergroup()->first()?->getTitle() ?? '—'),
]),
])
->actions([
OpenUrl::make('Edit user', $this->user->getBackendEditUrl()),
])
);
}
}
use Lex\Notifications\Notification;
use Lex\Notifications\MicrosoftTeams\Channel\TeamsChannel;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\Action\OpenUrl;
use Lex\Notifications\MicrosoftTeams\Message\Action\ToggleVisibility;
use Lex\Notifications\MicrosoftTeams\Message\AdaptiveCard;
use Lex\Notifications\MicrosoftTeams\Message\Element\Container;
use Lex\Notifications\MicrosoftTeams\Message\Element\Fact;
use Lex\Notifications\MicrosoftTeams\Message\Element\FactSet;
use Lex\Notifications\MicrosoftTeams\Message\Element\TextBlock;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
class ContentApprovalRequestNotification extends Notification
{
use CanSendToTeams;
public function __construct(
private readonly PageRecord $page,
private readonly BackendUser $submitter,
private readonly string $note,
) {}
public function via(object $notifiable): array
{
return [TeamsChannel::CHANNEL];
}
public function toTeams(object $notifiable): TeamsMessage
{
return TeamsMessage::create()
->card(
AdaptiveCard::make()
->body([
TextBlock::make('Content Approval Required')
->size('Large')
->weight('Bolder'),
FactSet::make([
Fact::make('Page', $this->page->getTitle()),
Fact::make('Submitted by', $this->submitter->getRealName()),
Fact::make('URL', $this->page->getSlug()),
])->spacing('Medium'),
Container::make([
TextBlock::make('Editorial Note')->weight('Bolder'),
TextBlock::make($this->note)->wrap(true)->isSubtle(true),
])
->id('editorialNote')
->isVisible(false)
->style('emphasis')
->spacing('Medium'),
])
->actions([
OpenUrl::make('Preview page', $this->page->getFrontendPreviewUrl()),
OpenUrl::make('Open in backend', $this->page->getBackendUrl()),
ToggleVisibility::make('Show editorial note', ['editorialNote']),
])
);
}
}
use Lex\Notifications\Notification;
use Lex\Notifications\NotificationChannel;
use Lex\Notifications\MicrosoftTeams\Channel\TeamsChannel;
use Lex\Notifications\MicrosoftTeams\Domain\Model\Ability\CanSendToTeams;
use Lex\Notifications\MicrosoftTeams\Message\AdaptiveCard;
use Lex\Notifications\MicrosoftTeams\Message\Element\TextBlock;
use Lex\Notifications\MicrosoftTeams\Message\TeamsMessage;
use TYPO3\CMS\Core\Mail\MailMessage;
class DeploymentFinishedNotification extends Notification
{
use CanSendToTeams;
public function __construct(
private readonly string $environment,
private readonly string $version,
private readonly bool $success,
) {}
public function via(object $notifiable): array
{
return [TeamsChannel::CHANNEL, NotificationChannel::CHANNEL_MAIL];
}
public function toTeams(object $notifiable): TeamsMessage
{
$status = $this->success ? 'SUCCESS' : 'FAILED';
$color = $this->success ? 'Good' : 'Attention';
return TeamsMessage::create()
->card(
AdaptiveCard::make()
->body([
TextBlock::make("Deploy {$status} — {$this->environment}")
->size('Large')
->weight('Bolder')
->color($color),
TextBlock::make("Version {$this->version} deployed to {$this->environment}.")
->wrap(true),
])
);
}
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage())
->subject("Deploy {$this->environment}: " . ($this->success ? 'SUCCESS' : 'FAILED'))
->text("Version {$this->version} was deployed to {$this->environment}.");
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.