team-reflex/discord-php
DiscordPHP is a PHP wrapper for Discord’s REST, gateway, and voice APIs. Build Discord bots that run in CLI with ReactPHP-style async handling. Includes limited docs/class reference and community integrations like Laracord for Laravel.
## Getting Started
### Minimal Setup in Laravel
1. **Install via Composer** (preferably with `laracord/laracord` for Laravel integration):
```bash
composer require team-reflex/discord-php laracord/laracord
Register the Service Provider (if using laracord/laracord):
Add to config/app.php under providers:
Laracord\LaracordServiceProvider::class,
Configure the Bot (publish config):
php artisan vendor:publish --provider="Laracord\LaracordServiceProvider" --tag="config"
Edit .env with your bot token and intents:
DISCORD_BOT_TOKEN=your_bot_token_here
DISCORD_INTENTS=GUILDS|GUILD_MESSAGES
First Event Listener (in a Laravel command or service):
use Discord\Discord;
use Discord\Parts\Channel\Message;
use Discord\WebSockets\Event;
public function handle(Discord $discord)
{
$discord->on(Event::MESSAGE_CREATE, function (Message $message) {
if ($message->content === '!ping') {
$message->channel->sendMessage('Pong!');
}
});
$discord->run();
}
Run the Bot (via Artisan command):
php artisan discord:run
Leverage laracord/laracord to bind DiscordPHP to Laravel’s container:
// In a service provider or boot method
$this->app->singleton(Discord::class, function ($app) {
return new Discord([
'token' => config('discord.bot_token'),
'intents' => Intents::fromString(config('discord.intents')),
]);
});
Use Laravel’s event system to decouple Discord events from business logic:
// Dispatch a Laravel event when a Discord event fires
$discord->on(Event::MESSAGE_CREATE, function (Message $message) {
event(new DiscordMessageReceived($message));
});
// Handle in a Laravel listener
public function handle(DiscordMessageReceived $event)
{
if ($event->message->content === '!help') {
$event->message->channel->sendMessage('Help content...');
}
}
Wrap DiscordPHP in an Artisan command for CLI execution:
use Illuminate\Console\Command;
use Discord\Discord;
class RunDiscordBot extends Command
{
protected $signature = 'discord:run';
protected $description = 'Run the Discord bot';
public function handle(Discord $discord)
{
$discord->run();
}
}
Reuse MessageBuilder for consistent message formatting:
protected function buildHelpMessage(): MessageBuilder
{
return MessageBuilder::new()
->setContent('Available commands:')
->addEmbed((new Embed())
->setTitle('Help')
->setDescription('List of commands...')
);
}
// Usage in event handler
$message->channel->sendMessage($this->buildHelpMessage());
Cache frequent API calls using Laravel’s cache:
use Discord\Parts\User;
use Illuminate\Support\Facades\Cache;
public function getUser(string $userId): ?User
{
return Cache::remember("discord.user.{$userId}", now()->addHours(1), function () use ($userId) {
return $this->discord->getUser($userId);
});
}
For voice support, integrate discord-php/DiscordPHP-Voice:
use Discord\Voice\VoiceClient;
$voice = new VoiceClient($discord, $guild->id);
$voice->connect($channel->id);
ReactPHP integration for webhooks or wrap in a CLI command.ReactPHP directly:
$loop = React\EventLoop\Factory::create();
$server = new React\Http\Server($loop);
$server->on('request', [$this, 'handleWebhook']);
$loop->run();
MESSAGE_CONTENT for reading message content).
$discord = new Discord([
'token' => '...',
'intents' => Intents::getDefaultIntents() | Intents::MESSAGE_CONTENT,
]);
Intents::fromString() for config-based intents:
$intents = Intents::fromString(config('discord.intents'));
ini_set('memory_limit', '-1') cautiously.$discord->on(Event::MESSAGE_CREATE, function (Message $message) {
dispatch(new ProcessMessage($message))->onQueue('discord');
});
use Discord\Exceptions\RateLimitException;
try {
$message->channel->sendMessage('...');
} catch (RateLimitException $e) {
sleep($e->retryAfter);
retry();
}
throttle middleware for API routes interacting with Discord.Channel types).
$channel = $message->channel;
if ($channel->type === Channel::TYPE_GUILD_TEXT) {
// Handle text channel
}
class CustomChannel extends Channel
{
public function isVerified(): bool
{
return $this->type === Channel::TYPE_GUILD_TEXT && $this->nsfw === false;
}
}
$discord->on(Event::MESSAGE_CREATE, function (Message $message) {
ProcessMessageJob::dispatch($message);
});
Define the job:
class ProcessMessageJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle()
{
// Process message...
}
}
$discord->on('disconnect', function () {
$this->logger->error('WebSocket disconnected. Reconnecting...');
$this->discord->reconnect();
});
stderr logging for CLI:
$discord->logger = new \Monolog\Logger('discord', [
new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Logger::DEBUG),
]);
caextract from cURL and set in php.ini:
openssl.cafile=C:\path\to\caextract.crt
class HelpMessageBuilder extends MessageBuilder
{
public function __construct()
{
$this->setContent('Help Menu')
->addEmbed($this->buildHelpEmbed());
}
protected function buildHelpEmbed(): Embed
{
return (new Embed())->setDescription('...');
}
}
$mockDiscord = Mockery::mock(Discord::class);
$mockDiscord->shouldReceive
How can I help you explore Laravel packages today?