diff --git a/packages/docs/site/docs/developers/05-local-development/03-php-wasm-node.md b/packages/docs/site/docs/developers/05-local-development/03-php-wasm-node.md index cc75499dc2..c68043fcc0 100644 --- a/packages/docs/site/docs/developers/05-local-development/03-php-wasm-node.md +++ b/packages/docs/site/docs/developers/05-local-development/03-php-wasm-node.md @@ -1,20 +1,584 @@ --- title: php-wasm/node slug: /developers/local-development/php-wasm-node +description: WordPress Playground brings WebAssembly-powered PHP to Node.js for server-side execution, data processing, and testing without a native install. --- # Using WordPress Playground in Node.js As a WebAssembly project, you can also use WordPress Playground in Node.js. -If you need low-level control over the underlying WebAssembly PHP build, take a look at the [`@php-wasm/node` package](https://npmjs.org/@php-wasm/node) which ships the PHP WebAssembly runtime. This package is at the core of all WordPress Playground tools for Node.js. - -:::info **API reference** +If you need low-level control over the underlying WebAssembly PHP build, take a look at the [@php-wasm/node package](https://npmjs.org/@php-wasm/node) which ships the PHP WebAssembly runtime. This package is at the core of all WordPress Playground tools for Node.js. Consult the [complete list](/api/node) of Classes, Functions, Interfaces, and Type Aliases. -::: +## WebAssembly PHP for Node.js + +This package ships WebAssembly PHP binaries and the JavaScript API optimized for Node.js. It uses the host file system directly and can access the network if you plug in a custom WS proxy. + +### Basic usage + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); +const output = await php.runStream({ + code: '', +}); +console.log(await output.stdoutText); +``` + +## Use cases + +Run PHP inside Node.js without a native PHP install. Allow developer to produce the following solutions: + +- CI/CD jobs and developer tooling. +- Support education and WordPress workflows: Power interactive tutorials, sandboxes, and coding challenges. +- Generate content and prototype server behavior. +- Render HTML using PHP templates, and quickly stand up mock API endpoints to simulate requests. + +## Practical demos + +We will list some examples using the PHP-WASM package. + +### Demo 1: File system operations + +Execute PHP scripts that interact with the file system: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create directory structure +php.mkdir('/app/data'); + +// Write configuration file +await php.writeFile( + '/app/config.json', + JSON.stringify({ + app: 'MyApp', + version: '1.0.0', + debug: true, + }) +); + +// Create and run PHP script that reads the config +await php.writeFile( + '/app/index.php', + `` +); + +const result = await php.runStream({ scriptPath: '/app/index.php' }); +console.log(await result.stdoutText); +``` + +### Demo 2: SQLite database operations + +Use PHP's SQLite extension for data storage: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create directory for database +php.mkdir('/data'); + +// Create database, insert data, and query +const result = await php.runStream({ + code: `exec('CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +)'); + +// Insert sample data +$stmt = $db->prepare('INSERT INTO users (name, email) VALUES (?, ?)'); +$users = [ + ['Alice Johnson', 'alice@example.com'], + ['Bob Smith', 'bob@example.com'], + ['Charlie Davis', 'charlie@example.com'] +]; + +foreach ($users as $user) { + $stmt->bindValue(1, $user[0]); + $stmt->bindValue(2, $user[1]); + $stmt->execute(); +} + +// Query data +echo "All Users:\\n"; +echo str_repeat('-', 50) . "\\n"; +$results = $db->query('SELECT * FROM users ORDER BY name'); +while ($row = $results->fetchArray(SQLITE3_ASSOC)) { + echo "ID: {$row['id']} | {$row['name']} ({$row['email']})\\n"; +} + +$db->close(); +?>`, +}); + +console.log(await result.stdoutText); + +// Database file persists in the virtual file system +const dbExists = await php.fileExists('/data/app.db'); +console.log('\nDatabase persisted:', dbExists); +``` + +### Demo 3: Processing uploaded files (ZIP archives) + +Process ZIP files using PHP's Libzip extension: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create sample files +php.mkdir('/uploads'); +await php.writeFile('/uploads/readme.txt', 'This is a sample text file'); +await php.writeFile('/uploads/data.json', JSON.stringify({ name: 'Test', version: '1.0' })); + +// Create, process, and extract ZIP archive +const result = await php.runStream({ + code: `open('/uploads/archive.zip', ZipArchive::CREATE); +$zip->addFromString('readme.txt', file_get_contents('/uploads/readme.txt')); +$zip->addFromString('data.json', file_get_contents('/uploads/data.json')); +$zip->addFromString('info.txt', 'Created with PHP WASM'); +$zip->close(); + +echo "ZIP archive created successfully\\n\\n"; + +// Read and display archive contents +$zip->open('/uploads/archive.zip'); +echo "Archive Contents:\\n"; +echo str_repeat('=', 50) . "\\n"; + +for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + $size = round($stat['size'] / 1024, 2); + echo sprintf("%-40s %10s KB\\n", $stat['name'], $size); +} + +// Extract files +$zip->extractTo('/uploads/extracted/'); +$zip->close(); + +echo "\\nExtracted successfully to /uploads/extracted/\\n"; + +// List extracted files +echo "\\nExtracted Files:\\n"; +$files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator('/uploads/extracted/') +); +foreach ($files as $file) { + if ($file->isFile()) { + echo " " . $file->getPathname() . "\\n"; + } +} +?>`, +}); + +console.log(await result.stdoutText); +``` + +### Demo 4: HTTP request/response pattern + +Simulate web server behavior with request handlers: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Set up a simple API endpoint +await php.mkdir('/www/api'); +await php.writeFile( + '/www/api/users.php', + ` [ + ['id' => 1, 'name' => 'John Doe'], + ['id' => 2, 'name' => 'Jane Smith'] + ] + ]); + break; + + case 'POST': + $name = $input['name'] ?? 'Unknown'; + echo json_encode([ + 'success' => true, + 'user' => [ + 'id' => 3, + 'name' => $name + ], + 'message' => "User $name created" + ]); + break; + + default: + http_response_code(405); + echo json_encode(['error' => 'Method not allowed']); +} +?>` +); + +// Make GET request +const getResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'GET', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, +}); +console.log('GET Response:', await getResponse.stdoutText); + +// Make POST request +const postResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'POST', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, + body: JSON.stringify({ name: 'Alice Wonder' }), +}); +console.log('\\nPOST Response:', await postResponse.stdoutText); +``` + +### Demo 5: Template rendering engine + +Use PHP as a templating engine for dynamic content: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create templates directory +php.mkdir('/templates'); + +// Create template +await php.writeFile( + '/templates/email.php', + ` + + + + + +
+

