lorenzo/pinky
Pinky is a Laravel package for managing multiple tenants with clean separation and simple configuration. It helps you identify tenants per request, switch context automatically, and keep tenant-specific resources isolated, making multi-tenant apps easier to build and maintain.
Start by installing the package via Composer: composer require lorenzo/pinky. Then publish the config using php artisan vendor:publish --tag=pinky-config. The default config (config/pinky.php) defines channels and default settings — adjust it to match your app’s delivery needs (e.g., email, Slack, in-app).
First use case: define and send a simple in-app notification:
Pinky::create('Order Shipped')
->toUser($user)
->withData(['order_id' => $order->id])
->send();
This creates and dispatches a notification using the default channel. Check Pinky::channels() in Tinker or the config to see available channels — pinky (in-app), log, mail, and slack are commonly included.
Notification classes, use Pinky::create() with named channels or build reusable Pinky\Notification subclasses for complex flows.config/pinky.php or resources/views/pinky/*.blade.php for consistent UI styling (e.g., pinky/alert.blade.php). Use ->template('alert') to apply them.Pinky::create('Security Alert')
->toUser($admin)
->sendThrough(['mail', 'slack']);
Pinky::fake() to assert notifications were sent, inspect payload, or prevent real dispatch in tests:
Pinky::fake();
// ... run action
Pinky::assertSentTo($user, fn($notification) => $notification->title === 'Alert');
OrderShipped → send notification) without cluttering domain logic.sendThrough() match exactly (e.g., 'Slack' vs 'slack') as defined in config — mismatch silently skips delivery.toUser() Fails Gracefully: Calling send() without specifying recipient (toUser(), toChannel(), etc.) results in a RuntimeException — use Pinky::fake() during testing to catch this early.resources/views/pinky/ are cached — run php artisan view:clear after editing templates.Pinky\Channels\ChannelInterface and registering them in config. For example, send SMS via Twilio by adding a sms channel config entry pointing to your custom driver.withData() accepts arrays — avoid passing Eloquent models directly (they’re serialized and may cause hydration issues). Prefer ['order_id' => $order->id].toUser(), etc.). Don’t expect a fallback like via('database').How can I help you explore Laravel packages today?