Skip to content

Conversation

@jsundai
Copy link
Contributor

@jsundai jsundai commented Aug 11, 2025

@jsundai jsundai requested a review from a team as a code owner August 11, 2025 19:32
@webchick
Copy link
Contributor

webchick commented Aug 27, 2025

Gave this a whirl this evening since I was trying really hard to procrastinate on making slides. 🤣

  1. I can access the quickstart page from the sidebar (Develop > PHP SDK > Quickstart Setup) but from the link on the "main" PHP SDK page at https://temporal-documentation-git-php-quickstart.preview.thundergun.io/develop/php/ it's a 404. (Not sure if this is an actual bug or an artifact of how the preview site works.)
Screenshot 2025-08-26 at 10 32 01 PM
  1. For the "Download RoadRunner" step, if the commands are run together, like:
composer require spiral/roadrunner-cli ./vendor/bin/rr get-binary

You get an error: "Could not parse version constraint get-binary: Invalid version string "get-binary"

Screenshot 2025-08-26 at 10 34 46 PM

Solution: Add a ; in between the two commands, or split them across two lines.

(EDIT: Oh, interesting, they ARE on two lines in the PR, but the newlines are not translating to
s on the web version.)

  1. The Quickstart's .rr.yaml code is missing indentation, which I worry is going to change the meaning of the keys.

Default .rr.yaml file:

version: '3'
rpc:
    listen: 'tcp://127.0.0.1:6001'
server:
    command: 'php app.php'
    relay: pipes
http:
    address: '0.0.0.0:8080'
    middleware:
        - gzip
        - static
    static:
        dir: public
        forbid:
            - .php
            - .htaccess
    pool:
        num_workers: 1
        supervisor:
            max_worker_memory: 100
jobs:
    pool:
        num_workers: 2
        max_worker_memory: 100
    consume: {  }
kv:
    local:
        driver: memory
        config:
            interval: 60
metrics:
    address: '127.0.0.1:2112'

Quickstart's .rr.yaml file:

version: "3"

rpc:
listen: tcp://127.0.0.1:6001

server:
command: "php -d display_errors=stderr src/worker.php"

temporal:
address: ${TEMPORAL_HOST:-localhost}:${TEMPORAL_PORT:-7233}
activities:
num_workers: 4

logs:
level: info
mode: development

Nevertheless, I copy/paste it, as instructed...

  1. Since the code sample doesn't explain what exactly I'm copy/pasting here (fair enough; it's a "quickstart" after all), I would love a link somewhere in here to https://github.com/roadrunner-server/roadrunner/blob/master/.rr.yaml which seems to explain what these options do.

  2. Would be cool to add some explanation as to what I'm doing when I copy/paste the WorkflowInterface and ActivityInterface. This is found in the "implementation" instructions but not here.

  3. When I run php worker.php I get:

PHP Fatal error:  Uncaught ReflectionException: Class "App\Workflows\SayHelloWorkflow" does not exist in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Internal/Declaration/Reader/WorkflowReader.php:81
Stack trace:
#0 /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Internal/Declaration/Reader/WorkflowReader.php(81): ReflectionClass->__construct('App\\Workflows\\S...')
#1 /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Worker/Worker.php(73): Temporal\Internal\Declaration\Reader\WorkflowReader->fromClass('App\\Workflows\\S...')
#2 /Users/webchick/helloworld-temporalphp/worker.php(12): Temporal\Worker\Worker->registerWorkflowTypes('App\\Workflows\\S...')
#3 {main}
  thrown in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Internal/Declaration/Reader/WorkflowReader.php on line 81

Fatal error: Uncaught ReflectionException: Class "App\Workflows\SayHelloWorkflow" does not exist in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Internal/Declaration/Reader/WorkflowReader.php:81
Stack trace:
#0 /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Internal/Declaration/Reader/WorkflowReader.php(81): ReflectionClass->__construct('App\\Workflows\\S...')
#1 /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Worker/Worker.php(73): Temporal\Internal\Declaration\Reader\WorkflowReader->fromClass('App\\Workflows\\S...')
#2 /Users/webchick/helloworld-temporalphp/worker.php(12): Temporal\Worker\Worker->registerWorkflowTypes('App\\Workflows\\S...')
#3 {main}
  thrown in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Internal/Declaration/Reader/WorkflowReader.php on line 81

This is getting into all sorts of Composer autloading mumbo jumbo, but essentially, two things:

a. The Activities and Workflows folders should be under an src/ directory (or something), not on the project root (as is implied by the current instructions)
b. Composer needs to be instructed to map directories under src/ to the App namespace.

According to ChatGPT, you can fix this by adding a "Step 0" in Hello World to add the following to composer.json above the "require" bits (the comma at the end means "there's something else after me"):

    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },

