laravel-slack maintained by labrodev
Laravel Slack
Stateless Slack incoming-webhook client for Laravel with Block Kit message transport and webhook-URL validation. Slack incoming webhooks are self-contained bearer URLs — there is no OAuth flow, no bot token, and no app-level credential to configure. Each caller supplies its own webhook URL on every call, and the package stores nothing.
Installation
composer require labrodev/laravel-slack
Optionally publish the config file:
php artisan vendor:publish --tag=slack-config
SLACK_HTTP_TIMEOUT=10
SLACK_WEBHOOK_HOST=hooks.slack.com
SLACK_WEBHOOK_PATH_PREFIX=/services/
SLACK_WEBHOOK_HOST and SLACK_WEBHOOK_PATH_PREFIX only need overriding if Slack ever changes its incoming-webhook domain or path shape — the defaults match Slack's current URLs.
Sending a message
SlackClient::send() posts Block Kit blocks and a fallback text to the incoming-webhook URL you provide:
use Labrodev\Slack\Services\SlackClient;
use Labrodev\Slack\Exceptions\SlackRequestFailed;
use Labrodev\Slack\Exceptions\SlackWebhookRevoked;
$slackClient = new SlackClient();
$blocks = [
[
'type' => 'section',
'text' => [
'type' => 'mrkdwn',
'text' => 'A new incident was reported.',
],
],
];
try {
$slackClient->send(
webhookUrl: $webhookUrl,
blocks: $blocks,
fallbackText: 'A new incident was reported.',
);
} catch (SlackWebhookRevoked) {
// the webhook was deleted or revoked on Slack's side
} catch (SlackRequestFailed) {
// any other failed request
}
Validating a webhook URL
Use SlackWebhookUrl::validate() to check a pasted webhook URL before storing it. It checks the scheme, the host against slack.webhook_host, and the path against slack.webhook_path_prefix, without overfitting to the exact segment count — and throws a specific exception for whichever part failed:
use Labrodev\Slack\Support\SlackWebhookUrl;
use Labrodev\Slack\Exceptions\SlackWebhookUrlSchemeInvalid;
use Labrodev\Slack\Exceptions\SlackWebhookUrlHostInvalid;
use Labrodev\Slack\Exceptions\SlackWebhookUrlPathInvalid;
try {
new SlackWebhookUrl()->validate($request->input('webhook_url'));
} catch (SlackWebhookUrlSchemeInvalid|SlackWebhookUrlHostInvalid|SlackWebhookUrlPathInvalid) {
throw ValidationException::withMessages([
'webhook_url' => 'That does not look like a Slack incoming-webhook URL.',
]);
}
Detecting a revoked webhook
Catch SlackWebhookRevoked to mark a stored webhook credential as dead instead of retrying it indefinitely:
use Labrodev\Slack\Exceptions\SlackWebhookRevoked;
try {
$slackClient->send(webhookUrl: $channel->webhook_url, blocks: $blocks, fallbackText: $fallbackText);
} catch (SlackWebhookRevoked) {
$channel->update(['webhook_url' => null]);
}
Exceptions
Labrodev\Slack\Exceptions\SlackWebhookRevoked— Slack returned404or410: the webhook was deleted or revoked.Labrodev\Slack\Exceptions\SlackRequestFailed— any other failed request.Labrodev\Slack\Exceptions\SlackWebhookUrlSchemeInvalid— thrown bySlackWebhookUrl::validate()when the scheme isn'thttps.Labrodev\Slack\Exceptions\SlackWebhookUrlHostInvalid— thrown bySlackWebhookUrl::validate()when the host doesn't matchslack.webhook_host.Labrodev\Slack\Exceptions\SlackWebhookUrlPathInvalid— thrown bySlackWebhookUrl::validate()when the path doesn't start withslack.webhook_path_prefix.
All carry fixed messages only. A Slack incoming-webhook URL is the bearer secret itself, so it is never interpolated into an exception message.
Testing
composer test # pest
composer phpstan # larastan, level 7
composer pint # laravel preset
composer check # all of the above
License
MIT. See LICENSE.md.