Welcome, !

+
+
+

Thank you for registering with .

+

Your account details:

+ +

You now have access to the following features:

+ +
+ + +` +); + +// Render template with data +const templateData = { + name: 'Priya Sharma', + email: 'priya@example.com', + appName: 'MyAwesomeApp', + timestamp: Math.floor(Date.now() / 1000), + features: ['Dashboard Access', 'API Integration', 'Premium Support', 'Custom Branding'], +}; + +// Pass data to template via environment variables or files +await php.writeFile('/template-data.json', JSON.stringify(templateData)); + +const result = await php.runStream({ + code: ``, +}); + +console.log(await result.stdoutText); +// Now you have rendered HTML that can be sent via email or saved +``` + +### Demo 6: Real-time code execution and streaming + +Process PHP output as it's generated: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +await php.writeFile( + '/stream-demo.php', + `` +); + +// Run PHP script +const streamedResponse = await php.runStream({ + scriptPath: '/stream-demo.php', +}); + +streamedResponse.stdout.pipeTo( + new WritableStream({ + write(chunk) { + console.log(chunk); + }, + }) +); +``` + +## Integration patterns + +### Pattern 1: Express.js middleware + +Integrate PHP processing into an Express.js application: + +```TypeScript +import express from 'express'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const app = express(); +const php = new PHP(await loadNodeRuntime('8.3')); + +// PHP execution middleware +app.use('/php', async (req, res, next) => { + try { + const phpScript = req.query.script || 'index.php'; + const result = await php.runStream({ + scriptPath: `/www/${phpScript}`, + env: { + REQUEST_METHOD: req.method, + QUERY_STRING: new URLSearchParams( + req.query as Record + ).toString(), + REQUEST_URI: req.url, + }, + }); + + res.send(await result.stdoutText); + } catch (error) { + next(error); + } +}); + +app.listen(3000, () => { + console.log('Server with PHP support running on port 3000'); +}); +``` + +### Pattern 2: Automated testing + +Create automated tests for PHP code: + +```TypeScript +import { describe, it, expect, beforeAll } from '@jest/globals'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +describe('PHP Functions', () => { + let php: PHP; + + beforeAll(async () => { + php = new PHP(await loadNodeRuntime('8.3')); + }); + + it('should calculate sum correctly', async () => { + const result = await php.run({ + code: ``, + }); + + expect(result.text).toBe('8'); + }); + + it('should handle JSON operations', async () => { + const input = { name: 'Test', value: 42 }; + const result = await php.run({ + code: ` $input, + 'doubled' => $input['value'] * 2 + ]; + echo json_encode($output); + ?>`, + }); + + const output = JSON.parse(result.text); + expect(output.doubled).toBe(84); + }); +}); +``` + +### Pattern 3: Build tool integration + +Use in build scripts with other Node.js tools: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; +import fs from 'fs/promises'; + +async function generateDocumentation() { + const php = new PHP(await loadNodeRuntime('8.3')); + + // Create output directory + php.mkdir('/output'); + + // Generate documentation + const result = await php.runStream({ + code: ``, + }); + + console.log(await result.stdoutText); + + // Extract generated docs back to Node.js file system + await fs.mkdir('./docs', { recursive: true }); + const summaryContent = await php.readFileAsText('/output/summary.md'); + await fs.writeFile('./docs/summary.md', summaryContent); + + console.log('Documentation saved to ./docs/summary.md'); +} + +generateDocumentation().catch(console.error); +``` + +## Advanced features + +### Working with environment variables + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +const result = await php.runStream({ + code: '', + env: { + CUSTOM_VAR: 'Hello from Node.js!', + }, +}); + +console.log(await result.stdoutText); +``` + +### Error handling + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +try { + const result = await php.runStream({ + code: '', + }); + + const stdout = await result.stdoutText; + const stderr = await result.stderrText; + + console.log('stdout:', stdout); + console.log('stderr:', stderr); + + if (stderr) { + console.error('PHP produced errors:', stderr); + } +} catch (error: any) { + console.error('JavaScript Error:', error.message); +} +``` -import PHPWASMNode from '@php-wasm/node/\README.md'; +## Performance considerations - +- **Reuse PHP instances**: Creating a new PHP instance is expensive. Reuse the same instance when possible. +- **Batch operations**: Group multiple file operations together rather than running separate scripts. +- **Memory management**: Large files may impact performance. Consider streaming for big datasets. +- **Caching**: Cache compiled PHP scripts and frequently accessed data. diff --git a/packages/docs/site/i18n/es/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md b/packages/docs/site/i18n/es/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md new file mode 100644 index 0000000000..06f878509e --- /dev/null +++ b/packages/docs/site/i18n/es/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md @@ -0,0 +1,661 @@ +--- +title: php-wasm/node +slug: /developers/local-development/php-wasm-node +description: WordPress Playground trae PHP con WebAssembly a Node.js para ejecución del lado del servidor, procesamiento de datos y pruebas sin instalación nativa. +--- + + + +# Usando WordPress Playground en Node.js + + + +Como un proyecto WebAssembly, también puedes usar WordPress Playground en Node.js. + + + +Si necesitas control de bajo nivel sobre la compilación WebAssembly de PHP subyacente, echa un vistazo al [paquete @php-wasm/node](https://npmjs.org/@php-wasm/node) que incluye el runtime WebAssembly de PHP. Este paquete está en el núcleo de todas las herramientas de WordPress Playground para Node.js. + + + +Consulta la [lista completa](/api/node) de Clases, Funciones, Interfaces y Alias de Tipos. + + + +## WebAssembly PHP para Node.js + + + +Este paquete incluye binarios WebAssembly de PHP y la API JavaScript optimizada para Node.js. Utiliza el sistema de archivos del host directamente y puede acceder a la red si conectas un proxy WS personalizado. + + + +### Uso básico + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); +const output = await php.runStream({ + code: '', +}); +console.log(await output.stdoutText); +``` + + + +## Casos de uso + + + + + + + +Ejecuta PHP dentro de Node.js sin instalación nativa de PHP. Permite al desarrollador producir las siguientes soluciones: + +- Tareas de CI/CD y herramientas de desarrollo. +- Soporte a educación y flujos de trabajo de WordPress: potencia tutoriales interactivos, sandboxes y retos de código. +- Generar contenido y prototipar comportamiento de servidor. +- Renderizar HTML usando plantillas PHP y levantar rápidamente endpoints de API simulados para simular peticiones. + + + +## Demos prácticas + + + +Enumeraremos algunos ejemplos usando el paquete PHP-WASM. + + + +### Demo 1: Operaciones en el sistema de archivos + + + +Ejecuta scripts PHP que interactúan con el sistema de archivos: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Crear estructura de directorios +php.mkdir('/app/data'); + +// Escribir archivo de configuración +await php.writeFile( + '/app/config.json', + JSON.stringify({ + app: 'MyApp', + version: '1.0.0', + debug: true, + }) +); + +// Crear y ejecutar script PHP que lee la configuración +await php.writeFile( + '/app/index.php', + `` +); + +const result = await php.runStream({ scriptPath: '/app/index.php' }); +console.log(await result.stdoutText); +``` + + + +### Demo 2: Operaciones de base de datos SQLite + + + +Usa la extensión SQLite de PHP para almacenamiento de datos: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Crear directorio para la base de datos +php.mkdir('/data'); + +// Crear base de datos, insertar datos y consultar +const result = await php.runStream({ + code: `exec('CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +)'); + +// Insertar datos de ejemplo +$stmt = $db->prepare('INSERT INTO users (name, email) VALUES (?, ?)'); +$users = [ + ['Alice Johnson', 'alice@example.com'], + ['Bob Smith', 'bob@example.com'], + ['Charlie Davis', 'charlie@example.com'] +]; + +foreach ($users as $user) { + $stmt->bindValue(1, $user[0]); + $stmt->bindValue(2, $user[1]); + $stmt->execute(); +} + +// Consultar datos +echo "All Users:\\n"; +echo str_repeat('-', 50) . "\\n"; +$results = $db->query('SELECT * FROM users ORDER BY name'); +while ($row = $results->fetchArray(SQLITE3_ASSOC)) { + echo "ID: {$row['id']} | {$row['name']} ({$row['email']})\\n"; +} + +$db->close(); +?>`, +}); + +console.log(await result.stdoutText); + +// El archivo de base de datos persiste en el sistema de archivos virtual +const dbExists = await php.fileExists('/data/app.db'); +console.log('\nDatabase persisted:', dbExists); +``` + + + +### Demo 3: Procesamiento de archivos subidos (archivos ZIP) + + + +Procesa archivos ZIP usando la extensión Libzip de PHP: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Crear archivos de ejemplo +php.mkdir('/uploads'); +await php.writeFile('/uploads/readme.txt', 'This is a sample text file'); +await php.writeFile('/uploads/data.json', JSON.stringify({ name: 'Test', version: '1.0' })); + +// Crear, procesar y extraer archivo ZIP +const result = await php.runStream({ + code: `open('/uploads/archive.zip', ZipArchive::CREATE); +$zip->addFromString('readme.txt', file_get_contents('/uploads/readme.txt')); +$zip->addFromString('data.json', file_get_contents('/uploads/data.json')); +$zip->addFromString('info.txt', 'Created with PHP WASM'); +$zip->close(); + +echo "ZIP archive created successfully\\n\\n"; + +// Leer y mostrar contenido del archivo +$zip->open('/uploads/archive.zip'); +echo "Archive Contents:\\n"; +echo str_repeat('=', 50) . "\\n"; + +for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + $size = round($stat['size'] / 1024, 2); + echo sprintf("%-40s %10s KB\\n", $stat['name'], $size); +} + +// Extraer archivos +$zip->extractTo('/uploads/extracted/'); +$zip->close(); + +echo "\\nExtracted successfully to /uploads/extracted/\\n"; + +// Listar archivos extraídos +echo "\\nExtracted Files:\\n"; +$files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator('/uploads/extracted/') +); +foreach ($files as $file) { + if ($file->isFile()) { + echo " " . $file->getPathname() . "\\n"; + } +} +?>`, +}); + +console.log(await result.stdoutText); +``` + + + +### Demo 4: Patrón de petición/respuesta HTTP + + + +Simula comportamiento de servidor web con manejadores de peticiones: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Configurar un endpoint de API simple +await php.mkdir('/www/api'); +await php.writeFile( + '/www/api/users.php', + ` [ + ['id' => 1, 'name' => 'John Doe'], + ['id' => 2, 'name' => 'Jane Smith'] + ] + ]); + break; + + case 'POST': + $name = $input['name'] ?? 'Unknown'; + echo json_encode([ + 'success' => true, + 'user' => [ + 'id' => 3, + 'name' => $name + ], + 'message' => "User $name created" + ]); + break; + + default: + http_response_code(405); + echo json_encode(['error' => 'Method not allowed']); +} +?>` +); + +// Hacer petición GET +const getResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'GET', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, +}); +console.log('GET Response:', await getResponse.stdoutText); + +// Hacer petición POST +const postResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'POST', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, + body: JSON.stringify({ name: 'Alice Wonder' }), +}); +console.log('\\nPOST Response:', await postResponse.stdoutText); +``` + + + +### Demo 5: Motor de renderización de plantillas + + + +Usa PHP como motor de plantillas para contenido dinámico: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Crear directorio de plantillas +php.mkdir('/templates'); + +// Crear plantilla +await php.writeFile( + '/templates/email.php', + ` + + + + + +
+

