
# Κοινόχρηστα αντικείμενα

Η μεταβίβαση αντικειμένου PHP στο JavaScript μέσω αναφοράς — η ανάγνωση των ιδιοτήτων του, η κλήση των μεθόδων του και η παρατήρηση των αλλαγών στο PHP — **δεν υποστηρίζεται ακόμη**. Παρακολουθείται στο [ζήτημα #18](https://github.com/inline0/phasis/issues/18). Αυτή η σελίδα περιγράφει τι συμβαίνει σήμερα και ποια μοτίβα λειτουργούν ως εναλλακτικές.

## Τι συμβαίνει σήμερα

Το `setGlobal()` μετατρέπει την τιμή του σύμφωνα με τους κανόνες της [Μετατροπής τιμών](https://phasis.inline0.dev/el/docs/interop/values). Ένα αντικείμενο PHP που δεν είναι κλήσιμο δεν μετατρέπεται, οπότε το global γίνεται `undefined`:

```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')
```

Το ίδιο ισχύει για `stdClass`, οντότητες και μοντέλα, κοντέινερ υπηρεσιών, γεννήτριες και πόρους. Εξαιρούνται δύο είδη κλήσιμων αντικειμένων:

- Ένα αντικείμενο με `__invoke()` γίνεται συνάρτηση JS που το καλεί.
- Ένας κλήσιμος πίνακας όπως το `[$counter, 'increment']` γίνεται συνάρτηση JS που καλεί αυτή τη μέθοδο.

Δεν υπάρχει `PhpBridge` ή άλλη κλάση περιτυλίγματος για την έκθεση αντικειμένων· το `src/Interop/` περιέχει μόνο τον μετατροπέα τιμών.

## Έκθεση μεθόδων ως κλεισίματα

Ένα κλείσιμο μπορεί να δεσμεύσει το αντικείμενο, ώστε το JS να καλεί μια συνάρτηση και η μέθοδος να εκτελείται στο αρχικό στιγμιότυπο PHP:

```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
```

Ένας κλήσιμος πίνακας κάνει το ίδιο χωρίς κλείσιμο:

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

## Ομαδοποίηση σε πίνακα

Ένας συσχετιστικός πίνακας γίνεται αντικείμενο JS και τα κλεισίματα μέσα σε αυτόν γίνονται συναρτήσεις. Έτσι το JS αποκτά αντικείμενο API, του οποίου οι μέθοδοι λειτουργούν στο στιγμιότυπο PHP:

```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
```

Μόνο όσα βάλετε στον πίνακα είναι ορατά στο JS, οπότε η ιδιωτική κατάσταση, όπως το `$secret`, παραμένει στο PHP.

Τα πεδία δεδομένων είναι αντίγραφα που λαμβάνονται όταν εκτελείται το `setGlobal()`. Στο παράδειγμα, το `user.name` είναι συμβολοσειρά στο JS· αν του αναθέσετε νέα τιμή, αλλάζει το αντίγραφο JS και όχι το `$user->name`. Περάστε κάθε εγγραφή μέσω κλεισίματος.

## Εξαγωγή δεδομένων και επιστροφή αποτελεσμάτων

Για αντικείμενα με μορφή δεδομένων, μετατρέψτε τα σε πίνακα κατά την είσοδο και διαβάστε το αποτέλεσμα κατά την έξοδο:

```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)` ή μια μέθοδος `toArray()` σάς δίνει τον πίνακα ενός αντικειμένου. Έπειτα εφαρμόστε τον πίνακα που επιστράφηκε στο αντικείμενο, την οντότητα ή το μοντέλο σας στο PHP.

## Επισημάνσεις

- Οι εξαιρέσεις που προκύπτουν μέσα σε αυτές τις συναρτήσεις κλεισίματος δεν μπορούν προς το παρόν να συλληφθούν από τα JS `try` / `catch`· φτάνουν στον καλούντα του `eval()` ([issue #20](https://github.com/inline0/phasis/issues/20)). Δείτε τις [Συναρτήσεις φιλοξενίας](https://phasis.inline0.dev/el/docs/interop/host-functions#throwing-back-into-js).
- Μια συνάρτηση κλεισίματος που έχει καταχωριστεί με το `setGlobal()` διατηρεί ζωντανά τα αντικείμενα που δεσμεύει, όσο η μηχανή διατηρεί το καθολικό αντικείμενο.
