
# 互操作

Phasis 与你的应用运行在同一个 PHP 进程中，因此值可在 PHP 和 JavaScript 之间传递，无需 JSON、管道或第二个运行时。值通过**转换**传递：标量映射为 JS 基本类型，PHP 数组会复制为新的 JS 数组和对象，JS 结果则会复制回 PHP 数组。JS 修改转换后的数组，不会影响 PHP 数组。PHP 可调用对象是例外，它们会保持活动状态：会成为直接调用 PHP 的 JS 函数。

本节介绍这些规则。

## 页面

- **[值](https://phasis.inline0.dev/zh/docs/interop/values)** — 两个方向的转换表：数字、字符串、布尔值、null/undefined、数组、对象，以及无法转换的值。
- **[宿主函数](https://phasis.inline0.dev/zh/docs/interop/host-functions)** — 通过 `$engine->setGlobal()` 将 PHP `callable` 绑定为 JS 函数。参数转换、返回值以及异常的处理方式。
- **[共享对象](https://phasis.inline0.dev/zh/docs/interop/shared-objects)** — 将 PHP 对象传给 JS 时会发生什么（目前会作为 `undefined` 到达），以及如何改用数组和闭包暴露 PHP 状态与行为。
- **[Fetch 传输](https://phasis.inline0.dev/zh/docs/interop/fetch-transport)** — 将默认的 `ext-curl` HTTP 后端换成 Guzzle、Symfony HttpClient、模拟传输或全部拒绝的传输。还介绍用于允许列表、标头注入和按租户绑定的策略钩子。
- **[Cookie 存储](https://phasis.inline0.dev/zh/docs/interop/cookie-jar)** — 挂载 `get(url)`/`set(url, header)` 存储以在多次 fetch 之间保留 Cookie。可使用内存存储、Symfony BrowserKit，或 JS 端的 `Map`。
- **[AbortController 模式](https://phasis.inline0.dev/zh/docs/interop/abort-patterns)** — 超时、竞态、传播、`AbortSignal.any` / `.timeout`，以及自定义 PHP 传输如何在传输过程中轮询信号。

## 快速示例

```php
$engine = new Phasis\Engine();

// 1. Bind a PHP callable as a JS function
$engine->setGlobal('greet', fn (string $name) => "Hello, $name!");
echo $engine->eval('greet("world")');  // → Hello, world!

// 2. Let JS change PHP state through a closure
$total = 0;
$engine->setGlobal('add', function (int $n) use (&$total): void { $total += $n; });
$engine->eval('add(2); add(3)');
echo $total;  // → 5

// 3. Call a JS function from PHP
$engine->eval('function add(a, b) { return a + b; }');
echo $engine->call('add', 2, 3);  // → 5
```

## 另请参阅

- [API 参考](https://phasis.inline0.dev/zh/docs/api) — 完整的 `Phasis\Engine` 功能范围。
- [Web API](https://phasis.inline0.dev/zh/docs/compatibility/web-apis) — Web Platform Pack 和 Fetch Pack 都基于同一互操作层运行。