Welcome, !

+
+
+

Thank you for registering with .

+

Your account details:

+
    +
  • Email:
  • +
  • Member Since:
  • +
+

You now have access to the following features:

+
    + +
  • + +
+
+ + +` +); + +// Renderizar plantilla con datos +const templateData = { + name: 'Priya Sharma', + email: 'priya@example.com', + appName: 'MyAwesomeApp', + timestamp: Math.floor(Date.now() / 1000), + features: ['Dashboard Access', 'API Integration', 'Premium Support', 'Custom Branding'], +}; + +// Pasar datos a la plantilla vía variables de entorno o archivos +await php.writeFile('/template-data.json', JSON.stringify(templateData)); + +const result = await php.runStream({ + code: ``, +}); + +console.log(await result.stdoutText); +// Ahora tienes HTML renderizado que puede enviarse por email o guardarse +``` + + + +### Demo 6: Ejecución de código en tiempo real y streaming + + + +Procesa la salida de PHP conforme se genera: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +await php.writeFile( + '/stream-demo.php', + `` +); + +// Ejecutar script PHP +const streamedResponse = await php.runStream({ + scriptPath: '/stream-demo.php', +}); + +streamedResponse.stdout.pipeTo( + new WritableStream({ + write(chunk) { + console.log(chunk); + }, + }) +); +``` + + + +## Patrones de integración + + + +### Patrón 1: Middleware Express.js + + + +Integra procesamiento PHP en una aplicación Express.js: + +```TypeScript +import express from 'express'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const app = express(); +const php = new PHP(await loadNodeRuntime('8.3')); + +// Middleware de ejecución PHP +app.use('/php', async (req, res, next) => { + try { + const phpScript = req.query.script || 'index.php'; + const result = await php.runStream({ + scriptPath: `/www/${phpScript}`, + env: { + REQUEST_METHOD: req.method, + QUERY_STRING: new URLSearchParams( + req.query as Record + ).toString(), + REQUEST_URI: req.url, + }, + }); + + res.send(await result.stdoutText); + } catch (error) { + next(error); + } +}); + +app.listen(3000, () => { + console.log('Server with PHP support running on port 3000'); +}); +``` + + + +### Patrón 2: Pruebas automatizadas + + + +Crea pruebas automatizadas para código PHP: + +```TypeScript +import { describe, it, expect, beforeAll } from '@jest/globals'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +describe('PHP Functions', () => { + let php: PHP; + + beforeAll(async () => { + php = new PHP(await loadNodeRuntime('8.3')); + }); + + it('should calculate sum correctly', async () => { + const result = await php.run({ + code: ``, + }); + + expect(result.text).toBe('8'); + }); + + it('should handle JSON operations', async () => { + const input = { name: 'Test', value: 42 }; + const result = await php.run({ + code: ` $input, + 'doubled' => $input['value'] * 2 + ]; + echo json_encode($output); + ?>`, + }); + + const output = JSON.parse(result.text); + expect(output.doubled).toBe(84); + }); +}); +``` + + + +### Patrón 3: Integración con herramientas de construcción + + + +Usa en scripts de construcción con otras herramientas Node.js: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; +import fs from 'fs/promises'; + +async function generateDocumentation() { + const php = new PHP(await loadNodeRuntime('8.3')); + + // Crear directorio de salida + php.mkdir('/output'); + + // Generar documentación + const result = await php.runStream({ + code: ``, + }); + + console.log(await result.stdoutText); + + // Extraer documentación generada de vuelta al sistema de archivos Node.js + await fs.mkdir('./docs', { recursive: true }); + const summaryContent = await php.readFileAsText('/output/summary.md'); + await fs.writeFile('./docs/summary.md', summaryContent); + + console.log('Documentation saved to ./docs/summary.md'); +} + +generateDocumentation().catch(console.error); +``` + + + +## Características avanzadas + + + +### Trabajando con variables de entorno + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +const result = await php.runStream({ + code: '', + env: { + CUSTOM_VAR: 'Hello from Node.js!', + }, +}); + +console.log(await result.stdoutText); +``` + + + +### Manejo de errores + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +try { + const result = await php.runStream({ + code: '', + }); + + const stdout = await result.stdoutText; + const stderr = await result.stderrText; + + console.log('stdout:', stdout); + console.log('stderr:', stderr); + + if (stderr) { + console.error('PHP produced errors:', stderr); + } +} catch (error: any) { + console.error('JavaScript Error:', error.message); +} +``` + + + +## Consideraciones de rendimiento + + + + + + +- **Reutiliza instancias PHP**: Crear una nueva instancia PHP es costoso. Reutiliza la misma instancia cuando sea posible. +- **Operaciones por lotes**: Agrupa múltiples operaciones de archivos juntas en lugar de ejecutar scripts separados. +- **Gestión de memoria**: Los archivos grandes pueden impactar el rendimiento. Considera streaming para grandes conjuntos de datos. +- **Caché**: Almacena en caché scripts PHP compilados y datos accedidos frecuentemente. diff --git a/packages/docs/site/i18n/fr/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md b/packages/docs/site/i18n/fr/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md new file mode 100644 index 0000000000..623c5b9fb7 --- /dev/null +++ b/packages/docs/site/i18n/fr/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md @@ -0,0 +1,661 @@ +--- +title: php-wasm/node +slug: /developers/local-development/php-wasm-node +description: WordPress Playground apporte PHP propulsé par WebAssembly à Node.js pour l'exécution côté serveur, le traitement de données et les tests sans installation native. +--- + + + +# Utiliser WordPress Playground dans Node.js + + + +En tant que projet WebAssembly, vous pouvez aussi utiliser WordPress Playground dans Node.js. + + + +Si vous avez besoin d'un contrôle bas niveau sur la build WebAssembly de PHP, consultez le [paquet @php-wasm/node](https://npmjs.org/@php-wasm/node) qui fournit l'environnement d'exécution PHP WebAssembly. Ce paquet est au cœur de tous les outils WordPress Playground pour Node.js. + + + +Consultez la [liste complète](/api/node) des classes, fonctions, interfaces et alias de types. + + + +## PHP WebAssembly pour Node.js + + + +Ce paquet fournit les exécutables PHP WebAssembly et l'API JavaScript optimisée pour Node.js. Il utilise directement le système de fichiers hôte et peut accéder au réseau si vous branchez un proxy WS personnalisé. + + + +### Utilisation de base + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); +const output = await php.runStream({ + code: '', +}); +console.log(await output.stdoutText); +``` + + + +## Cas d'usage + + + + + + + +Exécutez PHP dans Node.js sans installation native de PHP. Cela permet au développeur de produire les solutions suivantes : + +- Tâches CI/CD et outils de développement. +- Support pour l'éducation et les workflows WordPress : didacticiels interactifs, sandboxes et défis de code. +- Génération de contenu et prototypage du comportement serveur. +- Rendu HTML via des templates PHP et création rapide d'endpoints d'API simulés pour simuler des requêtes. + + + +## Démonstrations pratiques + + + +Nous listerons quelques exemples utilisant le paquet PHP-WASM. + + + +### Démo 1 : Opérations sur le système de fichiers + + + +Exécutez des scripts PHP qui interagissent avec le système de fichiers : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create directory structure +php.mkdir('/app/data'); + +// Write configuration file +await php.writeFile( + '/app/config.json', + JSON.stringify({ + app: 'MyApp', + version: '1.0.0', + debug: true, + }) +); + +// Create and run PHP script that reads the config +await php.writeFile( + '/app/index.php', + `` +); + +const result = await php.runStream({ scriptPath: '/app/index.php' }); +console.log(await result.stdoutText); +``` + + + +### Démo 2 : Opérations SQLite + + + +Utilisez l'extension SQLite de PHP pour le stockage des données : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create directory for database +php.mkdir('/data'); + +// Create database, insert data, and query +const result = await php.runStream({ + code: `exec('CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +)'); + +// Insert sample data +$stmt = $db->prepare('INSERT INTO users (name, email) VALUES (?, ?)'); +$users = [ + ['Alice Johnson', 'alice@example.com'], + ['Bob Smith', 'bob@example.com'], + ['Charlie Davis', 'charlie@example.com'] +]; + +foreach ($users as $user) { + $stmt->bindValue(1, $user[0]); + $stmt->bindValue(2, $user[1]); + $stmt->execute(); +} + +// Query data +echo "All Users:\\n"; +echo str_repeat('-', 50) . "\\n"; +$results = $db->query('SELECT * FROM users ORDER BY name'); +while ($row = $results->fetchArray(SQLITE3_ASSOC)) { + echo "ID: {$row['id']} | {$row['name']} ({$row['email']})\\n"; +} + +$db->close(); +?>`, +}); + +console.log(await result.stdoutText); + +// Database file persists in the virtual file system +const dbExists = await php.fileExists('/data/app.db'); +console.log('\nDatabase persisted:', dbExists); +``` + + + +### Démo 3 : Traitement de fichiers téléchargés (archives ZIP) + + + +Traitez des fichiers ZIP avec l'extension Libzip de PHP : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create sample files +php.mkdir('/uploads'); +await php.writeFile('/uploads/readme.txt', 'This is a sample text file'); +await php.writeFile('/uploads/data.json', JSON.stringify({ name: 'Test', version: '1.0' })); + +// Create, process, and extract ZIP archive +const result = await php.runStream({ + code: `open('/uploads/archive.zip', ZipArchive::CREATE); +$zip->addFromString('readme.txt', file_get_contents('/uploads/readme.txt')); +$zip->addFromString('data.json', file_get_contents('/uploads/data.json')); +$zip->addFromString('info.txt', 'Created with PHP WASM'); +$zip->close(); + +echo "ZIP archive created successfully\\n\\n"; + +// Read and display archive contents +$zip->open('/uploads/archive.zip'); +echo "Archive Contents:\\n"; +echo str_repeat('=', 50) . "\\n"; + +for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + $size = round($stat['size'] / 1024, 2); + echo sprintf("%-40s %10s KB\\n", $stat['name'], $size); +} + +// Extract files +$zip->extractTo('/uploads/extracted/'); +$zip->close(); + +echo "\\nExtracted successfully to /uploads/extracted/\\n"; + +// List extracted files +echo "\\nExtracted Files:\\n"; +$files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator('/uploads/extracted/') +); +foreach ($files as $file) { + if ($file->isFile()) { + echo " " . $file->getPathname() . "\\n"; + } +} +?>`, +}); + +console.log(await result.stdoutText); +``` + + + +### Démo 4 : Modèle requête/réponse HTTP + + + +Simulez le comportement d'un serveur web avec des gestionnaires de requêtes : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Set up a simple API endpoint +await php.mkdir('/www/api'); +await php.writeFile( + '/www/api/users.php', + ` [ + ['id' => 1, 'name' => 'John Doe'], + ['id' => 2, 'name' => 'Jane Smith'] + ] + ]); + break; + + case 'POST': + $name = $input['name'] ?? 'Unknown'; + echo json_encode([ + 'success' => true, + 'user' => [ + 'id' => 3, + 'name' => $name + ], + 'message' => "User $name created" + ]); + break; + + default: + http_response_code(405); + echo json_encode(['error' => 'Method not allowed']); +} +?>` +); + +// Make GET request +const getResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'GET', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, +}); +console.log('GET Response:', await getResponse.stdoutText); + +// Make POST request +const postResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'POST', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, + body: JSON.stringify({ name: 'Alice Wonder' }), +}); +console.log('\\nPOST Response:', await postResponse.stdoutText); +``` + + + +### Démo 5 : Moteur de rendu de templates + + + +Utilisez PHP comme moteur de templates pour du contenu dynamique : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Create templates directory +php.mkdir('/templates'); + +// Create template +await php.writeFile( + '/templates/email.php', + ` + + + + + +
+

