Skip to content

Commit cdb1724

Browse files
authored
Merge pull request #4952 from marcduiker/remove-php-submodule
Move PHP SDK docs into main Docs & remove PHP SDK submodule
2 parents 6ddc281 + 5be2de9 commit cdb1724

File tree

12 files changed

+1113
-5
lines changed

12 files changed

+1113
-5
lines changed

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
[submodule "sdkdocs/php"]
2-
path = sdkdocs/php
3-
url = https://github.com/dapr/php-sdk.git
41
[submodule "translations/docs-zh"]
52
path = translations/docs-zh
63
url = https://github.com/dapr/docs-zh.git

hugo.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ module:
281281
- source: sdkdocs/python/content/en/python-sdk-contributing
282282
target: content/contributing/sdk-contrib/
283283
lang: en
284-
- source: sdkdocs/php/daprdocs/content/en/php-sdk-docs
284+
- source: sdkdocs/php/content/en/php-sdk-docs
285285
target: content/developing-applications/sdks/php
286286
lang: en
287287
- source: sdkdocs/dotnet/content/en/dotnet-sdk-docs

sdkdocs/php

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
type: docs
3+
title: "Dapr PHP SDK"
4+
linkTitle: "PHP"
5+
weight: 1000
6+
description: PHP SDK packages for developing Dapr applications
7+
no_list: true
8+
cascade:
9+
github_repo: https://github.com/dapr/php-sdk
10+
github_subdir: daprdocs/content/en/php-sdk-docs
11+
path_base_for_github_subdir: content/en/developing-applications/sdks/php/
12+
github_branch: main
13+
---
14+
15+
Dapr offers an SDK to help with the development of PHP applications. Using it, you can create PHP clients, servers, and virtual actors with Dapr.
16+
17+
## Setting up
18+
19+
### Prerequisites
20+
21+
- [Composer](https://getcomposer.org/)
22+
- [PHP 8](https://www.php.net/)
23+
24+
### Optional Prerequisites
25+
26+
- [Docker](https://www.docker.com/)
27+
- [xdebug](http://xdebug.org/) -- for debugging
28+
29+
## Initialize your project
30+
31+
In a directory where you want to create your service, run `composer init` and answer the questions.
32+
Install with `composer require dapr/php-sdk` and any other dependencies you may wish to use.
33+
34+
## Configure your service
35+
36+
Create a config.php, copying the contents below:
37+
38+
```php
39+
<?php
40+
41+
use Dapr\Actors\Generators\ProxyFactory;
42+
use Dapr\Middleware\Defaults\{Response\ApplicationJson,Tracing};
43+
use Psr\Log\LogLevel;
44+
use function DI\{env,get};
45+
46+
return [
47+
// set the log level
48+
'dapr.log.level' => LogLevel::WARNING,
49+
50+
// Generate a new proxy on each request - recommended for development
51+
'dapr.actors.proxy.generation' => ProxyFactory::GENERATED,
52+
53+
// put any subscriptions here
54+
'dapr.subscriptions' => [],
55+
56+
// if this service will be hosting any actors, add them here
57+
'dapr.actors' => [],
58+
59+
// if this service will be hosting any actors, configure how long until dapr should consider an actor idle
60+
'dapr.actors.idle_timeout' => null,
61+
62+
// if this service will be hosting any actors, configure how often dapr will check for idle actors
63+
'dapr.actors.scan_interval' => null,
64+
65+
// if this service will be hosting any actors, configure how long dapr will wait for an actor to finish during drains
66+
'dapr.actors.drain_timeout' => null,
67+
68+
// if this service will be hosting any actors, configure if dapr should wait for an actor to finish
69+
'dapr.actors.drain_enabled' => null,
70+
71+
// you shouldn't have to change this, but the setting is here if you need to
72+
'dapr.port' => env('DAPR_HTTP_PORT', '3500'),
73+
74+
// add any custom serialization routines here
75+
'dapr.serializers.custom' => [],
76+
77+
// add any custom deserialization routines here
78+
'dapr.deserializers.custom' => [],
79+
80+
// the following has no effect, as it is the default middlewares and processed in order specified
81+
'dapr.http.middleware.request' => [get(Tracing::class)],
82+
'dapr.http.middleware.response' => [get(ApplicationJson::class), get(Tracing::class)],
83+
];
84+
```
85+
86+
## Create your service
87+
88+
Create `index.php` and put the following contents:
89+
90+
```php
91+
<?php
92+
93+
require_once __DIR__.'/vendor/autoload.php';
94+
95+
use Dapr\App;
96+
97+
$app = App::create(configure: fn(\DI\ContainerBuilder $builder) => $builder->addDefinitions(__DIR__ . '/config.php'));
98+
$app->get('/hello/{name}', function(string $name) {
99+
return ['hello' => $name];
100+
});
101+
$app->start();
102+
```
103+
104+
## Try it out
105+
106+
Initialize dapr with `dapr init` and then start the project with `dapr run -a dev -p 3000 -- php -S 0.0.0.0:3000`.
107+
108+
<!-- IGNORE_LINKS -->
109+
You can now open a web browser and point it to [http://localhost:3000/hello/world](http://localhost:3000/hello/world)
110+
replacing `world` with your name, a pet's name, or whatever you want.
111+
<!-- END_IGNORE -->
112+
113+
Congratulations, you've created your first Dapr service! I'm excited to see what you'll do with it!
114+
115+
## More Information
116+
117+
- [Packagist](https://packagist.org/packages/dapr/php-sdk)
118+
- [Dapr SDK serialization]({{% ref sdk-serialization.md %}})
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
---
2+
type: docs
3+
title: "Virtual Actors"
4+
linkTitle: "Actors"
5+
weight: 1000
6+
description: How to build actors
7+
no_list: true
8+
---
9+
10+
If you're new to the actor pattern, the best place to learn about the actor pattern is in
11+
the [Actor Overview.]({{% ref actors-overview.md %}})
12+
13+
In the PHP SDK, there are two sides to an actor, the Client, and the Actor (aka, the Runtime). As a client of an actor,
14+
you'll interact with a remote actor via the `ActorProxy` class. This class generates a proxy class on-the-fly using one
15+
of several configured strategies.
16+
17+
When writing an actor, state can be managed for you. You can hook into the actor lifecycle, and define reminders and
18+
timers. This gives you considerable power for handling all types of problems that the actor pattern is suited for.
19+
20+
## The Actor Proxy
21+
22+
Whenever you want to communicate with an actor, you'll need to get a proxy object to do so. The proxy is responsible for
23+
serializing your request, deserializing the response, and returning it to you, all while obeying the contract defined by
24+
the specified interface.
25+
26+
In order to create the proxy, you'll first need an interface to define how and what you send and receive from an actor.
27+
For example, if you want to communicate with a counting actor that solely keeps track of counts, you might define the
28+
interface as follows:
29+
30+
```php
31+
<?php
32+
#[\Dapr\Actors\Attributes\DaprType('Counter')]
33+
interface ICount {
34+
function increment(int $amount = 1): void;
35+
function get_count(): int;
36+
}
37+
```
38+
39+
It's a good idea to put this interface in a shared library that the actor and clients can both access (if both are written in PHP). The `DaprType`
40+
attribute tells the DaprClient the name of the actor to send to. It should match the implementation's `DaprType`, though
41+
you can override the type if needed.
42+
43+
```php
44+
<?php
45+
$app->run(function(\Dapr\Actors\ActorProxy $actorProxy) {
46+
$actor = $actorProxy->get(ICount::class, 'actor-id');
47+
$actor->increment(10);
48+
});
49+
```
50+
51+
## Writing Actors
52+
53+
To create an actor, you need to implement the interface you defined earlier and also add the `DaprType` attribute. All
54+
actors *must* implement `IActor`, however there's an `Actor` base class that implements the boilerplate making your
55+
implementation much simpler.
56+
57+
Here's the counter actor:
58+
59+
```php
60+
<?php
61+
#[\Dapr\Actors\Attributes\DaprType('Count')]
62+
class Counter extends \Dapr\Actors\Actor implements ICount {
63+
function __construct(string $id, private CountState $state) {
64+
parent::__construct($id);
65+
}
66+
67+
function increment(int $amount = 1): void {
68+
$this->state->count += $amount;
69+
}
70+
71+
function get_count(): int {
72+
return $this->state->count;
73+
}
74+
}
75+
```
76+
77+
The most important bit is the constructor. It takes at least one argument with the name of `id` which is the id of the
78+
actor. Any additional arguments are injected by the DI container, including any `ActorState` you want to use.
79+
80+
### Actor Lifecycle
81+
82+
An actor is instantiated via the constructor on every request targeting that actor type. You can use it to calculate
83+
ephemeral state or handle any kind of request-specific startup you require, such as setting up other clients or
84+
connections.
85+
86+
After the actor is instantiated, the `on_activation()` method may be called. The `on_activation()` method is called any
87+
time the actor "wakes up" or when it is created for the first time. It is not called on every request.
88+
89+
Next, the actor method is called. This may be from a timer, reminder, or from a client. You may perform any work that
90+
needs to be done and/or throw an exception.
91+
92+
Finally, the result of the work is returned to the caller. After some time (depending on how you've configured the
93+
service), the actor will be deactivated and `on_deactivation()` will be called. This may not be called if the host dies,
94+
daprd crashes, or some other error occurs which prevents it from being called successfully.
95+
96+
## Actor State
97+
98+
Actor state is a "Plain Old PHP Object" (POPO) that extends `ActorState`. The `ActorState` base class provides a couple
99+
of useful methods. Here's an example implementation:
100+
101+
```php
102+
<?php
103+
class CountState extends \Dapr\Actors\ActorState {
104+
public int $count = 0;
105+
}
106+
```
107+
108+
## Registering an Actor
109+
110+
Dapr expects to know what actors a service may host at startup. You need to add it to the configuration:
111+
112+
{{< tabpane text=true >}}
113+
114+
{{% tab header="Production" %}}
115+
116+
If you want to take advantage of pre-compiled dependency injection, you need to use a factory:
117+
118+
```php
119+
<?php
120+
// in config.php
121+
122+
return [
123+
'dapr.actors' => fn() => [Counter::class],
124+
];
125+
```
126+
127+
All that is required to start the app:
128+
129+
```php
130+
<?php
131+
132+
require_once __DIR__ . '/vendor/autoload.php';
133+
134+
$app = \Dapr\App::create(
135+
configure: fn(\DI\ContainerBuilder $builder) => $builder->addDefinitions('config.php')->enableCompilation(__DIR__)
136+
);
137+
$app->start();
138+
```
139+
140+
{{% /tab %}}
141+
{{% tab header="Development" %}}
142+
143+
```php
144+
<?php
145+
// in config.php
146+
147+
return [
148+
'dapr.actors' => [Counter::class]
149+
];
150+
```
151+
152+
All that is required to start the app:
153+
154+
```php
155+
<?php
156+
157+
require_once __DIR__ . '/vendor/autoload.php';
158+
159+
$app = \Dapr\App::create(configure: fn(\DI\ContainerBuilder $builder) => $builder->addDefinitions('config.php'));
160+
$app->start();
161+
```
162+
163+
{{% /tab %}}
164+
{{< /tabpane >}}

0 commit comments

Comments
 (0)