team-reflex/discord-php
DiscordPHP is a PHP wrapper for Discord’s REST, Gateway, and Voice APIs. Build Discord bots and integrations in CLI using an event-driven approach (ReactPHP). Includes guides and class reference; community Laravel integration available via Laracord.
## Getting Started
### Minimal Setup in Laravel
1. **Install via Composer** (preferably with Laracord for Laravel integration):
```bash
composer require team-reflex/discord-php laracord/laracord
php artisan vendor:publish --provider="Laracord\LaracordServiceProvider"
config/discord.php:
'token' => env('DISCORD_BOT_TOKEN'),
'intents' => [
'GUILDS',
'GUILD_MESSAGES',
// Add other required intents (e.g., 'MESSAGE_CONTENT' for message content)
],
'cache' => env('DISCORD_CACHE_DRIVER', 'array'), // Optional: 'array', 'redis', or custom
// config/app.php
'providers' => [
Laracord\LaracordServiceProvider::class,
],
app/Listeners/DiscordReady.php):
namespace App\Listeners;
use Discord\Discord;
use Illuminate\Contracts\Events\Dispatcher;
class DiscordReady
{
public function handle(Discord $discord)
{
$discord->on('ready', function (Discord $discord) {
$discord->logger->info('Bot is ready!');
});
$discord->on('messageCreate', function ($message) {
if ($message->content === '!ping') {
$message->channel->sendMessage('Pong!');
}
});
}
}
Register the listener in EventServiceProvider:
protected $listen = [
'discord.ready' => [
\App\Listeners\DiscordReady::class,
],
];
Leverage Laravel's DI container to bind Discord instances:
// In a service provider or boot method
$this->app->singleton(Discord::class, function ($app) {
return new Discord([
'token' => config('discord.token'),
'intents' => Intents::fromArray(config('discord.intents')),
]);
});
Use case: Dependency injection for testability and modularity.
Use Laravel events to decouple Discord logic:
// Dispatch a Laravel event from Discord
$discord->on('messageCreate', function ($message) {
event(new DiscordMessageReceived($message));
});
// Handle in Laravel
class DiscordMessageReceived implements ShouldBroadcast
{
public function handle()
{
// Business logic (e.g., validate, process, or store)
}
}
Tip: Use ShouldBroadcast for real-time notifications (e.g., via Laravel Echo).
Map Discord slash commands to Laravel routes:
// In a service provider
Route::discord('greet', function (Interaction $interaction) {
return $interaction->respondWithMessage('Hello, ' . $interaction->user->username . '!');
});
Laracord integration:
// config/discord.php
'slash_commands' => [
'greet' => [
'description' => 'Greet a user',
'options' => [
['name' => 'name', 'description' => 'Name to greet', 'type' => 3, 'required' => false],
],
],
],
Use Laravel's cache drivers for DiscordPHP's experimental cache:
// config/discord.php
'cache' => [
'driver' => 'redis',
'prefix' => 'discord_',
],
Custom cache adapter (for Laravel):
use Discord\Cache\CacheInterface;
use Illuminate\Cache\CacheManager;
class LaravelCacheAdapter implements CacheInterface
{
public function __construct(protected CacheManager $cache)
{}
public function get($key): ?string
{
return $this->cache->get($key);
}
// Implement other CacheInterface methods...
}
Register in config/discord.php:
'cache' => [
'adapter' => \App\Services\LaravelCacheAdapter::class,
],
For voice support, use discord-php/voice:
composer require discord-php/voice
Laravel example:
use Discord\Voice\VoiceClient;
$voice = new VoiceClient($discord, 'channel_id');
$voice->connect();
$voice->play('path/to/audio.mp3');
Check permissions using Laravel helpers:
use Discord\Parts\Permissions\ChannelPermission;
if ($message->channel->permissionsFor($message->author)->has(ChannelPermission::SEND_MESSAGES)) {
$message->channel->sendMessage('You can send messages here!');
}
Laravel policy integration:
// app/Policies/DiscordChannelPolicy.php
public function canSendMessages(User $user, Channel $channel)
{
return $channel->permissionsFor($user)->has(ChannelPermission::SEND_MESSAGES);
}
// Dispatch to a queue
$discord->on('messageCreate', function ($message) {
dispatch(new ProcessDiscordMessage($message));
});
MESSAGE_CONTENT intent requires bot approval in the Discord Developer Portal.
Tip: Use MESSAGE_CREATE for basic events and handle content separately if needed:
$discord->on('messageCreate', function ($message) {
if ($message->mentions->contains($discord->self)) {
// Handle mentions (content is available)
}
});
use Illuminate\Support\Facades\Retry;
Retry::retry(3, function () use ($discord) {
$discord->getGuild('guild_id');
}, 100); // Retry after 100ms
ini_set('memory_limit', '-1') in your CLI script.cache() for temporary data:
$discord->on('ready', function () use ($cache) {
$cache->remember('discord_guilds', now()->addHours(1), function () {
return $discord->guilds->all();
});
});
openssl.cafile in php.ini.
Fix: Download caextract and set:
openssl.cafile=C:\path\to\caextract.crt
// Bad: Blocking call
$user = $discord->getUser('user_id')->wait();
// Good: Async with promises
$discord->getUser('user_id')->then(function ($user) {
// Handle user
});
Laravel tip: Use now() for async operations:
$promise = $discord->getUser('user_id');
$user = $promise->wait(); // Only in CLI or sync contexts
discord:run Artisan command requires a Discord instance bound to the container.
Fix: Ensure your service provider binds the instance:
$this->app->singleton(Discord::class, function ($app) {
return new Discord(config('discord'));
});
php artisan discord:run for development and deploy a CLI script for production:
# production_cli.php
<?php
require __DIR__.'/vendor/autoload.php';
$discord = app(Discord::class);
$discord->
How can I help you explore Laravel packages today?