Welcome, !

+
+
+

Thank you for registering with .

+

Your account details:

+
    +
  • Email:
  • +
  • Member Since:
  • +
+

You now have access to the following features:

+
    + +
  • + +
+
+ + +` +); + +// Render template with data +const templateData = { + name: 'Priya Sharma', + email: 'priya@example.com', + appName: 'MyAwesomeApp', + timestamp: Math.floor(Date.now() / 1000), + features: ['Dashboard Access', 'API Integration', 'Premium Support', 'Custom Branding'], +}; + +// Pass data to template via environment variables or files +await php.writeFile('/template-data.json', JSON.stringify(templateData)); + +const result = await php.runStream({ + code: ``, +}); + +console.log(await result.stdoutText); +// Now you have rendered HTML that can be sent via email or saved +``` + + + +### Démo 6 : Exécution en temps réel et streaming + + + +Traitez la sortie PHP au fur et à mesure : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +await php.writeFile( + '/stream-demo.php', + `` +); + +// Run PHP script +const streamedResponse = await php.runStream({ + scriptPath: '/stream-demo.php', +}); + +streamedResponse.stdout.pipeTo( + new WritableStream({ + write(chunk) { + console.log(chunk); + }, + }) +); +``` + + + +## Modèles d'intégration + + + +### Modèle 1 : Middleware Express.js + + + +Intégrez l'exécution PHP dans une application Express.js : + +```TypeScript +import express from 'express'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const app = express(); +const php = new PHP(await loadNodeRuntime('8.3')); + +// PHP execution middleware +app.use('/php', async (req, res, next) => { + try { + const phpScript = req.query.script || 'index.php'; + const result = await php.runStream({ + scriptPath: `/www/${phpScript}`, + env: { + REQUEST_METHOD: req.method, + QUERY_STRING: new URLSearchParams( + req.query as Record + ).toString(), + REQUEST_URI: req.url, + }, + }); + + res.send(await result.stdoutText); + } catch (error) { + next(error); + } +}); + +app.listen(3000, () => { + console.log('Server with PHP support running on port 3000'); +}); +``` + + + +### Modèle 2 : Tests automatisés + + + +Créez des tests automatisés pour du code PHP : + +```TypeScript +import { describe, it, expect, beforeAll } from '@jest/globals'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +describe('PHP Functions', () => { + let php: PHP; + + beforeAll(async () => { + php = new PHP(await loadNodeRuntime('8.3')); + }); + + it('should calculate sum correctly', async () => { + const result = await php.run({ + code: ``, + }); + + expect(result.text).toBe('8'); + }); + + it('should handle JSON operations', async () => { + const input = { name: 'Test', value: 42 }; + const result = await php.run({ + code: ` $input, + 'doubled' => $input['value'] * 2 + ]; + echo json_encode($output); + ?>`, + }); + + const output = JSON.parse(result.text); + expect(output.doubled).toBe(84); + }); +}); +``` + + + +### Modèle 3 : Intégration aux outils de build + + + +Utilisez-le dans des scripts de build avec d'autres outils Node.js : + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; +import fs from 'fs/promises'; + +async function generateDocumentation() { + const php = new PHP(await loadNodeRuntime('8.3')); + + // Create output directory + php.mkdir('/output'); + + // Generate documentation + const result = await php.runStream({ + code: ``, + }); + + console.log(await result.stdoutText); + + // Extract generated docs back to Node.js file system + await fs.mkdir('./docs', { recursive: true }); + const summaryContent = await php.readFileAsText('/output/summary.md'); + await fs.writeFile('./docs/summary.md', summaryContent); + + console.log('Documentation saved to ./docs/summary.md'); +} + +generateDocumentation().catch(console.error); +``` + + + +## Fonctionnalités avancées + + + +### Travailler avec des variables d'environnement + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +const result = await php.runStream({ + code: '', + env: { + CUSTOM_VAR: 'Hello from Node.js!', + }, +}); + +console.log(await result.stdoutText); +``` + + + +### Gestion des erreurs + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +try { + const result = await php.runStream({ + code: '', + }); + + const stdout = await result.stdoutText; + const stderr = await result.stderrText; + + console.log('stdout:', stdout); + console.log('stderr:', stderr); + + if (stderr) { + console.error('PHP produced errors:', stderr); + } +} catch (error: any) { + console.error('JavaScript Error:', error.message); +} +``` + + + +## Considérations de performance + + + + + + +- **Réutiliser les instances PHP** : créer une nouvelle instance PHP est coûteux. Réutilisez la même instance lorsque c'est possible. +- **Regrouper les opérations** : groupez plusieurs opérations de fichiers plutôt que d'exécuter des scripts séparés. +- **Gestion de la mémoire** : les fichiers volumineux peuvent impacter les performances. Envisagez le streaming pour de grands jeux de données. +- **Mise en cache** : mettez en cache les scripts PHP compilés et les données souvent consultées. diff --git a/packages/docs/site/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md b/packages/docs/site/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md index 74280541d4..cbe46564d7 100644 --- a/packages/docs/site/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md +++ b/packages/docs/site/i18n/pt-BR/docusaurus-plugin-content-docs/current/developers/05-local-development/03-php-wasm-node.md @@ -1,6 +1,7 @@ --- title: php-wasm/node slug: /developers/local-development/php-wasm-node +description: WordPress Playground traz PHP com WebAssembly para Node.js para execução do lado do servidor, processamento de dados e testes sem instalação nativa. --- @@ -11,20 +12,650 @@ slug: /developers/local-development/php-wasm-node Como um projeto WebAssembly, você também pode usar o WordPress Playground no Node.js. - + -Se você precisa de controle de baixo nível sobre a compilação WebAssembly do PHP subjacente, dê uma olhada no pacote [`@php-wasm/node`](https://npmjs.org/@php-wasm/node) que inclui o runtime WebAssembly do PHP. Este pacote está no centro de todas as ferramentas WordPress Playground para Node.js. - - - -:::info **Referência da API** +Se você precisa de controle de baixo nível sobre a compilação WebAssembly do PHP subjacente, dê uma olhada no [pacote @php-wasm/node](https://npmjs.org/@php-wasm/node) que inclui o runtime WebAssembly do PHP. Este pacote está no centro de todas as ferramentas WordPress Playground para Node.js. Consulte a [lista completa](/api/node) de Classes, Funções, Interfaces e Aliases de Tipo. -::: + + +## WebAssembly PHP para Node.js + + + +Este pacote inclui binários WebAssembly do PHP e a API JavaScript otimizada para Node.js. Ele usa o sistema de arquivos do host diretamente e pode acessar a rede se você conectar um proxy WS customizado. + + + +### Uso básico + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); +const output = await php.runStream({ + code: '', +}); +console.log(await output.stdoutText); +``` + + + +## Casos de uso + + + + + + + +Execute PHP dentro do Node.js sem instalação nativa de PHP. Permite ao desenvolvedor produzir as seguintes soluções: + +- Tarefas de CI/CD e ferramentas de desenvolvimento. +- Suporte à educação e fluxos de trabalho WordPress: potencialize tutoriais interativos, sandboxes e desafios de código. +- Gerar conteúdo e prototipar comportamento de servidor. +- Renderizar HTML usando templates PHP e levantar rapidamente endpoints de API simulados para simular requisições. + + + +## Demos práticas + + + +Listaremos alguns exemplos usando o pacote PHP-WASM. + + + +### Demo 1: Operações no sistema de arquivos + + + +Execute scripts PHP que interagem com o sistema de arquivos: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Criar estrutura de diretórios +php.mkdir('/app/data'); + +// Escrever arquivo de configuração +await php.writeFile( + '/app/config.json', + JSON.stringify({ + app: 'MyApp', + version: '1.0.0', + debug: true, + }) +); + +// Criar e executar script PHP que lê a configuração +await php.writeFile( + '/app/index.php', + `` +); + +const result = await php.runStream({ scriptPath: '/app/index.php' }); +console.log(await result.stdoutText); +``` + + + +### Demo 2: Operações de banco de dados SQLite + + + +Use a extensão SQLite do PHP para armazenamento de dados: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Criar diretório para o banco de dados +php.mkdir('/data'); + +// Criar banco de dados, inserir dados e consultar +const result = await php.runStream({ + code: `exec('CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT UNIQUE NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +)'); + +// Inserir dados de exemplo +$stmt = $db->prepare('INSERT INTO users (name, email) VALUES (?, ?)'); +$users = [ + ['Alice Johnson', 'alice@example.com'], + ['Bob Smith', 'bob@example.com'], + ['Charlie Davis', 'charlie@example.com'] +]; + +foreach ($users as $user) { + $stmt->bindValue(1, $user[0]); + $stmt->bindValue(2, $user[1]); + $stmt->execute(); +} + +// Consultar dados +echo "All Users:\\n"; +echo str_repeat('-', 50) . "\\n"; +$results = $db->query('SELECT * FROM users ORDER BY name'); +while ($row = $results->fetchArray(SQLITE3_ASSOC)) { + echo "ID: {$row['id']} | {$row['name']} ({$row['email']})\\n"; +} + +$db->close(); +?>`, +}); + +console.log(await result.stdoutText); + +// Arquivo do banco de dados persiste no sistema de arquivos virtual +const dbExists = await php.fileExists('/data/app.db'); +console.log('\nDatabase persisted:', dbExists); +``` + + + +### Demo 3: Processamento de arquivos enviados (arquivos ZIP) + + + +Processe arquivos ZIP usando a extensão Libzip do PHP: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Criar arquivos de exemplo +php.mkdir('/uploads'); +await php.writeFile('/uploads/readme.txt', 'This is a sample text file'); +await php.writeFile('/uploads/data.json', JSON.stringify({ name: 'Test', version: '1.0' })); + +// Criar, processar e extrair arquivo ZIP +const result = await php.runStream({ + code: `open('/uploads/archive.zip', ZipArchive::CREATE); +$zip->addFromString('readme.txt', file_get_contents('/uploads/readme.txt')); +$zip->addFromString('data.json', file_get_contents('/uploads/data.json')); +$zip->addFromString('info.txt', 'Created with PHP WASM'); +$zip->close(); + +echo "ZIP archive created successfully\\n\\n"; + +// Ler e exibir conteúdo do arquivo +$zip->open('/uploads/archive.zip'); +echo "Archive Contents:\\n"; +echo str_repeat('=', 50) . "\\n"; + +for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + $size = round($stat['size'] / 1024, 2); + echo sprintf("%-40s %10s KB\\n", $stat['name'], $size); +} + +// Extrair arquivos +$zip->extractTo('/uploads/extracted/'); +$zip->close(); + +echo "\\nExtracted successfully to /uploads/extracted/\\n"; + +// Listar arquivos extraídos +echo "\\nExtracted Files:\\n"; +$files = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator('/uploads/extracted/') +); +foreach ($files as $file) { + if ($file->isFile()) { + echo " " . $file->getPathname() . "\\n"; + } +} +?>`, +}); + +console.log(await result.stdoutText); +``` + + + +### Demo 4: Padrão de requisição/resposta HTTP + + + +Simule comportamento de servidor web com manipuladores de requisição: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Configurar um endpoint de API simples +await php.mkdir('/www/api'); +await php.writeFile( + '/www/api/users.php', + ` [ + ['id' => 1, 'name' => 'John Doe'], + ['id' => 2, 'name' => 'Jane Smith'] + ] + ]); + break; + + case 'POST': + $name = $input['name'] ?? 'Unknown'; + echo json_encode([ + 'success' => true, + 'user' => [ + 'id' => 3, + 'name' => $name + ], + 'message' => "User $name created" + ]); + break; + + default: + http_response_code(405); + echo json_encode(['error' => 'Method not allowed']); +} +?>` +); + +// Fazer requisição GET +const getResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'GET', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, +}); +console.log('GET Response:', await getResponse.stdoutText); + +// Fazer requisição POST +const postResponse = await php.runStream({ + scriptPath: '/www/api/users.php', + env: { + REQUEST_METHOD: 'POST', + SERVER_NAME: 'localhost', + SERVER_PORT: '80', + }, + body: JSON.stringify({ name: 'Alice Wonder' }), +}); +console.log('\\nPOST Response:', await postResponse.stdoutText); +``` + + + +### Demo 5: Motor de renderização de templates + + + +Use PHP como um motor de templates para conteúdo dinâmico: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +// Criar diretório de templates +php.mkdir('/templates'); + +// Criar template +await php.writeFile( + '/templates/email.php', + ` + + + + + +
+

