diff --git a/.rr.yaml b/.rr.yaml index 186b19e..180c970 100644 --- a/.rr.yaml +++ b/.rr.yaml @@ -6,6 +6,17 @@ server: rpc: listen: tcp://127.0.0.1:6001 +grpc: + listen: "tcp://0.0.0.0:9001" + pool: + command: "php grpc-worker.php" + num_workers: ${GRPC_WORKERS:-4} + debug: ${DEBUG:-false} + reflection: ${GRPC_REFLECTION:-true} + destroy_timeout: 5s + proto: + - "protos/example.proto" + http: pool: allocate_timeout: 5s diff --git a/Dockerfile b/Dockerfile index 1fbd4b6..885b972 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,11 +42,14 @@ COPY --from=library /app/vendor /app/vendor # Copy the RoadRunner configuration file and source ADD src src/ +ADD generated generated/ +ADD protos protos/ ADD server.php . ADD .rr.yaml . ADD config.php . EXPOSE 9501 +EXPOSE 9001 # Entrypoint command to run the RoadRunner server with the specified configuration ENTRYPOINT ["rr", "serve", "-c", ".rr.yaml", "-s"] \ No newline at end of file diff --git a/README.md b/README.md index c60c60e..072f710 100644 --- a/README.md +++ b/README.md @@ -2,55 +2,132 @@ ![pipeline status](https://gitea.siteworxpro.com/siteworxpro/Php-Template/actions/workflows/tests.yml/badge.svg?branch=master&style=flat-square) +## Overview + +This is a PHP project template that provides a structured development environment using Docker Compose and Make. +It includes tools for code quality, testing, dependency management, and gRPC support. + ## Dev Environment -### Prerequisites -- Docker -- Docker Compose +This project uses Docker Compose and Make to manage the development environment. The `makefile` provides convenient +commands for common development tasks. -### migrations +## Prerequisites -create a new migration -```shell -docker run --rm -v $(PWD):/app siteworxpro/migrate:v4.18.3 create -ext sql -dir /app/db/migrations -seq create_users_table +- Docker and Docker Compose +- Make +- protoc (Protocol Buffers compiler) - for gRPC code generation + +## Quick Start + +```bash +# Install PHP dependencies +make composer-install + +# Start the development container +make start + +# Run the application server +make run ``` -```text -postgres://siteworxpro:password@localhost:5432/siteworxpro?sslmode=disable +## Available Commands + +### Container Management + +- `make start` - Start the development runtime container +- `make stop` - Stop and remove all containers +- `make restart` - Restart the development container +- `make rebuild` - Rebuild containers (use after Dockerfile changes) +- `make sh` - Open a shell in the development container +- `make ps` - Show running containers + +### Application + +- `make run` - Run the application server (RoadRunner) +- `make migrate` - Run database migrations + +### Composer & Dependencies + +- `make composer-install` - Install PHP dependencies +- `make composer-update` - Update PHP dependencies +- `make composer-require package=vendor/package` - Add a new dependency +- `make composer-require-dev package=vendor/package` - Add a new dev dependency + +### Code Quality + +- `make lint` - Run linters (phpcs and phpstan) +- `make fmt` - Format code with php-cs-fixer +- `make test` - Run the test suite (phpunit) +- `make license-check` - Check license headers in source files + +### Debugging & Coverage + +- `make enable-debug` - Enable Xdebug for debugging +- `make enable-coverage` - Enable PCOV for code coverage + +### gRPC + +- `make protoc` - Generate PHP gRPC code from `.proto` files + +### CI Workflow + +- `make ci` - Run the full CI pipeline locally (install, license check, lint, test) + +### Help + +- `make help` - Show all available commands with descriptions + +## Common Workflows + +### Starting Development + +```bash +make composer-install +make start +make run ``` -```shell -docker run --rm -v $(PWD):/app siteworxpro/migrate:v4.18.3 -database "postgres://siteworxpro:password@localhost:5432/siteworxpro?sslmode=disable" -path /app/db/migrations up +### Adding a New Package + +```bash +make composer-require package=vendor/package-name ``` -### Starting the Runtime -```shell -docker-compose up -d -``` -### Start the server -```shell -docker exec -it template-dev-runtime-1 rr serve +### Running Tests + +```bash +make test ``` -You can access the api at `http://localhost:9501/` +### Code Quality Check -### Xdebug - -xdebug needs to be built into the container before it will work -```shell - docker exec -it php-template-composer-runtime-1 bin/xdebug.sh +```bash +make lint +make fmt ``` -### Install the dependencies -```shell -docker run --rm -v $(PWD):/app siteworxpro/composer install --ignore-platform-reqs +### Debugging + +```bash +make enable-debug +make run ``` -### Running all tests -```shell -docker run --rm -v $(PWD):/app siteworxpro/composer run tests:all -``` +## Notes +- All commands run inside Docker containers, ensuring a consistent environment +- The development runtime uses RoadRunner as the application server +- Composer commands run in a separate `composer-runtime` container +- Database migrations run in a dedicated `migration-container` + +## Additional Information + +### Accessing Services + +- You can access the api at [https://localhost](https://localhost) +- Traefik dashboard is at [https://127.0.0.1/dashboard/](https://127.0.0.1/dashboard/) +- the grpc server is at [tcp://localhost:9001](tcp://localhost:9001) ## License diff --git a/composer.json b/composer.json index 2ca465d..53136ba 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,8 @@ "autoload": { "psr-4": { "Siteworxpro\\App\\": "src/", - "Siteworxpro\\Tests\\": "tests/" + "Siteworxpro\\Tests\\": "tests/", + "GRPC\\": "generated/GRPC" } }, "require": { @@ -25,7 +26,8 @@ "react/promise": "^3", "react/async": "^4", "guzzlehttp/guzzle": "^7.10", - "zircote/swagger-php": "^5.7" + "zircote/swagger-php": "^5.7", + "spiral/roadrunner-grpc": "^3.5" }, "require-dev": { "phpunit/phpunit": "^12.4", diff --git a/composer.lock b/composer.lock index eb3ac31..9d3dad5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f12aaf0dae6930c226e719a5705e3f91", + "content-hash": "977f74570c671e4d59fd70d5e732c3d2", "packages": [ { "name": "adhocore/cli", @@ -298,6 +298,65 @@ ], "time": "2025-08-10T19:31:58+00:00" }, + { + "name": "google/common-protos", + "version": "4.12.4", + "source": { + "type": "git", + "url": "https://github.com/googleapis/common-protos-php.git", + "reference": "0127156899af0df2681bd42024c60bd5360d64e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/googleapis/common-protos-php/zipball/0127156899af0df2681bd42024c60bd5360d64e3", + "reference": "0127156899af0df2681bd42024c60bd5360d64e3", + "shasum": "" + }, + "require": { + "google/protobuf": "^4.31", + "php": "^8.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6" + }, + "type": "library", + "extra": { + "component": { + "id": "common-protos", + "path": "CommonProtos", + "entry": "README.md", + "target": "googleapis/common-protos-php.git" + } + }, + "autoload": { + "psr-4": { + "Google\\Api\\": "src/Api", + "Google\\Iam\\": "src/Iam", + "Google\\Rpc\\": "src/Rpc", + "Google\\Type\\": "src/Type", + "Google\\Cloud\\": "src/Cloud", + "GPBMetadata\\Google\\Api\\": "metadata/Api", + "GPBMetadata\\Google\\Iam\\": "metadata/Iam", + "GPBMetadata\\Google\\Rpc\\": "metadata/Rpc", + "GPBMetadata\\Google\\Type\\": "metadata/Type", + "GPBMetadata\\Google\\Cloud\\": "metadata/Cloud", + "GPBMetadata\\Google\\Logging\\": "metadata/Logging" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "Google API Common Protos for PHP", + "homepage": "https://github.com/googleapis/common-protos-php", + "keywords": [ + "google" + ], + "support": { + "source": "https://github.com/googleapis/common-protos-php/tree/v4.12.4" + }, + "time": "2025-09-20T01:29:44+00:00" + }, { "name": "google/protobuf", "version": "v4.33.1", @@ -2943,6 +3002,87 @@ ], "time": "2025-11-13T17:24:29+00:00" }, + { + "name": "spiral/roadrunner-grpc", + "version": "v3.5.2", + "source": { + "type": "git", + "url": "https://github.com/roadrunner-php/grpc.git", + "reference": "916c061de160d6b2f3efc82dcffac0360d84fab8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/roadrunner-php/grpc/zipball/916c061de160d6b2f3efc82dcffac0360d84fab8", + "reference": "916c061de160d6b2f3efc82dcffac0360d84fab8", + "shasum": "" + }, + "require": { + "ext-json": "*", + "google/common-protos": "^3.1|^4.0", + "google/protobuf": "^3.7 || ^4.0", + "php": ">=8.1", + "spiral/goridge": "^4.0", + "spiral/roadrunner": "^2024.3 || ^2025.1", + "spiral/roadrunner-worker": "^3.0", + "symfony/polyfill-php83": "*" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "^1.0", + "mockery/mockery": "^1.4", + "phpunit/phpunit": "^10.0", + "spiral/code-style": "^2.2", + "spiral/dumper": "^3.3", + "vimeo/psalm": ">=5.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spiral\\RoadRunner\\GRPC\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anton Titov (wolfy-j)", + "email": "wolfy-j@spiralscout.com" + }, + { + "name": "Pavel Buchnev (butschster)", + "email": "pavel.buchnev@spiralscout.com" + }, + { + "name": "Aleksei Gagarin (roxblnfk)", + "email": "alexey.gagarin@spiralscout.com" + }, + { + "name": "Maksim Smakouz (msmakouz)", + "email": "maksim.smakouz@spiralscout.com" + }, + { + "name": "RoadRunner Community", + "homepage": "https://github.com/spiral/roadrunner/graphs/contributors" + } + ], + "description": "High-Performance GRPC server for PHP applications", + "homepage": "https://roadrunner.dev/", + "support": { + "chat": "https://discord.gg/V6EK4he", + "docs": "https://docs.roadrunner.dev", + "forum": "https://forum.roadrunner.dev/", + "issues": "https://github.com/roadrunner-server/roadrunner/issues", + "source": "https://github.com/roadrunner-php/grpc/tree/v3.5.2" + }, + "funding": [ + { + "url": "https://github.com/sponsors/roadrunner-server", + "type": "github" + } + ], + "time": "2025-05-18T13:54:33+00:00" + }, { "name": "spiral/roadrunner-http", "version": "v3.6.0", diff --git a/config.php b/config.php index 48dd820..4b00213 100644 --- a/config.php +++ b/config.php @@ -14,7 +14,6 @@ return [ */ 'server' => [ 'port' => Env::get('HTTP_PORT', 9501, 'int'), - 'dev_mode' => Env::get('DEV_MODE', false, 'bool'), ], /** diff --git a/docker-compose.yml b/docker-compose.yml index a7c1f4c..aad53f4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,12 @@ volumes: services: traefik: + labels: + - "traefik.enable=true" + - "traefik.http.routers.traefik.entrypoints=web-secure" + - "traefik.http.routers.traefik.rule=Host(`127.0.0.1`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))" + - "traefik.http.routers.traefik.tls=true" + - "traefik.http.routers.traefik.service=api@internal" image: traefik:latest container_name: traefik healthcheck: @@ -15,15 +21,18 @@ services: ports: - "80:80" - "443:443" + - "9001:9001" volumes: - "/var/run/docker.sock:/var/run/docker.sock" restart: always command: - "--providers.docker=true" + - "--api.insecure=true" - "--ping" - "--providers.docker.exposedByDefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.web-secure.address=:443" + - "--entrypoints.grpc.address=:9001" - "--accesslog=true" - "--entrypoints.web.http.redirections.entryPoint.to=web-secure" - "--entrypoints.web.http.redirections.entryPoint.scheme=https" @@ -79,6 +88,13 @@ services: - "traefik.http.services.api.loadbalancer.healthcheck.path=/healthz" - "traefik.http.services.api.loadbalancer.healthcheck.interval=5s" - "traefik.http.services.api.loadbalancer.healthcheck.timeout=60s" + - "traefik.tcp.services.api.loadbalancer.server.port=9001" + - "traefik.http.services.api.loadbalancer.server.port=9501" + - "traefik.tcp.routers.grpc.entrypoints=grpc" + - "traefik.tcp.routers.grpc.rule=HostSNI(`localhost`) || HostSNI(`127.0.0.1`)" + - "traefik.tcp.routers.grpc.tls=true" + - "traefik.tcp.routers.grpc.service=api" + container_name: dev-runtime volumes: - .:/app build: @@ -103,6 +119,7 @@ services: QUEUE_BROKER: redis PHP_IDE_CONFIG: serverName=localhost WORKERS: 1 + GRPC_WORKERS: 1 DEBUG: 1 REDIS_HOST: redis DB_HOST: postgres diff --git a/generated/GRPC/GPBMetadata/Example.php b/generated/GRPC/GPBMetadata/Example.php new file mode 100644 index 0000000..09e16d5 --- /dev/null +++ b/generated/GRPC/GPBMetadata/Example.php @@ -0,0 +1,25 @@ +internalAddGeneratedFile( + "\x0A\xE5\x01\x0A\x14protos/example.proto\x12\x0Ahelloworld\"\x1C\x0A\x0CHelloRequest\x12\x0C\x0A\x04name\x18\x01 \x01(\x09\"\x1D\x0A\x0AHelloReply\x12\x0F\x0A\x07message\x18\x01 \x01(\x092I\x0A\x07Greeter\x12>\x0A\x08SayHello\x12\x18.helloworld.HelloRequest\x1A\x16.helloworld.HelloReply\"\x00B1Z\x0Dproto/greeter\xCA\x02\x0CGRPC\\Greeter\xE2\x02\x10GRPC\\GPBMetadatab\x06proto3" + , true); + + static::$is_initialized = true; + } +} + diff --git a/generated/GRPC/Greeter/GreeterInterface.php b/generated/GRPC/Greeter/GreeterInterface.php new file mode 100644 index 0000000..ad49827 --- /dev/null +++ b/generated/GRPC/Greeter/GreeterInterface.php @@ -0,0 +1,22 @@ +helloworld.HelloReply + */ +class HelloReply extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field string message = 1; + */ + protected $message = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $message + * } + */ + public function __construct($data = NULL) { + \GRPC\GPBMetadata\Example::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field string message = 1; + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * Generated from protobuf field string message = 1; + * @param string $var + * @return $this + */ + public function setMessage($var) + { + GPBUtil::checkString($var, True); + $this->message = $var; + + return $this; + } + +} + diff --git a/generated/GRPC/Greeter/HelloRequest.php b/generated/GRPC/Greeter/HelloRequest.php new file mode 100644 index 0000000..87bd96f --- /dev/null +++ b/generated/GRPC/Greeter/HelloRequest.php @@ -0,0 +1,61 @@ +helloworld.HelloRequest + */ +class HelloRequest extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * } + */ + public function __construct($data = NULL) { + \GRPC\GPBMetadata\Example::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + +} + diff --git a/generated/README.md b/generated/README.md new file mode 100644 index 0000000..aa2bde0 --- /dev/null +++ b/generated/README.md @@ -0,0 +1,3 @@ +### Note to Developers +Only generated files are allowed in this directory. +Please do not add any other files here manually. \ No newline at end of file diff --git a/grpc-worker.php b/grpc-worker.php new file mode 100644 index 0000000..0dbc05c --- /dev/null +++ b/grpc-worker.php @@ -0,0 +1,14 @@ +start()); +} catch (\Exception $e) { + echo $e->getMessage(); + + exit(1); +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..e4d4d80 --- /dev/null +++ b/makefile @@ -0,0 +1,159 @@ +# Makefile (enhanced) +SHELL := /bin/sh +.DEFAULT_GOAL := help + +# Reusable vars +DOCKER := docker compose +COMPOSER_RUNTIME := composer-runtime +DEV_RUNTIME := dev-runtime +MIGRATION_CONTAINER := migration-container + +PROTOC_GEN_DIR := ./protoc-gen-php-grpc-2025.1.5-darwin-arm64 +PROTOC_GEN := $(PROTOC_GEN_DIR)/protoc-gen-php-grpc +PROTOC_URL := https://github.com/roadrunner-server/roadrunner/releases/download/v2025.1.5/protoc-gen-php-grpc-2025.1.5-darwin-arm64.tar.gz + +COMPOSER := $(DOCKER) exec $(COMPOSER_RUNTIME) sh -c +DEV := $(DOCKER) exec $(DEV_RUNTIME) sh -c + +# Colors +GREEN := \033[32m +YELLOW := \033[33m +RESET := \033[0m + +# Fancy emoji +SPARK := โœจ +ROCKET := ๐Ÿš€ +WARN := โš ๏ธ +MAGNIFY := ๐Ÿ” +BUG := ๐Ÿž +COMPOSE := ๐Ÿณ +TRASH := ๐Ÿงน +PROTO := ๐Ÿงฉ +CHECK := โœ… +CROSS := โŒ + +# Align width for help display +HELP_COL_WIDTH := 26 + +# Help: auto-generate from targets with "##" comments +help: ## Show this help + @echo "$(SPARK) Available commands:" + @awk -F':|##' '/^[a-zA-Z0-9._-]+:.*##/ {printf " %-$(HELP_COL_WIDTH)s - %s\n", $$1, $$3}' $(MAKEFILE_LIST) | sort + +start: ## Start the development runtime container + @printf "$(GREEN)$(ROCKET) Starting $(DEV_RUNTIME)$(RESET)\n" + $(DOCKER) up $(DEV_RUNTIME) -d --no-recreate + +sh: ## Open a shell in the development runtime container + @$(MAKE) start + $(DOCKER) exec $(DEV_RUNTIME) sh + +run: ## Run the application server in the development runtime container + @$(MAKE) start + $(DEV) "rr serve" + +stop: ## Stop and remove the development runtime container + @printf "$(YELLOW)$(WARN) Stopping all containers$(RESET)\n" + $(DOCKER) down + +restart: ## Restart dev container (stop + start) + @$(MAKE) stop + @$(MAKE) start + +rebuild: ## Rebuild containers (useful after Dockerfile changes) + @printf "$(YELLOW)$(SPARK) Rebuilding containers$(RESET)\n" + @$(MAKE) stop + @printf "$(YELLOW)$(TRASH) Deleting all Docker resources$(RESET)\n" + docker system prune --all --volumes --force + @$(MAKE) start + +ps: ## Show docker compose ps + $(DOCKER) ps + +migrate: ## Run database migrations in the migration container + $(DOCKER) up $(MIGRATION_CONTAINER) + +# Composer helpers +composer-install: ## Install PHP dependencies in the composer runtime container + @printf "$(COMPOSE) $(GREEN)Installing PHP dependencies in $(COMPOSER_RUNTIME)$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer install --no-interaction --prefer-dist --optimize-autoloader --ignore-platform-reqs" + +composer-require: ## Require a PHP package in the composer runtime container (usage: make composer-require package=vendor/package) +ifndef package + $(error package variable is required: make composer-require package=vendor/package) +endif + @printf "$(COMPOSE) $(MAGNIFY) Requiring package $(package) in $(COMPOSER_RUNTIME)$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer require $(package) --ignore-platform-reqs" + +composer-require-dev: ## Require a PHP package as dev in the composer runtime container (usage: make composer-require-dev package=vendor/package) +ifndef package + $(error package variable is required: make composer-require-dev package=vendor/package) +endif + @printf "$(COMPOSE) $(MAGNIFY) Requiring dev package $(package) in $(COMPOSER_RUNTIME)$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer require --dev $(package) --ignore-platform-reqs" + +composer-update: ## Update PHP dependencies in the composer runtime container + @printf "$(COMPOSE) $(MAGNIFY) Updating PHP dependencies$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer update --no-interaction --prefer-dist --optimize-autoloader --ignore-platform-reqs" + +enable-debug: ## Enable Xdebug in the development runtime container + @$(DOCKER) up $(DEV_RUNTIME) -d --no-recreate + @printf "$(GREEN)$(BUG) Enabling Xdebug in $(DEV_RUNTIME)$(RESET)\n" + $(DEV) "bin/xdebug.sh" + +enable-coverage: ## Enable PCOV code coverage in the composer runtime container + @printf "$(GREEN)$(MAGNIFY) Enabling PCOV in $(COMPOSER_RUNTIME)$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "bin/pcov.sh" + +protoc: ## Generate PHP gRPC code from .proto files + @printf "$(PROTO) $(GREEN)Setting up protoc-gen-php-grpc plugin$(RESET)\n" + @curl -LOs $(PROTOC_URL) + @tar -xzf protoc-gen-php-grpc-2025.1.5-darwin-arm64.tar.gz + @printf "$(PROTO) $(GREEN)Generating PHP gRPC code from .proto files$(RESET)\n" + @protoc --plugin=./protoc-gen-php-grpc-2025.1.5-darwin-arm64/protoc-gen-php-grpc \ + --php_out=./generated \ + --php-grpc_out=./generated \ + protos/example.proto + @printf "$(TRASH) $(GREEN)Cleaning up protoc-gen-php-grpc plugin files$(RESET)\n" + @rm -rf $(PROTOC_GEN_DIR) protoc-gen-php-grpc-2025.1.5-darwin-arm64.tar.gz + +license-check: ## Check license headers in source files + @printf "$(MAGNIFY) $(GREEN)Checking license headers$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer run-script tests:license || true" + +# Developer tasks +lint: ## Run linting (phpcs/phpstan) in composer runtime + @printf "$(MAGNIFY) $(GREEN)Running linters$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer run-script tests:lint || true" + $(COMPOSER) "composer run-script tests:phpstan || true" + +fmt: ## Format code (php-cs-fixer) + @printf "$(MAGNIFY) $(GREEN)Formatting code$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d --no-recreate + $(COMPOSER) "composer run-script tests:lint:fix" + +test: ## Run test suite (phpunit) + @printf "$(CHECK) $(GREEN)Running unit tests$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d + $(COMPOSER) "composer run-script tests:unit || true" + +test-coverage: ## Run test suite with coverage report + @printf "$(CHECK) $(GREEN)Running unit tests with coverage report$(RESET)\n" + @$(DOCKER) up $(COMPOSER_RUNTIME) -d + @$(MAKE) enable-coverage + $(COMPOSER) "composer run-script tests:unit:coverage || true" + +# Convenience aliases +dev: run ## Alias for start +ci: composer-install license-check lint test ## CI-like local flow +down: stop ## Alias for stop +up: start ## Alias for start + +.PONY: help start sh run stop restart rebuild ps migrate composer-install composer-require composer-require-dev composer-update enable-debug enable-coverage protoc license-check lint fmt test test-coverage dev ci down up \ No newline at end of file diff --git a/protos/example.proto b/protos/example.proto new file mode 100644 index 0000000..78ab89a --- /dev/null +++ b/protos/example.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +option go_package = "proto/greeter"; +option php_namespace = "GRPC\\Greeter"; +option php_metadata_namespace = "GRPC\\GPBMetadata"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/server.php b/server.php index dd031c6..74aabcf 100644 --- a/server.php +++ b/server.php @@ -5,10 +5,7 @@ use Siteworxpro\App\Api; require __DIR__ . '/vendor/autoload.php'; try { - // Instantiate the ExternalServer class $server = new Api(); - - // Start the server $server->startServer(); } catch (JsonException $e) { echo $e->getMessage(); diff --git a/src/Grpc.php b/src/Grpc.php new file mode 100644 index 0000000..d8c2779 --- /dev/null +++ b/src/Grpc.php @@ -0,0 +1,47 @@ + Config::get('app.dev_mode'), + ]); + + $server->registerService(GreeterInterface::class, new GreeterHandler()); + $server->serve(Worker::create()); + + return 0; + } +} diff --git a/src/GrpcHandlers/GreeterHandler.php b/src/GrpcHandlers/GreeterHandler.php new file mode 100644 index 0000000..72028d7 --- /dev/null +++ b/src/GrpcHandlers/GreeterHandler.php @@ -0,0 +1,21 @@ +setMessage('Hello ' . $in->getName()); + + return $reply; + } +}