blackfire/php-sdk
Blackfire PHP SDK provides a client for programmatic profiling with Blackfire, plus integrations like PHPUnit. Includes an optional proxy to inspect profiling traffic and a pure-PHP probe fallback for environments where the Blackfire extension can’t be installed.
Install the SDK:
composer require blackfire/php-sdk
Ensure your environment has the Blackfire PHP extension installed (or use the PHP Probe fallback for unsupported setups).
First Use Case: Profiling a Laravel Route Add this to a controller or middleware:
use Blackfire\Client;
public function index()
{
$client = new Client();
$client->startScenario('My Scenario');
// Your code to profile...
$result = DB::table('users')->get();
$client->endScenario();
return response()->json($result);
}
First Use Case: PHPUnit Integration
Annotate tests with @blackfire:
use Blackfire\Tests\PhpUnit\BlackfireTestCase;
class UserTest extends BlackfireTestCase
{
public function testUserCreation()
{
$user = User::create(['name' => 'John']);
$this->assertDatabaseHas('users', ['name' => 'John']);
}
}
Run tests with:
vendor/bin/phpunit --blackfire
Verify Setup
Check the Blackfire UI for recorded profiles. If using the PHP Probe, ensure blackfire.php-probe is enabled in your php.ini or Docker config.
Middleware for HTTP Profiling:
use Blackfire\Client;
use Closure;
class BlackfireMiddleware
{
public function handle($request, Closure $next)
{
$client = new Client();
$client->startScenario('HTTP Request: ' . $request->path());
$response = $next($request);
$client->endScenario();
return $response;
}
}
Register in app/Http/Kernel.php:
protected $middleware = [
\App\Http\Middleware\BlackfireMiddleware::class,
];
Queue Job Profiling:
use Blackfire\Client;
class ProcessOrderJob implements ShouldQueue
{
public function handle()
{
$client = new Client();
$client->startScenario('ProcessOrderJob');
// Job logic...
$client->endScenario();
}
}
- name: Profile with Blackfire
run: |
composer require blackfire/php-sdk
vendor/bin/phpunit --blackfire --filter testUserCreation
use Blackfire\Client;
use Illuminate\Console\Command;
class ProfileCommand extends Command
{
protected $signature = 'blackfire:profile {command}';
protected $description = 'Profile an Artisan command';
public function handle()
{
$client = new Client();
$client->startScenario('Artisan: ' . $this->argument('command'));
$this->call($this->argument('command'));
$client->endScenario();
}
}
Laravel Octane:
Use the BlackfiredHttpClient for async profiling:
use Blackfire\Client;
use Illuminate\Support\Facades\Http;
$client = new Client();
$blackfiredHttp = $client->getHttpClient();
$response = $blackfiredHttp->get('https://api.example.com/data');
Symfony Runtime: Leverage the built-in subscriber (no extra config needed in v3.0.0).
Custom Annotations:
Extend BlackfireTestCase for project-specific annotations:
use Blackfire\Tests\PhpUnit\BlackfireTestCase;
class PerformanceTestCase extends BlackfireTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->blackfire()->setScenario('Performance Regression Test');
}
}
Data Providers:
public function testMultipleQueries()
{
$this->blackfire()->startScenario('Database Queries');
$this->assertDatabaseHas('users', ['name' => 'Alice']);
$this->assertDatabaseHas('users', ['name' => 'Bob']);
$this->blackfire()->endScenario();
}
Service Provider Binding:
Bind the Blackfire\Client in AppServiceProvider for dependency injection:
public function register()
{
$this->app->singleton(Client::class, function () {
return new Client();
});
}
Event-Based Profiling:
Profile specific events (e.g., illuminate.query):
use Blackfire\Client;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Events;
Events::listen('illuminate.query', function ($query) {
$client = app(Client::class);
$client->startScenario('Slow Query: ' . $query->sql);
DB::connection()->getPdo()->exec($query->sql);
$client->endScenario();
});
Conditional Profiling: Profile only in specific environments (e.g., staging):
if (app()->environment('staging')) {
$client->startScenario('Staging Profiling');
// Code...
$client->endScenario();
}
Profile Groups: Use scenarios to group related profiles (e.g., "Checkout Flow"):
$client->startScenario('Checkout Flow');
$client->addJobInScenario('Add to Cart');
$client->addJobInScenario('Checkout');
$client->endScenario();
Custom Metrics: Add custom context to profiles:
$client->setAttribute('user_id', auth()->id());
$client->setAttribute('request_id', $request->header('X-Request-ID'));
Deprecated API in v2.x:
Client::createBuild) will fail in v3.0.0.// Old (v2.x)
$client->createBuild('My Build');
// New (v3.0.0)
$client->startScenario('My Scenario');
PHP Probe Limitations:
Scenario Naming Collisions:
$client->startScenario('User ' . auth()->id() . ' - Checkout');
HTTP Client Quirks:
BlackfiredHttpClient may not work with relative URLs or custom hosts.$client = $blackfireClient->getHttpClient(['base_uri' => 'https://api.example.com']);
CI/CD Profiling Failures:
services:
blackfire-agent:
image: blackfire/blackfire-agent
ports:
- "8307:8307"
PHPUnit Integration Edge Cases:
@blackfire annotations may not work with custom test suites or parallel testing.$this->blackfire()->startScenario('Custom Test');
// Test logic...
$this->blackfire()->endScenario();
Profile Not Uploading:
blackfire-agent --version).BLACKFIRE_CLIENT_ID and BLACKFIRE_CLIENT_TOKEN environment variables are set.$client = new Client(['debug' => true]);
High Overhead:
How can I help you explore Laravel packages today?