PHP code example of roadrunner-php / laravel-bridge

1. Go to this page and download the library: Download roadrunner-php/laravel-bridge library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

roadrunner-php / laravel-bridge example snippets


'providers' => [
    // ... other providers
    Spiral\RoadRunnerLaravel\Queue\QueueServiceProvider::class,
],

'connections' => [
    // ... other connections
   'roadrunner' => [
      'driver' => 'roadrunner',
      'queue' => env('RR_QUEUE', 'default'),
      'retry_after' => (int) env('RR_QUEUE_RETRY_AFTER', 90),
      'after_commit' => false,
   ],
],

return [
    // ... other configuration
    'grpc' => [
        'services' => [
            \App\GRPC\EchoServiceInterface::class => \App\GRPC\EchoService::class,

            // Service with specific interceptors
            \App\GRPC\UserServiceInterface::class => [
                'service' => \App\GRPC\UserService::class,
                'interceptors' => [
                    \App\GRPC\Interceptors\ValidationInterceptor::class,
                    \App\GRPC\Interceptors\CacheInterceptor::class,
                ],
            ],
        ]
    ],
];



namespace App\GRPC\Interceptors;

use Spiral\Interceptors\Context\CallContextInterface;
use Spiral\Interceptors\HandlerInterface;
use Spiral\Interceptors\InterceptorInterface;

class LoggingInterceptor implements InterceptorInterface
{
    public function intercept(CallContextInterface $context, HandlerInterface $handler): mixed
    {
        $method = $context->getTarget()->getPath();
        \Log::info("gRPC call: {$method}");

        $response = $handler->handle($context);

        \Log::info("gRPC response: {$method}");

        return $response;
    }
}

return [
    // ... other configuration
    'grpc' => [
        'services' => [
            // Simple service configuration
            \App\GRPC\EchoServiceInterface::class => \App\GRPC\EchoService::class,

            // Service with specific interceptors
            \App\GRPC\UserServiceInterface::class => [
                'service' => \App\GRPC\UserService::class,
                'interceptors' => [
                    \App\GRPC\Interceptors\ValidationInterceptor::class,
                    \App\GRPC\Interceptors\CacheInterceptor::class,
                ],
            ],
        ],
        // Global interceptors - applied to all services
        'interceptors' => [
            \App\GRPC\Interceptors\LoggingInterceptor::class,
            \App\GRPC\Interceptors\AuthenticationInterceptor::class,
        ],
    ],
];

'interceptors' => [
    // ... other global interceptors before
    \Spiral\RoadRunnerLaravel\Common\Interceptor\AttributesInterceptor::class,
    // ... other global interceptors after
],



namespace App\GRPC\Interceptors;

use Spiral\Interceptors\Context\CallContextInterface;
use Spiral\Interceptors\HandlerInterface;
use Spiral\Interceptors\InterceptorInterface;
use Attribute;

#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
class RoleInterceptor implements InterceptorInterface
{
    public function __construct(
        private readonly string $role,
    ) {}

    public function intercept(CallContextInterface $context, HandlerInterface $handler): mixed
    {
        // Check user role
        if (!$this->checkRole($this->role)) {
            throw new \RuntimeException('Access denied');
        }

        return $handler->handle($context);
    }
}



namespace App\GRPC;

use App\GRPC\Interceptors\LoggingInterceptor;
use App\GRPC\Interceptors\AuthInterceptor;
use App\GRPC\Interceptors\RoleInterceptor;

#[LoggingInterceptor]
#[AuthInterceptor]
class UserService implements UserServiceInterface
{
    #[RoleInterceptor('admin')]
    public function DeleteUser(GRPC\ContextInterface $ctx, DeleteUserRequest $in): DeleteUserResponse
    {
        // Implementation - will use class-level + method-level interceptors
    }

    public function GetUser(GRPC\ContextInterface $ctx, GetUserRequest $in): GetUserResponse
    {
        // Implementation - will use only class-level interceptors
    }
}

return [
    // ... other configuration
    'grpc' => [
        // ... server config
        'clients' => [
            'services' => [
                [
                    'connection' => '127.0.0.1:9001', // gRPC server address
                    'interfaces' => [
                        \App\Grpc\EchoServiceInterface::class,
                    ],
                    // 'tls' => [ ... ] // Optional TLS configuration
                ],
            ],
            // 'interceptors' => [ ... ] // Optional interceptors
        ],
    ],
];

