# Set up your local development with the PHP SDK

> Configure your local development environment to get started developing with Temporal

# Quickstart

Configure your local development environment to get started developing with Temporal.

## Install PHP

Make sure you have PHP installed.

**If you don't have PHP:** Visit the official website to [download and install](https://www.php.net/downloads.php) it.

### GRPC extension

GRPC extension is required to work with RoadRunner application server.

**If you don't have `ext-grpc` installed:** Visit the official website to
[download and install](https://docs.cloud.google.com/php/docs/reference/help/grpc) it.

> **💡 Tip:**
> GRPC Installation Tip
>
> On macOS with Apple Silicon (M1/M2/M3/M4) and PHP 8.3, `pecl install grpc` may appear to hang or install indefinitely.
> If this happens, try installing a specific version:
>
> ```bash
> pecl install channel://pecl.php.net/grpc-1.78.0RC2
> ```
>
> Note: You can find the latest versions at [pecl.php.net/package/grpc](https://pecl.php.net/package/grpc).
>

```bash
php -v
```

## Create a Project

Now that you have PHP installed, create a project to manage your dependencies and build your Temporal application.

```bash
mkdir temporal-hello-world
```

```bash
cd temporal-hello-world
```

```bash
composer init --name="myproject/quickstart" -n
```

## Add Temporal PHP SDK and Configure Autoloading

Install the Temporal SDK, then add PSR-4 autoloading to your `composer.json` so PHP can find your Workflow and Activity
classes.

Your final `composer.json` should look like this. After updating, run `composer dump-autoload` to regenerate the
autoloader.

```bash
composer require temporal/sdk
```

```json
{`{
    "name": "myproject/quickstart",
    "require": {
        "temporal/sdk": "^2.16"
    },
    "autoload": {
        "psr-4": {
            "App\\\\": "src/"
        }
    }
}`}
```

```bash
composer dump-autoload
```

## Install RoadRunner application server

Install [RoadRunner application server](https://github.com/roadrunner-server/roadrunner). It starts and manages your PHP
processes that run Temporal Workers, and connects them to the Temporal Service over gRPC.

See [RoadRunner installation instructions](https://docs.roadrunner.dev/docs/general/install) to learn about other
installation methods.

```bash
./vendor/bin/rr get
```

```bash
composer require --dev internal/dload
```

```xml
        {`<?xml version="1.0"?>
<dload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="vendor/internal/dload/dload.xsd"
       temp-dir="./runtime"
>
    <actions>
        <download software="rr" version="^2025.1.6"/>
    </actions>
</dload>
`}
```

```bash
./vendor/bin/dload
```

Create a simple configuration file named `.rr.yaml` with the following content:

```yml
  {`version: "3"

rpc: listen: tcp://127.0.0.1:6001

server: command: "php worker.php"

temporal: address: "127.0.0.1:7233"

logs: level: info `}
```

## Install Temporal CLI and start the development server

The fastest way to get a development version of the Temporal Service running on your local machine is to use
[Temporal CLI](https://docs.temporal.io/cli).

Choose your operating system to install Temporal CLI:

```bash
brew install temporal
```

```bash
sudo mv temporal /usr/local/bin
```

### DLoad package manager

Consider using DLoad to delegate all installation and updating processes to the package manager.

```xml
{`<download software="temporal" version="^1.5"/>`}
```

```xml
    {`<?xml version="1.0"?>
<dload xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="vendor/internal/dload/dload.xsd"
       temp-dir="./runtime"
>
    <actions>
        <download software="rr" version="^2025.1.6"/>
        <download software="temporal" version="^1.5"/>
    </actions>
</dload>
`}
```

## Start the development server

Once you've installed Temporal CLI and added it to your PATH, open a new Terminal window and run the following command.

This command starts a local Temporal Service. It starts the Web UI, creates the default Namespace, and uses an in-memory
database.

The Temporal Service will be available on localhost:7233. The Temporal Web UI will be available at
http://localhost:8233.

Leave the local Temporal Service running as you work through tutorials and other projects. You can stop the Temporal
Service at any time by pressing CTRL+C.

Once you have everything installed, you're ready to build apps with Temporal on your local machine.

```bash
temporal server start-dev
```

```bash
temporal server start-dev --ui-port 8080
```

## Run Hello World: Test Your Installation

Now let's verify your setup is working by creating and running a complete Temporal application with both a Workflow and
Activity.

This test will confirm that:

- The Temporal PHP SDK is properly installed
- Your local Temporal Service is running
- You can successfully create and execute Workflows and Activities
- The communication between components is functioning correctly

### 1. Create the Activity

Create an Activity file (`src/GreetingActivity.php`):

```php
<?php
declare(strict_types=1);

namespace App;

use Temporal\Activity\ActivityInterface;
use Temporal\Activity\ActivityMethod;

#[ActivityInterface]
class GreetingActivity
{
    #[ActivityMethod]
    public function greet(string $name): string
    {
        return "Hello, $name!";
    }
}
```

An Activity is a method that executes a single, well-defined action (either short or long-running), which often involves
interacting with the outside world, such as sending emails, making network requests, writing to a database, or calling
an API, which is prone to failure. If an Activity fails, Temporal automatically retries it based on your configuration.

You define Activities in PHP as classes annotated with the `Temporal\Activity\ActivityInterface` attribute.

Each method used in workflow classes should be annotated with `Temporal\Activity\ActivityMethod`.

### 2. Create the Workflow

Create a Workflow file (`src/SayHelloWorkflow.php`):

```php
<?php
declare(strict_types=1);

namespace App;

use Temporal\Activity\ActivityOptions;
use Temporal\Workflow;
use Temporal\Workflow\WorkflowInterface;
use Temporal\Workflow\WorkflowMethod;

#[WorkflowInterface]
class SayHelloWorkflow
{
    #[WorkflowMethod]
    public function sayHello(string $name)
    {
        $activity = Workflow::newActivityStub(
            GreetingActivity::class,
            ActivityOptions::new()
                ->withStartToCloseTimeout(5),
        );

        return yield $activity->greet($name);
    }
}
```

### 3. Create a Worker file

Create a Worker file (`worker.php`, under project root directory):

```php
<?php
declare(strict_types=1);

use Temporal\WorkerFactory;

ini_set('display_errors', 'stderr');
require "vendor/autoload.php";

$factory = WorkerFactory::create();

$worker = $factory->newWorker();

// Register Workflows
$worker->registerWorkflowTypes(\App\SayHelloWorkflow::class);
// Register Activities
$worker->registerActivity(\App\GreetingActivity::class);

$factory->run();
```

#### Run the Worker

Previously, we created a Worker that executes Workflow and Activity tasks.

Now, start the RoadRunner application server to run the Worker by opening up a new terminal window and running this
command:

```bash
./rr serve
```

A Worker polls a Task Queue, that you configure it to poll, looking for work to do. Once the Worker dequeues a Workflow
or Activity task from the Task Queue, it then executes the task.

Workers are a crucial part of your Temporal application as they're what actually execute the tasks defined in your
Workflows and Activities. For more information on Workers, see
[Understanding Temporal](/evaluate/understanding-temporal#workers) and a [deep dive into Workers](/workers).

### 5. Execute the Workflow

Now that your Worker is running, it's time to start a Workflow Execution.

This final step will validate that everything is working correctly with your file labeled `client.php`.

Create a separate file called `client.php`:

```php
<?php
declare(strict_types=1);

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

ini_set('display_errors', 'stderr');
require "vendor/autoload.php";

$client = new WorkflowClient(
    ServiceClient::create('localhost:7233'),
);

$workflowStub = $client->newWorkflowStub(\App\SayHelloWorkflow::class);
$result = $workflowStub->sayHello('Temporal');

echo "Result: {$result}\n";
```

While your Worker is still running, open a new terminal and run:

```bash
php client.php
```

### Verify Success

If everything is working correctly, you should see:

- Worker processing the workflow and activity
- Output: `Result: Hello, Temporal!`
- Workflow Execution details in the [Temporal Web UI](http://localhost:8233)

- [Run your first Temporal Application](https://learn.temporal.io/getting_started/php/hello_world_in_php/): Create a basic Workflow and run it with the Temporal PHP SDK

- [Take a Temporal 101 course](https://learn.temporal.io/courses/): Learn Temporal concepts and build your first application with a guided course