Then run:

composer dump-autoload -o --classmap-authoritative
  1. Ok, now php worker.php isn't throwing errors anymore, though it's also just kinda sitting there spinning and not really doing... anything. :D Maybe make a note here that this is expected, and you should run it in a new tab as well.

  2. Running php starter.php gives the following errors:

PHP Fatal error:  Uncaught TypeError: Temporal\Client\WorkflowClient::create(): Argument #1 ($serviceClient) must be of type Temporal\Client\GRPC\ServiceClientInterface, string given, called in /Users/webchick/helloworld-temporalphp/starter.php on line 10 and defined in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/WorkflowClient.php:95
Stack trace:
#0 /Users/webchick/helloworld-temporalphp/starter.php(10): Temporal\Client\WorkflowClient::create('localhost:7233')
#1 {main}
  thrown in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/WorkflowClient.php on line 95

Fatal error: Uncaught TypeError: Temporal\Client\WorkflowClient::create(): Argument #1 ($serviceClient) must be of type Temporal\Client\GRPC\ServiceClientInterface, string given, called in /Users/webchick/helloworld-temporalphp/starter.php on line 10 and defined in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/WorkflowClient.php:95
Stack trace:
#0 /Users/webchick/helloworld-temporalphp/starter.php(10): Temporal\Client\WorkflowClient::create('localhost:7233')
#1 {main}
  thrown in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/WorkflowClient.php on line 95

According to ChatGPT, here's how to fix that one:

<?php

require __DIR__ . '/vendor/autoload.php';

use Temporal\Client\WorkflowClient;
use Temporal\Client\GRPC\ServiceClient;
use Workflows\SayHelloWorkflow;

// Create the ServiceClient
$serviceClient = ServiceClient::create('localhost:7233');

// Create the WorkflowClient
$workflowClient = WorkflowClient::create($serviceClient);

// Create a workflow stub
$options = WorkflowOptions::new()->withTaskQueue('hello');
$workflow = $workflowClient->newWorkflowStub(SayHelloWorkflow::class, $options);

// Start the workflow
$result = $workflow->greet('Temporal');
echo $result . PHP_EOL;

  1. However, now I get:
PHP Fatal error:  Uncaught RuntimeException: The gRPC extension is required to use Temporal Client. in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/GRPC/BaseClient.php:72
Stack trace:
#0 /Users/webchick/helloworld-temporalphp/starter.php(10): Temporal\Client\GRPC\BaseClient::create('localhost:7233')
#1 {main}
  thrown in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/GRPC/BaseClient.php on line 72

Fatal error: Uncaught RuntimeException: The gRPC extension is required to use Temporal Client. in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/GRPC/BaseClient.php:72
Stack trace:
#0 /Users/webchick/helloworld-temporalphp/starter.php(10): Temporal\Client\GRPC\BaseClient::create('localhost:7233')
#1 {main}
  thrown in /Users/webchick/helloworld-temporalphp/vendor/temporal/sdk/src/Client/GRPC/BaseClient.php on line 72

Fixing this apparently requires installing the gRPC PECL extension, which I worry is out of reach for many PHP devs, who are beholden to whatever extensions their host provides. :\

Roadrunner seems to have their own, mentioned here: https://docs.roadrunner.dev/docs/plugins/grpc that can be installed just with Composer.

  1. Hey, speaking of Roadrunner, they also have a Quick Start :D — though it seems to use some special version of Worker vs. the "raw" SDK version so perhaps not applicable here.

Next steps here might be talking to folks in #php-sdk on Comnmunity Slack. The maintainers of the PHP SDK are in there and I'm sure would love to help get this in shape!

@webchick
Copy link
Contributor

Ok, I see. According to the README on https://github.com/temporalio/sdk-php:

The Clients component requires the grpc extension, and the Workers component requires RoadRunner.

Ok then, I guess we need another step in/around Download RoadRunner to Install the gRPC extension:

[sudo] pecl install grpc

Then update php.ini to include:

extension=grpc.so

(I assume, my computer is still churning after the first command :D)

@webchick
Copy link
Contributor

Also cross-posted this to #php-sdk to see if we can get some input from people who use PHP on a regular basis. :) https://temporalio.slack.com/archives/C01LK9FAMM0/p1756277523073449

