|
1 | | -# laravel-grpc-example |
| 1 | +# Laravel gRPC Example (Publisher ↔ Consumer) |
| 2 | + |
| 3 | +This repository demonstrates a **minimal yet production-ready gRPC integration** using **Laravel** with **RoadRunner** and **Spiral PHP gRPC**. It contains two Laravel Sail applications: |
| 4 | + |
| 5 | +- `publisher-app`: Publishes gRPC messages |
| 6 | +- `consumer-app`: Listens and processes gRPC messages |
| 7 | + |
| 8 | +Both services communicate via `gRPC` using **Protocol Buffers**. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## 🧱 Architecture |
| 13 | + |
| 14 | +``` |
| 15 | +[publisher-app] Laravel → Spiral\GRPC\Client |
| 16 | + | |
| 17 | + | gRPC over TCP (default port 50051) |
| 18 | + v |
| 19 | +[consumer-app] Laravel + RoadRunner gRPC server |
| 20 | +``` |
| 21 | + |
| 22 | +- Laravel Sail (Docker-based) |
| 23 | +- `spiral/roadrunner` for gRPC server |
| 24 | +- `namely/protoc-all` for generating PHP stubs |
| 25 | +- No PECL compilation; all `.so` files prebuilt and compressed |
| 26 | +- Protos are **local per service**, not shared |
| 27 | + |
| 28 | +--- |
| 29 | + |
| 30 | +## ⚙️ Prerequisites |
| 31 | + |
| 32 | +- PHP 8.4+ (via Sail) |
| 33 | +- Docker + Docker Compose |
| 34 | +- Composer |
| 35 | +- Laravel Sail |
| 36 | +- ✅ No need for local `grpc.so` / `protobuf.so` or PECL tools |
| 37 | + |
| 38 | +--- |
| 39 | + |
| 40 | +## 🚀 Quick Setup |
| 41 | + |
| 42 | +### 1. Clone the Repository |
| 43 | + |
| 44 | +```bash |
| 45 | +git clone https://github.com/rxcod9/laravel-grpc-example.git |
| 46 | +cd laravel-grpc-example |
| 47 | +``` |
| 48 | + |
| 49 | +### 2. Install PHP and Composer Dependencies |
| 50 | + |
| 51 | +#### Installing directly: |
| 52 | + |
| 53 | +```sh |
| 54 | +cd publisher-app && composer install |
| 55 | +cd consumer-app && composer install |
| 56 | +``` |
| 57 | + |
| 58 | +#### Or Installing Composer Dependencies through `docker`: |
| 59 | + |
| 60 | +If you do not have php8.4 in host and wants to use docker with php8.4 for installing composer. |
| 61 | +```sh |
| 62 | +cd publisher-app |
| 63 | +docker run --rm \ |
| 64 | + --pull=always \ |
| 65 | + -v "$(pwd)":/opt \ |
| 66 | + -w /opt \ |
| 67 | + laravelsail/php84-composer:latest \ |
| 68 | + bash -c "composer install" |
| 69 | + |
| 70 | +cd consumer-app |
| 71 | +docker run --rm \ |
| 72 | + --pull=always \ |
| 73 | + -v "$(pwd)":/opt \ |
| 74 | + -w /opt \ |
| 75 | + laravelsail/php84-composer:latest \ |
| 76 | + bash -c "composer install" |
| 77 | +``` |
| 78 | + |
| 79 | +### 3. Generate PHP gRPC Stubs |
| 80 | + |
| 81 | +When you add.modify .proto files, you need to generate these files |
| 82 | + |
| 83 | +#### Using `protoc` directly: |
| 84 | + |
| 85 | +```sh |
| 86 | +# For publisher-app |
| 87 | +cd publisher-app/ |
| 88 | +protoc --proto_path=./protos \ |
| 89 | + --plugin=protoc-gen-php=$(which protoc-gen-php) \ |
| 90 | + --plugin=protoc-gen-php-grpc=/usr/local/bin/protoc-gen-php-grpc \ |
| 91 | + --php_out=./app/Grpc \ |
| 92 | + --php-grpc_out=./app/Grpc \ |
| 93 | + ./protos/messages.proto |
| 94 | + |
| 95 | +# For consumer-app |
| 96 | +cd consumer-app/ |
| 97 | +protoc --proto_path=./protos \ |
| 98 | + --plugin=protoc-gen-php=$(which protoc-gen-php) \ |
| 99 | + --plugin=protoc-gen-php-grpc=/usr/local/bin/protoc-gen-php-grpc \ |
| 100 | + --php_out=./app/Grpc \ |
| 101 | + --php-grpc_out=./app/Grpc \ |
| 102 | + ./protos/messages.proto |
| 103 | +``` |
| 104 | + |
| 105 | +#### Or using Docker: |
| 106 | + |
| 107 | +```sh |
| 108 | +cd publisher-app/ |
| 109 | +docker run --rm \ |
| 110 | + -v "$PWD:/workspace" \ |
| 111 | + -w /workspace namely/protoc-all \ |
| 112 | + -f protos/messages.proto \ |
| 113 | + -l php \ |
| 114 | + -o app/Grpc |
| 115 | + |
| 116 | +cd consumer-app/ |
| 117 | +docker run --rm \ |
| 118 | + -v "$PWD:/workspace" \ |
| 119 | + -w /workspace namely/protoc-all \ |
| 120 | + -f protos/messages.proto \ |
| 121 | + -l php \ |
| 122 | + -o app/Grpc |
| 123 | +``` |
| 124 | + |
| 125 | +> This uses `namely/protoc-all` to avoid installing Protobuf toolchains locally. |
| 126 | +
|
| 127 | + |
| 128 | +### 4. Start the Applications with Sail |
| 129 | + |
| 130 | +```sh |
| 131 | +cd publisher-app |
| 132 | +./vendor/bin/sail up -d |
| 133 | +cd consumer-app |
| 134 | +./vendor/bin/sail up -d |
| 135 | +``` |
| 136 | + |
| 137 | +--- |
| 138 | + |
| 139 | +## 🐘 Prebuilt PHP Extensions |
| 140 | + |
| 141 | +The `.so` files for `grpc` and `protobuf` are: |
| 142 | + |
| 143 | +- Precompiled |
| 144 | +- Compressed into `grpc-protobuf.tar.gz` |
| 145 | +- Extracted into `/usr/lib/php/20240924` inside the Sail containers |
| 146 | +- Auto-enabled in `/etc/php/8.3/cli/conf.d/99-grpc.ini` |
| 147 | + |
| 148 | +This avoids long PECL install times and keeps builds deterministic. |
| 149 | + |
| 150 | +--- |
| 151 | + |
| 152 | +## 📦 Artisan Command: Send Message |
| 153 | + |
| 154 | +You can test the gRPC publisher: |
| 155 | + |
| 156 | +```bash |
| 157 | +cd publisher-app |
| 158 | +./vendor/bin/sail artisan grpc:publish-message notifications '{"event":"user.registered"}' |
| 159 | +``` |
| 160 | + |
| 161 | +Expected output: |
| 162 | + |
| 163 | +```json |
| 164 | +{ |
| 165 | + "success": true, |
| 166 | + "message": "Message sent to consumer via gRPC" |
| 167 | +} |
| 168 | +``` |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## 🧪 Debugging & Logs |
| 173 | + |
| 174 | +To tail consumer logs: |
| 175 | + |
| 176 | +```bash |
| 177 | +cd consumer-app |
| 178 | +./vendor/bin/sail logs -f |
| 179 | +``` |
| 180 | + |
| 181 | +Verify gRPC extension is loaded: |
| 182 | + |
| 183 | +```bash |
| 184 | +./vendor/bin/sail php -m | grep grpc |
| 185 | +./vendor/bin/sail php -m | grep protobuf |
| 186 | +``` |
| 187 | + |
| 188 | +--- |
| 189 | + |
| 190 | +## 🛑 Stopping Services |
| 191 | + |
| 192 | +```bash |
| 193 | +cd publisher-app && ./vendor/bin/sail down |
| 194 | +cd consumer-app && ./vendor/bin/sail down |
| 195 | +``` |
| 196 | + |
| 197 | +--- |
| 198 | + |
| 199 | +## 📂 Project Structure |
| 200 | + |
| 201 | +```bash |
| 202 | +laravel-grpc-example/ |
| 203 | +├── consumer-app/ # Laravel gRPC server with RoadRunner + Supervisor |
| 204 | +│ ├── app/Grpc/ # Generated gRPC stub code |
| 205 | +│ ├── protos/ # Local proto definitions |
| 206 | +│ └── start-container # Entrypoint |
| 207 | +└── publisher-app/ # Laravel gRPC client |
| 208 | + ├── app/Grpc/ # Generated gRPC stub code |
| 209 | + ├── protos/ # Local proto definitions |
| 210 | + └── grpc:publish-message command |
| 211 | +``` |
| 212 | + |
| 213 | +--- |
| 214 | + |
| 215 | +## 🌍 Environment Configuration |
| 216 | + |
| 217 | +Make sure these `.env` variables are set: |
| 218 | + |
| 219 | +**consumer-app/.env** |
| 220 | +```env |
| 221 | +GRPC_PORT=50051 |
| 222 | +``` |
| 223 | + |
| 224 | +**publisher-app/.env** |
| 225 | +```env |
| 226 | +CONSUMER_PORT=50051 |
| 227 | +``` |
| 228 | + |
| 229 | +--- |
| 230 | + |
| 231 | +## 🛠 RoadRunner gRPC Server Setup (consumer-app) |
| 232 | + |
| 233 | +1. RoadRunner runs via Supervisor |
| 234 | +2. On container start: |
| 235 | + - `bootstrap.php` is invoked |
| 236 | + - Registers `MessageService` |
| 237 | + - Logs to stdout |
| 238 | + |
| 239 | +--- |
| 240 | + |
| 241 | +## 📈 Future Improvements |
| 242 | + |
| 243 | +- Use `.proto` sync between services (e.g., via `@shared-protos` git submodule) |
| 244 | +- Add TLS support (gRPC + secure channels) |
| 245 | +- Use GitHub Actions to generate `.so` into GitHub Releases |
| 246 | +- Implement streaming/bidirectional gRPC calls |
| 247 | +- Integrate with Laravel Events/Queue workers |
| 248 | + |
| 249 | +--- |
| 250 | + |
| 251 | +## 🧠 Got Questions? |
| 252 | + |
| 253 | +Feel free to open an [issue](https://github.com/rxcod9/laravel-grpc-example/issues) or discuss ideas for enhancements. Contributions are welcome! |
| 254 | + |
| 255 | +--- |
| 256 | + |
| 257 | +## 📜 License |
| 258 | + |
| 259 | +MIT — free to use, modify, and distribute. |
0 commit comments