Weave 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

Slack Api Laravel Package

vluzrmos/slack-api

A Laravel wrapper for the Slack API that provides a simple facade and configuration for sending messages, managing channels and users, and working with incoming webhooks, making Slack integrations clean and idiomatic in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require vluzrmos/slack-api

On Laravel 5.5+ the service provider and Slack facade are auto-discovered. On Lumen, register manually in bootstrap/app.php:

$app->register(Vluzrmos\SlackApi\SlackApiServiceProvider::class);
class_alias(Vluzrmos\SlackApi\Facades\Slack::class, 'Slack');
$app->withFacades();

Configure Publish the config and set a token:

php artisan vendor:publish --provider="Vluzrmos\SlackApi\SlackApiServiceProvider"
SLACK_TOKEN=xoxb-your-bot-token
SLACK_DEFAULT_CHANNEL=#general

In Lumen, copy config/slack.php manually into your config/ directory and load it via $app->configure('slack').

Look here first

  • config/slack.php — this is the whole surface area: token, endpoint, default_channel.
  • Vluzrmos\SlackApi\Facades\Slack — the facade you will call.
  • Slack's own Web API method reference — the package is a thin proxy; method names are passed through verbatim, so Slack's docs are this package's docs.

First use case — notify a channel

use Vluzrmos\SlackApi\Facades\Slack;

$response = Slack::post('chat.postMessage', [
    'channel' => '#general',
    'text'    => 'Deploy to production finished ✅',
]);

if (($response['ok'] ?? false) !== true) {
    logger()->error('Slack failed', $response);
}

Create a Slack app in your workspace, add a bot user, install it, and grant at minimum chat:write (plus channels:read, users:read if you want to resolve names).

Implementation Patterns

Treat it as a transport, not an SDK. Every call is Slack::get($method, $params) or Slack::post($method, $params); the token is injected for you. That means you get full coverage of the Web API with one package, but zero type safety and zero compile-time checks.

Wrap it in your own service. Do not sprinkle Slack::post(...) throughout controllers. Create App\Services\SlackNotifier with typed methods (notifyDeploy(), notifyUserMention()), inject the Slack contract or facade into it, then bind it in a service provider. This gives you a seam for testing and a swap point if you ever move to laravel/slack-notification-channel or the official SDK.

Queued notifications. Always send from a queued job, never inline in a request:

class NotifySlackChannel implements ShouldQueue
{
    public function __construct(public array $payload) {}

    public function handle(): void
    {
        Slack::post('chat.postMessage', $this->payload);
    }
}

Slack is rate-limited; a synchronous call in a controller on a slow network will bite you.

Block Kit payloads. Build a payload array and pass it through; the package just serializes JSON:

Slack::post('chat.postMessage', [
    'channel' => $channelId,
    'text'    => 'New signup', // required fallback even with blocks
    'blocks'  => json_encode($blocks),
]);

Note that blocks frequently needs to be a JSON string on the raw API, not an array — check Slack's docs for the exact shape, since the package does not transform it.

Multiple workspaces. The package binds a single configured client. For multi-tenant Slack, instantiate the underlying class directly with a per-tenant token and cache the instance (per-tenant, per-request) rather than mutating the singleton's token via config(['slack.token' => ...]), which leaks across the container.

Testing. Mock the facade — this is the biggest reason to go through the facade rather than a raw Guzzle client:

Slack::shouldReceive('post')
    ->once()
    ->with('chat.postMessage', Mockery::on(fn ($p) => $p['channel'] === '#alerts'))
    ->andReturn(['ok' => true]);

Because the package uses Guzzle directly under the hood, Laravel's Http::fake() will not intercept it. Facade mocking is the reliable path.

Integration points worth wiring up

  • Deploy hooks: a php artisan slack:notify command called from your CI pipeline.
  • Exception handler: report uncaught exceptions to a #errors channel via a queued listener, not in the handler itself.
  • Health checks: Slack::get('api.test') as a connectivity probe in a scheduled command.

Gotchas and Tips

HTTP 200 does not mean success. Slack returns 200 OK with {"ok": false, "error": "channel_not_found"}. The package will not throw. You must inspect $response['ok'] every single call — or wrap the client in a decorator that throws on ok === false. This is the #1 source of silent failures.

Rate limits are real. Slack enforces per-method tiers and returns 429 with a Retry-After header. Implement exponential backoff in your job ($this->release(...)) or throttle per channel. A notification loop over 500 users will trip this immediately.

Resolve channel names to IDs. Passing '#general' works but is fragile (renames, private channels, name collisions). Look up the channel ID once via channels.list / conversations.list and cache it (Cache::remember('slack.channel.alerts', 3600, ...)). Use IDs in payloads.

text is required even with Block Kit. Slack renders the fallback in notifications; omit it and the message can render blank or be rejected.

Config caching. The package's config uses env(). Once you run php artisan config:cache, the values are frozen — do not touch .env after caching in production and expect a change. In Lumen, env() inside config files won't work unless you explicitly enable Dotenv.

File uploads need multipart. files.upload and the newer files.getUploadURLExternal flow require multipart/form-data. The package's JSON-oriented proxy is not the right tool — fall back to plain Guzzle or Laravel's Http client for those calls.

Pagination via cursors. For conversations.list, users.list, etc., read response_metadata.next_cursor and loop with cursor in the params. The package does not paginate for you.

Timeouts. The default Guzzle timeout may be shorter than Slack's response under load. If you see sporadic cURL error 28, bump the timeout on the client the package registers (bind your own instance in the container if needed).

Debugging. There's no request log. When something fails opaquely, dump the raw response array before any transformation, or bind a Guzzle middleware that logs request/response bodies to a dedicated Slack log channel. Log the method name too — a typo returns unknown_method and you'll waste an afternoon staring at the wrong layer.

Extension point. Because the endpoint is configurable, you can point slack.endpoint at a proxy, an Enterprise Grid internal gateway, or a local stub server for integration tests.

Keep the blast radius small. This is a 99-star, zero-dependent package — a thin wrapper, not a battle-tested client. Confine all usage to one service class so that swapping to the official slack-php/slack-php-sdk later is a one-file change rather than a grep-and-replace.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package