Welcome, !

+
+
+

Thank you for registering with .

+

Your account details:

+
    +
  • Email:
  • +
  • Member Since:
  • +
+

You now have access to the following features:

+
    + +
  • + +
+
+ + +` +); + +// Renderizar template com dados +const templateData = { + name: 'Priya Sharma', + email: 'priya@example.com', + appName: 'MyAwesomeApp', + timestamp: Math.floor(Date.now() / 1000), + features: ['Dashboard Access', 'API Integration', 'Premium Support', 'Custom Branding'], +}; + +// Passar dados para o template via variáveis de ambiente ou arquivos +await php.writeFile('/template-data.json', JSON.stringify(templateData)); + +const result = await php.runStream({ + code: ``, +}); + +console.log(await result.stdoutText); +// Agora você tem HTML renderizado que pode ser enviado por email ou salvo +``` + + + +### Demo 6: Execução de código em tempo real e streaming + + + +Processe a saída do PHP conforme ela é gerada: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +await php.writeFile( + '/stream-demo.php', + `` +); + +// Executar script PHP +const streamedResponse = await php.runStream({ + scriptPath: '/stream-demo.php', +}); + +streamedResponse.stdout.pipeTo( + new WritableStream({ + write(chunk) { + console.log(chunk); + }, + }) +); +``` + + + +## Padrões de integração + + + +### Padrão 1: Middleware Express.js + + + +Integre processamento PHP em uma aplicação Express.js: + +```TypeScript +import express from 'express'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const app = express(); +const php = new PHP(await loadNodeRuntime('8.3')); + +// Middleware de execução PHP +app.use('/php', async (req, res, next) => { + try { + const phpScript = req.query.script || 'index.php'; + const result = await php.runStream({ + scriptPath: `/www/${phpScript}`, + env: { + REQUEST_METHOD: req.method, + QUERY_STRING: new URLSearchParams( + req.query as Record + ).toString(), + REQUEST_URI: req.url, + }, + }); + + res.send(await result.stdoutText); + } catch (error) { + next(error); + } +}); + +app.listen(3000, () => { + console.log('Server with PHP support running on port 3000'); +}); +``` + + + +### Padrão 2: Testes automatizados + + + +Crie testes automatizados para código PHP: + +```TypeScript +import { describe, it, expect, beforeAll } from '@jest/globals'; +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +describe('PHP Functions', () => { + let php: PHP; + + beforeAll(async () => { + php = new PHP(await loadNodeRuntime('8.3')); + }); + + it('should calculate sum correctly', async () => { + const result = await php.run({ + code: ``, + }); + + expect(result.text).toBe('8'); + }); + + it('should handle JSON operations', async () => { + const input = { name: 'Test', value: 42 }; + const result = await php.run({ + code: ` $input, + 'doubled' => $input['value'] * 2 + ]; + echo json_encode($output); + ?>`, + }); + + const output = JSON.parse(result.text); + expect(output.doubled).toBe(84); + }); +}); +``` + + + +### Padrão 3: Integração com ferramentas de build + + + +Use em scripts de build com outras ferramentas Node.js: + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; +import fs from 'fs/promises'; + +async function generateDocumentation() { + const php = new PHP(await loadNodeRuntime('8.3')); + + // Criar diretório de saída + php.mkdir('/output'); + + // Gerar documentação + const result = await php.runStream({ + code: ``, + }); + + console.log(await result.stdoutText); + + // Extrair documentação gerada de volta para o sistema de arquivos Node.js + await fs.mkdir('./docs', { recursive: true }); + const summaryContent = await php.readFileAsText('/output/summary.md'); + await fs.writeFile('./docs/summary.md', summaryContent); + + console.log('Documentation saved to ./docs/summary.md'); +} + +generateDocumentation().catch(console.error); +``` + + + +## Recursos avançados + + + +### Trabalhando com variáveis de ambiente + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +const result = await php.runStream({ + code: '', + env: { + CUSTOM_VAR: 'Hello from Node.js!', + }, +}); + +console.log(await result.stdoutText); +``` + + + +### Tratamento de erros + +```javascript +import { PHP } from '@php-wasm/universal'; +import { loadNodeRuntime } from '@php-wasm/node'; + +const php = new PHP(await loadNodeRuntime('8.3')); + +try { + const result = await php.runStream({ + code: '', + }); + + const stdout = await result.stdoutText; + const stderr = await result.stderrText; + + console.log('stdout:', stdout); + console.log('stderr:', stderr); + + if (stderr) { + console.error('PHP produced errors:', stderr); + } +} catch (error: any) { + console.error('JavaScript Error:', error.message); +} +``` + + + +## Considerações de desempenho -import PHPWASMNode from '@php-wasm/node/\README.md'; + + + + - +- **Reutilize instâncias PHP**: Criar uma nova instância PHP é custoso. Reutilize a mesma instância quando possível. +- **Operações em lote**: Agrupe múltiplas operações de arquivo juntas em vez de executar scripts separados. +- **Gerenciamento de memória**: Arquivos grandes podem impactar o desempenho. Considere streaming para grandes conjuntos de dados. +- **Cache**: Faça cache de scripts PHP compilados e dados acessados frequentemente.