@roxblnfk
Copy link
Contributor

Hello. Please note that we also have a money transfer repository, prepared specifically for the upcoming quick start tutorial with PHP. You can find all the necessary code in this repository.

In fact, you can install it with a single composer command composer create-project --prefer-dist -sdev temporal/money-transfer-project to get a fully ready template for a quick start with a pair of Workflow and Activity. There is only one requirement: grpc and socket extensions for PHP.


<p>Using Composer, you can install it with the following command:</p>
<CodeSnippet language="bash">
composer require spiral/roadrunner-cli
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
composer require spiral/roadrunner-cli

You don't need installing roadrunner-cli package because SDK already includes it.

Comment on lines 55 to 111
<SetupStep code={
<>

<p>See the <a href="https://github.com/roadrunner-server/roadrunner/blob/master/README.md" target="_blank">RoadRunner README file</a> for installation instructions.</p>

<p>Using Composer, you can install it with the following command:</p>
<CodeSnippet language="bash">
composer require spiral/roadrunner-cli
./vendor/bin/rr get-binary
</CodeSnippet></>
}>

## Download RoadRunner

See the RoadRunner README file for installation instructions.
When prompted, enter yes to generate a default `.rr.yaml` file.
You’ll update it later to configure the Temporal plugin.

Next, you'll configure a local Temporal Service for development.

</SetupStep>

<SetupStep code={
<>
<Tabs>
<TabItem value="macos" label="macOS" default>

<p>Install the Temporal CLI using Homebrew:</p>
<CodeSnippet language="bash">
brew install temporal
</CodeSnippet>
</TabItem>

<TabItem value="windows" label="Windows">
<p>Download the Temporal CLI archive for your architecture:</p>
<ul>
<li><a href="https://temporal.download/cli/archive/latest?platform=windows&arch=amd64">Windows amd64</a></li>
<li><a href="https://temporal.download/cli/archive/latest?platform=windows&arch=arm64">Windows arm64</a></li>
</ul>
<p>Extract it and add <code>temporal.exe</code> to your PATH.</p>
</TabItem>

<TabItem value="linux" label="Linux">
<p>Download the Temporal CLI for your architecture:</p>
<ul>
<li><a href="https://temporal.download/cli/archive/latest?platform=linux&arch=amd64">Linux amd64</a></li>
<li><a href="https://temporal.download/cli/archive/latest?platform=linux&arch=arm64">Linux arm64</a></li>
</ul>
<p>Extract the archive and move the <code>temporal</code> binary into your PATH, for example:</p>
<CodeSnippet language="bash">
sudo mv temporal /usr/local/bin
</CodeSnippet>
</TabItem>
</Tabs>

</>
}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW there is an utility that can automatically download RoadRunner and Temporal CLI binaries:

composer require --dev internal/dload
vendor/bin/dload get rr temporal

@webchick
Copy link
Contributor

webchick commented Aug 27, 2025

Thanks a lot, @roxblnfk ! I believe the "vision" here is for the instructions + code here to mimic as closely as possible the other Quickstart guides (for example, here's the one for Java) , and part of that is documenting the "vanilla" brew install temporal and temporal server start-dev across languages.

That being said, if you have any "quick start"-y solutions to the prequel to those commands (e.g. automatically installing the gRPC PECL extension alongside RoadRunner, I'm still fighting with that one :D ) that would definitely be of interest I think.

@roxblnfk
Copy link
Contributor

roxblnfk commented Aug 27, 2025

vanilla" brew install temporal and temporal server start-dev across languages.

Got it.
You can still consider downloading Temporal CLI via composer as another available option because it might be more convenient than manually downloading builds from GitHub, unpacking, and copying them into the project (speaking as a Windows user).

Unfortunately, as a Windows user, I can't help you with installing gRPC on Mac OS. I also checked if it could be done through PIE and concluded that it doesn't work on Windows.

php pie.phar install google/grpc

Unable to find an installable package google/grpc for the latest compatible version, with minimum stability stable.

@webchick
Copy link
Contributor

Shared in #php-sdk, https://github.com/shivammathur/homebrew-extensions might be a solution to solving macOS woes around the homebrew / PECL extension kerfuffle.

@jsundai
Copy link
Contributor Author

jsundai commented Sep 8, 2025

Thanks!! I ran into some of the same friction while going through it so I paused on it. Going to get back to it and aiming to make it frictionless this week.

@vercel
Copy link

vercel bot commented Oct 8, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
temporal-documentation Ready Ready Preview Comment Oct 8, 2025 1:14pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants