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

Signalbridge Laravel Sdk Laravel Package

nugsoft/signalbridge-laravel-sdk

A Laravel SDK for integrating SignalBridge into PHP applications, offering framework-friendly configuration, service provider bindings, and a clean API for connecting Laravel projects to SignalBridge services with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

The v3.0.3 release is the first change to the SDK's public surface since v3.0.0: PR #9 adds sending WhatsApp files (media), reply buttons, lists, and link buttons. In practical terms the package now covers interactive and media messages, not just plain text — so the "send one message" smoke test is still step one, but the interesting integration work is now around interactive payloads.

Note that v3.0.2 exists and its contents are not described in the release notes you have. Treat v3.0.1 → v3.0.3 as two bumps, not one: skim src/ on the diff between the tags before upgrading, and assume anything new in 3.0.2 is also new to you.

Install and publish:

composer require nugsoft/signalbridge-laravel-sdk:^3.0
php artisan vendor:publish --tag=signalbridge-config   # verify exact tag name in the README

Laravel's package auto-discovery should register the service provider and facade; if you are on an older skeleton or have discovery disabled, add them to config/app.php manually.

Where to look first, in this order:

  1. config/signalbridge.php after publishing — credentials, base URL, timeout, default sender/from. Everything else is downstream of it.
  2. The facade / entry class in vendor/nugsoft/signalbridge-laravel-sdk/src — confirm the actual method names and argument shapes for the new file/buttons/list/link-button calls. The PR added methods; the release notes do not name them, and they are not stable across majors.
  3. The README's quickstart, plus the PR #9 diff on GitHub — that diff is the only real documentation of the new payload builders until the README catches up.

The first use case to validate is still a single synchronous text send in tinker or a throwaway route: configure credentials in .env, send to your own number, confirm you get a provider-side ID back. Only then exercise the new surfaces, in this order: a media file (this is where host/URL problems surface), then a reply-button message, then a list, then a link button. Doing them one at a time separates credential problems from payload-shape problems, which look identical from the outside.

Upgrade path from v3.0.1: bump, composer update nugsoft/signalbridge-laravel-sdk --with-dependencies, re-run your existing smoke test. No config republish and no migration — but do re-read your wrapper service against the new method signatures if you plan to adopt the interactive features.

Implementation Patterns

Wrap it, don't sprinkle it. The day-to-day pattern remains a thin application service (App\Services\MessagingService) that injects the SDK client and exposes intent-named methods (sendOtp, sendOrderShipped, sendInvoiceWithPdf). This matters more now: v3.0.3 adds four new message shapes, and if those payloads are constructed inline in controllers you will be editing dozens of files the next time the vendor reshapes them. Keep the SDK's message-building objects inside the wrapper.

Model message types as value objects in your domain. With files, buttons, lists and link buttons now in play, the cleanest pattern is one small class per message kind (OrderShippedMessage, InvoiceMessage) that knows how to translate itself into the SDK's payload. Your controllers and jobs pass domain objects; the wrapper does the translation. This also gives you a single place to encode WhatsApp's structural limits (button and row counts, described below) as validation.

Media: decide upload-vs-link once, in one place. Providers of this shape typically let you either reference a publicly reachable URL or upload the file first and send an ID. Pick one strategy in the wrapper and stick to it — mixing them means two failure modes and two auth paths. If you upload, store the returned media ID against your domain record so a retry doesn't re-upload the same PDF. Generate URLs from object storage (S3/Spaces) with a TTL comfortably longer than your worst-case retry window, and never hand the provider a URL that only resolves inside your VPC.

Interactive messages are a UX decision, not a transport decision. Reply buttons, lists and link buttons are not interchangeable: reply buttons are for a handful of quick choices, lists are for longer menus, link buttons are for driving someone to a URL. Decide the shape where the business logic lives (e.g. SupportMenu::class returns a list definition), and let the wrapper turn it into whatever the SDK expects. Otherwise you will be rewriting business copy every time the payload shape shifts.

Notification channel integration. If the package ships a notification channel, prefer it over direct client calls — you get queueing, via() routing, and per-channel error handling for free. Check whether the channel supports the new message types or only text before you route media and interactive messages through it; a channel that silently drops the extra payload is worse than a direct call.

