
# Paylaşılan nesneler

Bir PHP nesnesini referansla JavaScript içine aktarma — özelliklerini okuma, yöntemlerini çağırma ve değişiklikleri PHP içinde görme — **henüz desteklenmiyor**. Bu konu [sorun #18](https://github.com/inline0/phasis/issues/18) kapsamında izleniyor. Bu sayfa bugün ne olduğunu ve bunun yerine işe yarayan kalıpları açıklar.

## Bugün ne oluyor

`setGlobal()`, değerini [Değer dönüştürme](https://phasis.inline0.dev/tr/docs/interop/values) içindeki kurallara göre dönüştürür. Çağrılabilir olmayan bir PHP nesnesinin dönüşüm kuralı yoktur; bu nedenle global değer `undefined` olur:

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

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

$engine->eval('typeof counter');
// "undefined"

$engine->eval('counter.increment()');
// throws Phasis\Exceptions\TypeError:
// Cannot read properties of undefined (reading 'increment')
```

Aynısı `stdClass`, varlıklar ve modeller, servis kapsayıcıları, üreteçler ve kaynaklar için de geçerlidir. İki istisna çağrılabilir nesnelerdir:

- `__invoke()` içeren bir nesne, onu çağıran bir JS işlevine dönüşür.
- `[$counter, 'increment']` gibi çağrılabilir bir dizi, o yöntemi çağıran bir JS işlevine dönüşür.

Nesneleri sunmak için `PhpBridge` veya başka bir sarmalayıcı sınıf yoktur; `src/Interop/` yalnızca değer dönüştürücüsünü içerir.

## Yöntemleri kapanım olarak sunma

Bir kapanım nesneyi yakalayabilir; böylece JS bir işlevi çağırır ve yöntem özgün PHP örneği üzerinde çalışır:

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

$engine->eval('increment(); increment(); count()');
// 2

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

Çağrılabilir bir dizi de kapanım olmadan aynı işi yapar:

```php
$engine->setGlobal('increment', [$counter, 'increment']);
```

## Bunları bir dizide gruplama

İlişkisel bir dizi JS nesnesine, içindeki kapanımlar da işlevlere dönüşür. Böylece JS, yöntemleri PHP örneği üzerinde çalışan nesne biçimli bir API elde eder:

```php
class User {
    public function __construct(
        public string $name,
        public int $age,
        private string $secret,
    ) {}

    public function greet(): string {
        return "Hi, I'm $this->name";
    }
}

$user = new User('Ada', 36, 'topsecret');

$engine->setGlobal('user', [
    'name'   => $user->name,
    'greet'  => fn () => $user->greet(),
    'setAge' => function (int $age) use ($user): void { $user->age = $age; },
]);

$engine->eval('user.greet()');
// "Hi, I'm Ada"

$engine->eval('user.setAge(37)');
echo $user->age;
// 37
```

Dizide ekledikleriniz dışında hiçbir şey JS tarafından görülemez; bu nedenle `$secret` gibi özel durumlar PHP içinde kalır.

Veri alanları, `setGlobal()` çalıştığında alınan kopyalardır. Örnekte `user.name`, JS içinde bir dizedir; ona atama yapmak JS kopyasını değiştirir, `$user->name` değerini değil. Her yazma işlemini bir kapanım üzerinden yönlendirin.

## Veriyi dışarı, sonuçları geri aktarma

Veri biçimli nesneler için, içeri girerken diziye dönüştürün ve sonucu çıkarken okuyun:

```php
$post = ['title' => 'Draft', 'tags' => ['php']];

$engine->setGlobal('post', $post);
$engine->eval('function edit(p) { p.title = "Edited from JS"; return p; }');

$post = $engine->call('edit', $post);
echo $post['title'];
// Edited from JS
```

`get_object_vars($object)` veya bir `toArray()` yöntemi, nesne için diziyi sağlar. Ardından döndürülen diziyi PHP içindeki nesnenize, varlığınıza veya modelinize uygulayın.

## Dikkat edilmesi gerekenler

- Bu kapatmaların içinde fırlatılan istisnalar şu anda JS `try` / `catch` tarafından yakalanamaz; `eval()` çağrısının çağıranına ulaşır ([sorun #20](https://github.com/inline0/phasis/issues/20)). Bkz. [Ana makine işlevleri](https://phasis.inline0.dev/tr/docs/interop/host-functions#throwing-back-into-js).
- `setGlobal()` ile kaydedilen bir kapatma, motor global değişkeni tuttuğu sürece yakaladığı nesneleri bellekte tutar.