use Spiral\Grpc\Client\ServiceClientProvider;
use App\Grpc\EchoServiceInterface;
use App\Grpc\EchoRequest;

class GrpcController extends Controller
{
    public function callService(ServiceClientProvider $provider)
    {
        /** @var EchoServiceInterface $client */
        $client = $provider->get(EchoServiceInterface::class);

        $request = new EchoRequest();
        $request->setMessage('Hello from client!');

        $response = $client->Echo($request);

        return $response->getMessage();
    }
}

return [
    // ... other configuration
    'temporal' => [
        'address' => env('TEMPORAL_ADDRESS', '127.0.0.1:7233'),
        'namespace' => 'default',
        'declarations' => [
            \App\Temporal\Workflows\MyWorkflow::class,
            \App\Temporal\Activities\MyActivity::class,
        ],
    ],
];

use Psr\Log\LoggerInterface;

class YourService
{
    public function __construct(
        private LoggerInterface $logger
    ) {}

    public function doSomething()
    {
        $this->logger->info('Operation started');

        try {
            // Your logic here
            $this->logger->info('Operation completed');
        } catch (\Exception $e) {
            $this->logger->error('Operation failed', [
                'exception' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
        }
    }
}

// Get logger from container
$logger = app(LoggerInterface::class);
// Or using the alias
$logger = app('roadrunner.logger');

$logger->info('Message', ['context' => 'data']);

return [
    // ... other configuration options ...

    'workers' => [
        Mode::MODE_HTTP => HttpWorker::class,
        Mode::MODE_JOBS => QueueWorker::class,
        Mode::MODE_GRPC => GrpcWorker::class,
        Mode::MODE_TEMPORAL => TemporalWorker::class,
    ],
];

namespace App\Workers;

use Spiral\RoadRunnerLaravel\WorkerInterface;
use Spiral\RoadRunnerLaravel\WorkerOptionsInterface;

class CustomWorker implements WorkerInterface
{
    public function start(WorkerOptionsInterface $options): void
    {
        // Your worker implementation goes here
        // This method should handle requests from the RoadRunner server
    }
}

return [
    // ... other configuration options ...

    'workers' => [
        // Existing workers
        Mode::MODE_HTTP => HttpWorker::class,
        Mode::MODE_JOBS => QueueWorker::class,

        // Your custom worker for a custom or built-in plugin
        'custom_plugin' => \App\Workers\CustomWorker::class,
    ],
];

namespace App\Workers;

use Spiral\RoadRunnerLaravel\WorkerInterface;
use Spiral\RoadRunnerLaravel\WorkerOptionsInterface;
use Spiral\RoadRunner\Centrifugo\CentrifugoWorker as RRCentrifugoWorker;
use Spiral\RoadRunner\Centrifugo\CentrifugoWorkerInterface;

class CentrifugoWorker implements WorkerInterface
{
    public function start(WorkerOptionsInterface $options): void
    {
        $worker = RRCentrifugoWorker::create();

        $worker->onConnect(function (CentrifugoWorkerInterface $worker, string $client, array $request): array {
            // Handle client connection
            $app = $options->getAppContainer();

            // Your connection handling logic

            return ['status' => 200];
        });

        $worker->onSubscribe(function (CentrifugoWorkerInterface $worker, string $client, array $request): array {
            // Handle client subscription
            $app = $options->getAppContainer();

            // Your subscription handling logic

            return ['status' => 200];
        });

        $worker->onPublish(function (CentrifugoWorkerInterface $worker, string $client, array $request): array {
            // Handle client publish
            $app = $options->getAppContainer();

            // Your publish handling logic

            return ['status' => 200];
        });

        $worker->start();
    }
}

return [
    'workers' => [
        // ... other workers
        'centrifugo' => \App\Workers\CentrifugoWorker::class,
    ],
];
shell
composer 
shell
php artisan vendor:publish --provider='Spiral\RoadRunnerLaravel\ServiceProvider' --tag=config
yaml
version: '3'
rpc:
  listen: 'tcp://127.0.0.1:6001'

server:
  command: 'php vendor/bin/rr-worker start'

http:
  address: 0.0.0.0:8080
  middleware: [ "static", "headers", "gzip" ]
  pool:
    #max_jobs: 64 # feel free to change this
    supervisor:
      exec_ttl: 60s
  headers:
    response:
      X-Powered-By: "RoadRunner"
  static:
    dir: "public"
    forbid: [ ".php" ]
yaml
server:
  command: 'php vendor/bin/rr-worker start'