Queue by default. Sending in a request cycle ties response time to provider latency and leaves no retry story. Implement ShouldQueue on notification classes, or dispatch a job calling your wrapper. Set tries, backoff, and a failed() handler that alerts someone. This is doubly true for media sends, which involve an upload round-trip before the send.

Centralise credentials and environment switching. Keep SIGNALBRIDGE_* keys in .env, everything else in the published config. Use distinct credentials per environment and, if the config allows, an explicit enabled/sandbox flag so local and CI degrade to a log driver. A config-level kill switch is easier to reason about than if (app()->isProduction()) scattered through jobs.

Fake it in tests. Bind a fake at your wrapper boundary, or swap the underlying HTTP client (Guzzle MockHandler, or Http::fake() if the SDK is built on Laravel's HTTP client — verify which). Assert on the outbound payload, especially for the new interactive types: the JSON body is the thing you actually care about, and it is the thing the vendor is most likely to change.

Idempotency and correlation. Pass your own reference ID through where the API allows it, and store the provider's response ID alongside the domain record. For media messages, also store the media ID and the source URL/hash so support can tell "we never sent it" from "we sent the wrong file".

Pin and read diffs. Stay on ^3.0, not *. This package is on its third patch in a short window and has shipped a payload-expanding feature in a patch — skim the src/ diff of each bump; it is small enough to read in a couple of minutes.

Gotchas and Tips

Interactive payload limits are hard provider limits, not SDK limits. WhatsApp-style platforms cap reply buttons at three, list rows at ten, and constrain titles/IDs by character count. The SDK will happily serialise an over-limit payload and the provider will reject it at runtime. Validate at the value-object level so this fails in your test suite, not in production.

Media reachability is the number one failure mode. If you pass a URL, the provider fetches it from its own infrastructure: localhost, 127.0.0.1, private subnets, and signed URLs that expire mid-retry all fail. If you upload instead, watch for media IDs expiring and for per-file size and MIME-type caps. Test with the exact file types you actually send (PDF invoices, JPEG receipts), not a placeholder PNG.

Business-initiated vs customer-initiated sends. Messaging platforms enforce a 24-hour reply window and require pre-approved templates for outbound conversations to cold recipients. The SDK does not enforce this for you. If you are sending order updates, appointment reminders, or OTPs to people who haven't messaged you recently, verify template requirements with the provider before wiring the feature into a customer-facing flow — otherwise the code works perfectly and nothing is delivered.

The Guzzle 8 constraint from v3.0.1 is permissive, not prescriptive. It says "Guzzle 8 is allowed", not "required". You stay on 7 unless something else pulls 8 forward. If another package pins guzzlehttp/guzzle:^7.0, run composer why guzzlehttp/guzzle — the widened constraint buys you nothing until the tree resolves to 8, and a widened constraint is untested against your resolved version.

Do not republish config on patch upgrades. vendor:publish --force will overwrite your tuned timeouts and base URLs. Diff the package's config on minor/major bumps; ignore it for patches.

Timeouts and retries live in config, not code. Set connect and total timeouts explicitly — the default is usually "wait forever", which turns a provider outage into exhausted PHP-FPM workers. Media sends are slower than text; if your timeout was tuned for a text send, an upload-plus-send will trip it intermittently and look like a random outage.

Exceptions are not your domain exceptions. Catch the SDK's exception type at your wrapper boundary and rethrow something your app understands, or vendor namespaces leak into controllers. Log the provider's raw response body on failure — for interactive messages it typically contains the specific field that was rejected (bad button ID, oversized list row), which a generic exception message drops.

Rate limits and per-recipient throttling. Provider-side 429s are common in bulk sends. Batch with a small delay or use Bus::batch() with chunking, and cap concurrency so a fan-out doesn't self-DoS against provider limits. Media uploads count against these limits too.

Facade static calls hide injection. SignalBridge::send(...) is untestable without Facade::swap. Prefer constructor injection of the underlying client so your wrapper is mockable.

Extension points to look for. If the SDK allows binding a custom HTTP client or overriding the transport, that's your hook for tracing headers, request logging, or a test double without forking. Confirm whether the client resolves as a container singleton — if it does, decorate it in a service provider rather than editing vendor code.

Watch the changelog, including the gaps. A payload-expanding feature arriving in a patch release tells you the project does not reserve minor versions for new functionality. Read the tag comparison, not just the release notes — v3.0.2's contents are unknown from the notes you have.

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.
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
kda/filament-dynamic-navigation
bypersoft/signbox