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

Laravel Mattermost Driver Laravel Package

gnello/laravel-mattermost-driver

A Laravel notification driver for Mattermost that lets your app send notifications to Mattermost channels through incoming webhooks. Configure a webhook URL and use a simple channel class to deliver alerts, updates, and team messages.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package with Composer:

    composer require gnello/laravel-mattermost-driver
    

    Laravel’s package discovery registers the service provider and the Mattermost facade automatically on 5.5+. On older versions, add them to config/app.php.

  2. Publish the config and inspect it first — it is the single place that decides whether you get webhook mode or API mode:

    php artisan vendor:publish --tag=config
    

    Look at config/mattermost.php. You will typically set one of:

    • MATTERMOST_WEBHOOK — an incoming webhook URL (simplest, no auth, no server-side permissions).
    • MATTERMOST_URL + MATTERMOST_LOGIN / MATTERMOST_PASSWORD, or MATTERMOST_TOKEN — full API mode, which lets you target channels and users programmatically.
  3. First use case — fire a smoke test from php artisan tinker:

    use Gnello\LaravelMattermostDriver\Facades\Mattermost;
    
    Mattermost::message('Hello from Laravel 👋');
    

    If that lands in your configured channel, you have a working baseline. If it throws, the failure is almost always config: bad webhook URL, wrong server URL, or credentials rejected by the API.

  4. Then wrap it in something real: a deploy-complete ping from a DeployCommand, a TicketCreated notification, or a daily digest command. The package is a thin transport; it does not give you opinionated notifications, so pick your first integration point deliberately.

Implementation Patterns

Webhook vs API mode — choose per use case.

  • Incoming webhook is fine for CI/CD, cron digests, and “someone else’s system posts into a fixed channel.” You cannot choose the channel at runtime (it is bound to the webhook), and some server settings block username/icon overrides.
  • API mode is required when the destination channel is dynamic (per-tenant, per-project, per-environment), when you need to post as a specific user, or when you need to read back channel IDs.

Static channels, dynamic content (webhook pattern):

Mattermost::message(sprintf(
    "**Deploy #%s** → `production`\nCommit: `%s`\nBy: %s",
    $deployment->id,
    $deployment->commit,
    $deployment->user->name,
));

Dynamic channel routing (API pattern). Resolve or look up the channel ID once, cache it, then post. Channel names are not stable inputs — the driver ultimately expects an ID in API mode:

$channelId = Cache::remember("mattermost:channel:{$project->slug}", 3600, function () use ($project) {
    return Mattermost::channel($project->mattermost_channel)->getId();
});

Mattermost::channel($channelId)->message($body);

Wrap it in a small application service. Do not sprinkle Mattermost:: calls across controllers. A single MattermostNotifier class gives you one place to handle markdown escaping, retries, and channel resolution:

final class MattermostNotifier
{
    public function send(string $channelName, string $text): void
    {
        try {
            Mattermost::channel($channelName)->message($text);
        } catch (\Throwable $e) {
            Log::warning('Mattermost delivery failed', ['e' => $e->getMessage()]);
        }
    }
}

Queue the send. Mattermost (or the network between you and it) will occasionally time out. Pushing the call onto a queue keeps user-facing requests fast and isolates failures from your HTTP response path:

dispatch(new SendMattermostMessage($channel, $text))->onQueue('notifications');

Custom Notification channel. If you already use Laravel notifications, implement a MattermostChannel and map toMattermost($notifiable) to the driver call. This keeps the package at the edge and lets notifications be ShouldQueue-ed and tested with Notification::fake().

Exception and lifecycle hooks. Reporting uncaught production exceptions to a #alerts channel is a natural fit:

// AppServiceProvider::boot()
$this->app->make(ExceptionHandler::class)->reportable(function (\Throwable $e) {
    if ($e instanceof \Illuminate\Auth\AuthenticationException) return;
    rescue(fn () => (new MattermostNotifier)->send('alerts', "🔥 " . get_class($e)));
});

Debounce or rate-limit this aggressively — an error loop will hammer Mattermost.

Multi-tenant / multi-webhook. The facade is a singleton bound to one configuration. If you need several Mattermost servers or webhooks, bypass the facade and construct the underlying Gnello\Mattermost\Driver directly inside your service with per-tenant config, leaving the facade for the “default” workspace.

Gotchas and Tips

  • The facade is a singleton. The driver authenticates lazily on first use, and any per-call state (target channel, team) can leak between calls in long-running processes like Octane or queue workers. Prefer explicitly passing the channel on every call rather than relying on a previously set one, and be suspicious of “worked in tinker, failed in Horizon” symptoms.
  • config:cache will freeze your credentials. Any env() values are resolved at cache time. Rotate tokens by deploying, not by editing .env on the box, and remember php artisan config:clear when debugging locally.
  • No built-in retry or circuit breaker. The package is a thin wrapper over Guzzle; if Mattermost returns 5xx or hangs, your caller sees it. Wrap calls in a queued job with $tries/backoff, set an application-level timeout, and always catch — a chat notification should never break a deploy or a payment flow.
  • Message size limits. Mattermost rejects very long posts (server default is roughly 16 000 characters, with incoming webhooks often stricter). Truncate before sending, or attach/upload large blobs as files instead of inline text.
  • Markdown quirks. Mattermost’s markdown is close to GitHub-flavored but not identical; tables and nested lists frequently render badly. Use code fences, bold, and links, and test rendering with the actual webhook/API path — some override fields are silently ignored in webhook mode when the server disables them.
  • Self-signed / internal TLS. If your Mattermost sits behind a company CA, Guzzle will throw certificate errors. Fix it at the Guzzle level (or via HTTP_PROXY/HTTPS_PROXY env), not by disabling verification globally in the app. See the driver’s issue tracker for how it exposes Guzzle options — this is a common friction point given the package’s low maintenance activity.
  • Testing. Because Mattermost is a facade, Mattermost::shouldReceive('message')->once() works in feature tests. For anything integration-shaped (channel ID lookups, error handling), mock your own MattermostNotifier instead — that keeps tests independent of the third-party driver’s exact signature.
  • Version drift is real. The package wraps gnello/php-mattermost-driver and the two do not always move together. When you upgrade either, re-run your smoke test — method names, argument order, and the shape returned by channel/team lookups have changed across versions.
  • Log at the boundary. When posts silently fail to appear, the useful information is the HTTP status and body from the underlying Guzzle exception. Log both in your notifier wrapper; the facade’s default exception message is often just “Request failed.”
  • Don’t use it as a general-purpose HTTP client for the Mattermost API. It covers messaging and basic entities; for anything beyond that, reach for the raw API with Laravel’s Http facade — you will get better typing, testing, and timeout control.
  • Watch the license. Apache-2.0 is permissive, but if this is a hard dependency in a distributed product, keep the attribution file intact.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle