
# Aan de slag

## Installeren

```bash
composer require phasis/phasis
```

Phasis vereist PHP 8.2 of hoger met drie extensies, allemaal vereist door `composer.json`:

- `mbstring` — tekenreeksverwerking.
- `bcmath` — BigInt-berekeningen en getallen met gehele precisie.
- `curl` — het standaardtransport achter `fetch()`.

`mbstring` en `curl` zijn in de meeste builds ingeschakeld. `bcmath` vaak niet: de officiële `php`-Docker-images (`php:8.x-cli`, `php:8.x-fpm`) bevatten het niet, en sommige distributies leveren het apart (`php-bcmath`). Zonder dit weigert Composer Phasis te installeren. Voeg in een Dockerfile op basis van de officiële image het volgende toe:

```dockerfile
RUN docker-php-ext-install bcmath
```

Voer `php -m` uit om te zien welke extensies je build bevat.

`ext-intl` is optioneel. Phasis werkt zonder, maar de volledige `Intl.*`-familie (`Collator`, `NumberFormat`, `DateTimeFormat`, `PluralRules`, `Locale`, `DisplayNames`, `ListFormat`, `RelativeTimeFormat`, `Segmenter`, `DurationFormat`) en de niet-ISO-kalenders van Temporal (`hebrew`, `islamic`, `japanese`, `persian` enz.) hebben het nodig. Installeer het wanneer de hostapplicatie JS aanbiedt die lokale instellingen gebruikt voor opmaak. `ext-openssl` is eveneens optioneel: `crypto.subtle` vereist AES-CBC-, AES-CTR- en AES-GCM-versleuteling, terwijl digests en HMAC zonder werken.

Geen `exec`, geen FFI, geen Node.js, geen aangepaste native extensie.

## Een script uitvoeren vanuit de CLI

```bash
./vendor/bin/phasis -e 'console.log(1 + 2 * 3)'
# 7

./vendor/bin/phasis -e 'console.log([1, 2, 3].map(x => x * x).join(","))'
# 1,4,9

./vendor/bin/phasis path/to/script.js
```

De CLI toont wat het script met `console.log` naar buiten schrijft; de waarde van de laatste expressie wordt niet getoond.

Zie de [CLI-referentie](https://phasis.inline0.dev/nl/docs/cli) voor de volledige set opdrachten.

## Inbedden in PHP

```php
<?php

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

use Phasis\Engine;

$engine = new Engine();

// Evaluate an expression
$result = $engine->eval('1 + 2 * 3');
echo $result;
// 7

// Execute a script file
$engine->execFile('path/to/script.js');

// Bridge a PHP value into the JS global scope
$engine->setGlobal('config', ['debug' => true, 'version' => '1.0']);
$engine->eval('console.log(config.version)');

// console output is buffered on the engine, not printed
echo $engine->getConsoleOutput();
// 1.0
```

De `Engine`-instantie bewaart de globale status tussen aanroepen, zodat volgende aanroepen van `eval()` alles zien wat je eerder hebt gedefinieerd.

`console.log` en de bijbehorende functies voegen tekst toe aan een buffer op de engine in plaats van naar stdout te schrijven. Lees die met `getConsoleOutput()` (één tekenreeks, regels samengevoegd met `\n`) of `getConsoleLines()` (een lijst met regels) en maak de buffer leeg met `clearConsole()`.

Een koude start is goedkoop: alleen de kern die de specificatie draagt (`Object`, `Function`, `Array`, `Promise`, `Symbol`, `BigInt`, `RegExp`, de fouttypen) wordt vooraf geïnstalleerd. `Map`, `TypedArray`, `Temporal`, `Intl`, `URL`, `fetch`, de volledige Web Platform / Fetch Packs en al het overige worden transparant geladen bij de eerste uitlezing. Geef `new Engine(eager: true)` mee om bij het maken alle ingebouwde onderdelen te installeren — handig voor conformiteitstools die descriptors inspecteren voordat ze worden uitgelezen; zelden nodig bij normaal inbedden.

## JS-functies aanroepen vanuit PHP

```php
$engine->eval('function add(a, b) { return a + b; }');
echo $engine->call('add', 2, 3);
// 5
```

`call()` zoekt de functie op naam op het globale object en roept die aan met de opgegeven argumenten van PHP (automatisch omgezet naar JS-waarden).

## Een aanroepbare PHP beschikbaar maken als JS-functie

```php
$engine->setGlobal('fetchData', function (string $url): array {
    return json_decode(file_get_contents($url), true);
});

$engine->eval('const users = fetchData("https://api.example.com/users")');
```

PHP-closures worden verpakt als JS-functies. Bij aanroepen worden argumenten omgezet van JS naar PHP en retourwaarden van PHP terug naar JS.

## PHP-objecten

PHP-objecten kunnen nog niet worden gedeeld met JavaScript. `setGlobal()` met een gewoon PHP-object koppelt `undefined` (bijgehouden in [issue #18](https://github.com/inline0/phasis/issues/18)). Geef gegevens door als arrays, die naar JS worden gekopieerd, en stel gedrag beschikbaar als closures:

```php
class Counter {
    public int $value = 0;
    public function increment(): void { $this->value++; }
}

$counter = new Counter();
$engine->setGlobal('increment', fn () => $counter->increment());

$engine->eval('increment(); increment();');

echo $counter->value;
// 2
```

Zie [Gedeelde objecten](https://phasis.inline0.dev/nl/docs/interop/shared-objects) voor meer informatie en andere oplossingen.

## Resourcelimieten

```php
$engine = new Engine();
$engine->setLimit('maxLoopIterations', 100_000);
```

`maxLoopIterations` (standaard 100,000) is de enige limiet die tijdens runtime kan worden ingesteld; momenteel geldt die alleen voor code die door de tree-walking interpreter wordt uitgevoerd. Lussen die de bytecode-VM uitvoert (functieblokken en de meeste code op topniveau) worden niet meegeteld, dus met alleen een limiet wordt `while (true) {}` niet tegengehouden ([issue #19](https://github.com/inline0/phasis/issues/19)). Wanneer de limiet is bereikt, kan de fout worden opgevangen in JS; als dat niet gebeurt, bereikt de fout PHP als `Phasis\Exceptions\InternalError`, een subklasse van `Phasis\Exceptions\RuntimeError`.

De engine heeft ook een vaste limiet van 4,096 frames voor de aanroepstack (en een beveiliging van 8,192 frames voor getranspilede closures); bij overschrijding wordt "Maximum call stack size exceeded" gegooid, opnieuw als `InternalError`. Er is geen limiet op de wandkloktijd, dus voer niet-vertrouwde code uit onder de eigen `max_execution_time` van PHP of in een afzonderlijk proces. Zie [API: setLimit](https://phasis.inline0.dev/nl/docs/api#setlimit).

## Volgende stappen

- [API-referentie](https://phasis.inline0.dev/nl/docs/api) — de volledige `Phasis\Engine`-interface.
- [Interoperabiliteit](https://phasis.inline0.dev/nl/docs/interop) — regels voor waardeconversie, hostfuncties, PHP-objecten.
- [Compatibiliteit](https://phasis.inline0.dev/nl/docs/compatibility) — wat is geïmplementeerd, test262-dekking.
- [Parser](https://phasis.inline0.dev/nl/docs/parser) en [Formatter](https://phasis.inline0.dev/nl/docs/formatter) — JavaScript parsen en opmaken zonder het uit te voeren.
- [Geavanceerd](https://phasis.inline0.dev/nl/docs/advanced) — architectuur, bytecode-VM, benchmarks, tests met een orakel.
