A PHP library for sending messages to Discord webhooks using PSR-18.
- PSR-18 Compatible — Works with any PSR-18 HTTP client
- Synchronous — No async/await complexity
- Simple API — Easy to use webhook messaging
- Rich Embeds — Support for Discord embed messages
- Rate Limiting — Built-in rate limit header parsing
- Lightweight — Minimal dependencies
composer require four-bytes/four-discord-clientThis package automatically resolves PSR-18 clients via php-http/discovery.
<?php
use Four\Discord\WebhookClient;
// Factory method (recommended) — auto-discovers PSR-18 client
$client = WebhookClient::create('https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN');
// Send simple message
$response = $client->sendMessage(
content: 'Hello Discord!',
username: 'My Bot',
avatarUrl: 'https://example.com/avatar.png'
);
if ($response->isSuccess()) {
echo "Message sent!";
} else {
echo "Error: " . $response->getErrorMessage();
}$response = $client->sendMessage(
content: 'Your countdown has 5 minutes remaining!',
username: 'Countdown Bot', // Optional
avatarUrl: 'https://example.com/bot.png' // Optional
);$embed = [
'title' => 'Countdown Alert',
'description' => 'Important event starting soon!',
'color' => 0xff6b35,
'timestamp' => date('c'),
'fields' => [
[
'name' => 'Time Remaining',
'value' => '5 minutes',
'inline' => true
]
]
];
$response = $client->sendEmbed(
embed: $embed,
content: '@everyone Reminder!' // Optional
);$response = $client->sendMessage('Hello!');
if (!$response->isSuccess()) {
echo "Status Code: " . $response->getStatusCode() . "\n";
echo "Error: " . $response->getErrorMessage() . "\n";
// Check rate limiting
if ($response->getRateLimitRemaining() !== null) {
echo "Rate limit remaining: " . $response->getRateLimitRemaining() . "\n";
echo "Rate limit resets at: " . date('c', $response->getRateLimitReset()) . "\n";
}
}The response object provides access to Discord's rate limit headers:
$response = $client->sendMessage('Hello!');
// Get rate limit info
$remaining = $response->getRateLimitRemaining(); // Requests left
$reset = $response->getRateLimitReset(); // Unix timestamp when limit resets- Go to your Discord server settings
- Navigate to Integrations → Webhooks
- Click New Webhook
- Configure name and channel
- Copy the Webhook URL
public static function create(string $webhookUrl): selfCreate a client with auto-discovered PSR-18 client. Recommended for most use cases.
public function __construct(
string $url,
?ClientInterface $psrClient = null,
?RequestFactoryInterface $requestFactory = null,
?StreamFactoryInterface $streamFactory = null
)Create a client with dependency injection. Use this if you need to provide a specific PSR-18 implementation.
public function sendMessage(
string $content,
?string $username = null,
?string $avatarUrl = null
): WebhookResponseSend a simple text message.
public function sendEmbed(
array $embed,
?string $content = null,
?string $username = null,
?string $avatarUrl = null
): WebhookResponseSend an embed message.
public function getWebhookUrl(): stringGet the configured webhook URL.
public function isSuccess(): boolCheck if the request was successful (2xx status code).
public function getStatusCode(): intGet HTTP status code.
public function getErrorMessage(): ?stringGet error message if request failed.
public function getResponseBody(): ?stringGet raw response body.
public function getRateLimitRemaining(): ?intGet remaining rate limit count from X-RateLimit-Remaining header.
public function getRateLimitReset(): ?intGet rate limit reset timestamp from X-RateLimit-Reset header.
- PHP 8.1+
four-bytes/four-http-client ^4.0- PSR-18 HTTP client (auto-discovered via
php-http/discovery) - PSR-17 request and stream factories
MIT