Koplietojami objekti
PHP objekta nodošana JavaScript pēc atsauces — tā īpašību lasīšana, metožu izsaukšana un izmaiņu redzēšana PHP — vēl netiek atbalstīta. Tas ir reģistrēts kā 18. problēma. Šajā lapā aprakstīts, kas notiek pašlaik un kādi paņēmieni darbojas tā vietā.
Kas notiek pašlaik
setGlobal() pārveido vērtību saskaņā ar noteikumiem, kas aprakstīti sadaļā Vērtību pārveide. PHP objektam, kas nav izsaucams, nav atbilstošas pārveides, tāpēc globālā vērtība ir undefined:
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')
Tas pats attiecas uz stdClass, entītijām un modeļiem, pakalpojumu konteineriem, ģeneratoriem un resursiem. Izņēmums ir divu veidu izsaucami objekti:
- Objekts ar
__invoke()kļūst par JS funkciju, kas to izsauc. - Izsaucams masīvs, piemēram,
[$counter, 'increment'], kļūst par JS funkciju, kas izsauc attiecīgo metodi.
Objektu atklāšanai nav ne PhpBridge, ne citas iesaiņotāja klases; src/Interop/ ietver tikai vērtību pārveidotāju.
Atklājiet metodes kā slēgtās funkcijas
Slēgtā funkcija var saglabāt objektu, tāpēc JS izsauc funkciju, un metode darbojas sākotnējā PHP instancē:
$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
Izsaucams masīvs dara to pašu bez slēgtās funkcijas:
$engine->setGlobal('increment', [$counter, 'increment']);
Grupējiet tās masīvā
Asociatīvais masīvs kļūst par JS objektu, un tajā iekļautās slēgtās funkcijas kļūst par funkcijām. Tādējādi JS iegūst objektam līdzīgu API, kura metodes darbojas ar PHP instanci:
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 ir redzams tikai tas, ko iekļaujat masīvā, tāpēc privāts stāvoklis, piemēram, $secret, paliek PHP.
Datu lauki ir kopijas, kas iegūtas brīdī, kad darbojas setGlobal(). Piemērā user.name ir virkne JS; piešķirot tai vērtību, tiek mainīta JS kopija, nevis $user->name. Visas ierakstīšanas darbības veiciet, izmantojot slēgto funkciju.
Nododiet datus un saņemiet rezultātus
Datu objektiem pārveidojiet tos par masīvu, nododot iekšā, un nolasiet rezultātu, saņemot to atpakaļ:
$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) vai toArray() metode nodrošina objekta masīvu. Pēc tam lietojiet atgriezto masīvu savam objektam, entītijai vai modelim PHP.
Ierobežojumi
- JS šajās slēgtajās funkcijās pašlaik nevar uztvert
trycatchizņēmumus; tie nonāk līdzeval()izsaucējam (20. problēma). Skatiet sadaļu Resursdatora funkcijas. - Slēgtā funkcija, kas reģistrēta ar
setGlobal(), uztur savus objektus dzīvus tik ilgi, kamēr dzinējs saglabā globālo vērtību.