স্কিপ করে মূল কন্টেন্ট এ যান

Node.js-এ ওয়ার্ডপ্রেস প্লেগ্রাউন্ড ব্যবহার

একটি WebAssembly প্রজেক্ট হিসেবে আপনি Node.js-এও ওয়ার্ডপ্রেস প্লেগ্রাউন্ড ব্যবহার করতে পারেন।

আন্ডারলায়িং WebAssembly PHP রানটাইমের ওপর যদি আপনার সরাসরি নিয়ন্ত্রণের প্রয়োজন হয়, তবে @php-wasm/node প্যাকেজটি দেখতে পারেন। এটি ওয়ার্ডপ্রেস প্লেগ্রাউন্ডের বিভিন্ন টুলে ব্যবহৃত Node.js লোডার এবং রানটাইম ইন্টিগ্রেশন সরবরাহ করে। কম্পাইল করা বাইনারিগুলো @php-wasm/node-8-4-এর মতো নির্দিষ্ট ভার্সনের প্যাকেজে প্রকাশিত হয়।

@php-wasm/universal, Node.js ও ওয়েব অ্যাডাপ্টার এবং নির্দিষ্ট ভার্সনের প্যাকেজগুলো কীভাবে একসাথে কাজ করে তা জানতে PHP.wasm packages দেখুন। ওই পেজে আরও কম ডিপেন্ডেন্সি ফুটপ্রিন্টসহ লোয়ার-লেভেল, একক-ভার্সন সেটআপ সম্পর্কেও আলোচনা করা হয়েছে।

Classes, Functions, Interfaces এবং Type Aliases-এর সম্পূর্ণ তালিকা দেখুন।

Node.js-এর জন্য WebAssembly PHP​

একসাথে @php-wasm/node এবং একটি ভার্সন-নির্দিষ্ট প্যাকেজ Node.js-এর জন্য অপ্টিমাইজ করা কম্পাইল্ড PHP রানটাইম ও JavaScript API প্রদান করে। PHP একটি ইন-মেমরি ফাইলসিস্টেম নিয়ে শুরু হয়; হোস্ট পাথ মাউন্ট করতে Node.js ফাইলসিস্টেম হেল্পার ব্যবহার করুন। আপনি যদি একটি কাস্টম WebSocket-to-TCP প্রক্সি যুক্ত করেন তবে রানটাইম নেটওয়ার্কও অ্যাক্সেস করতে পারে।

বেসিক ব্যবহার​

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: '<?php phpinfo(); ?>',
});
console.log(await output.stdoutText);

সরাসরি একটি নির্দিষ্ট PHP ভার্সন লোড করা​

যদি ইনস্টলেশনের আকার গুরুত্বপূর্ণ হয় এবং আপনার শুধুমাত্র শেয়ার্ড, লো-লেভেল PHP API প্রয়োজন হয়, তবে আপনি @php-wasm/node বাদ দিয়ে শুধুমাত্র একটি Node.js বিল্ড ইনস্টল করতে পারেন:

npm install @php-wasm/universal @php-wasm/node-8-4

এই পদ্ধতি নেটওয়ার্কিং, ফাইল লকিং এবং এক্সটেনশন লোডিংয়ের মতো Node.js-নির্দিষ্ট সেটআপ এড়িয়ে চলে। সম্পূর্ণ উদাহরণ এবং ট্রেডঅফ দেখতে Load one PHP version directly দেখুন।

PHP এক্সটেনশন লোড করা​

PHP শুরু হওয়ার আগে অপশনাল এক্সটেনশন সক্রিয় করতে extensions লোডার অপশন ব্যবহার করুন:

import { PHP } from '@php-wasm/universal';
import { loadNodeRuntime } from '@php-wasm/node';

const php = new PHP(
await loadNodeRuntime('8.4', {
extensions: ['intl', 'redis', 'memcached', { name: 'xdebug', options: { ideKey: 'PLAYGROUND' } }],
})
);

একই অ্যারে ম্যানিফেস্ট থেকে এক্সটার্নাল JSPI .so আর্টিফ্যাক্ট লোড করতে পারে:

const php = new PHP(
await loadNodeRuntime('8.4', {
extensions: [
{
source: {
format: 'manifest',
manifestUrl: './dist/wp_mysql_parser/manifest.json',
},
},
],
})
);

এক্সটার্নাল এক্সটেনশনের জন্য JSPI প্রয়োজন। Asyncify সাপোর্ট শুধুমাত্র PHP.wasm প্যাকেজের সাথে আসা বান্ডেলড এক্সটেনশনগুলোর মধ্যেই সীমাবদ্ধ।

ম্যানিফেস্ট ফরম্যাট, ব্রাউজারের ব্যবহার, সাইডকার ফাইল এবং সামঞ্জস্যের নোটগুলোর জন্য Loading PHP extensions দেখুন।

ব্যবহারের ক্ষেত্র (Use cases)​

নেটিভ PHP ইনস্টল ছাড়াই Node.js-এর ভেতর PHP রান করুন। এটি ডেভেলপারদের নিচের সমাধানগুলো তৈরি করতে সক্ষম করে:

  • সিআই/সিডি (CI/CD) জব এবং ডেভেলপার টুলিং।
  • শিক্ষামূলক ও ওয়ার্ডপ্রেস ওয়ার্কফ্লোতে সহায়তা: ইন্টারেক্টিভ টিউটোরিয়াল, স্যান্ডবক্স এবং কোডিং চ্যালেঞ্জ পরিচালনা করা।
  • কনটেন্ট তৈরি এবং সার্ভার আচরণের প্রোটোটাইপ প্রস্তুত করা।
  • PHP টেমপ্লেট ব্যবহার করে HTML রেন্ডার করা এবং রিকোয়েস্ট সিমুলেট করতে দ্রুত মক API এন্ডপয়েন্ট তৈরি করা।

ব্যবহারিক ডেমো (Practical demos)​

আমরা PHP-WASM প্যাকেজ ব্যবহার করে কিছু উদাহরণ তুলে ধরব।

ডেমো ১: ফাইল সিস্টেম অপারেশন (Demo 1: File system operations)​

ফাইল সিস্টেমের সাথে ইন্টার‍্যাক্ট করে এমন PHP স্ক্রিপ্ট চালান:

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',
`<?php
$config = json_decode(file_get_contents('/app/config.json'), true);
echo "Application: " . $config['app'] . "\\n";
echo "Version: " . $config['version'] . "\\n";
echo "Debug Mode: " . ($config['debug'] ? 'ON' : 'OFF') . "\\n";

// List all files
echo "\\nFiles in /app:\\n";
foreach (scandir('/app') as $file) {
if ($file !== '.' && $file !== '..') {
echo " - $file\\n";
}
}
?>`
);

const result = await php.runStream({ scriptPath: '/app/index.php' });
console.log(await result.stdoutText);

ডেমো ২: SQLite ডেটাবেস অপারেশন (Demo 2: SQLite database operations)​

ডেটা সংরক্ষণের জন্য PHP-এর SQLite এক্সটেনশন ব্যবহার করুন:

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: `<?php
// Create/connect to SQLite database
$db = new SQLite3('/data/app.db');

// Create table
$db->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);

ডেমো ৩: আপলোড করা ফাইল প্রসেসিং (ZIP আর্কাইভ)​

PHP-এর Libzip এক্সটেনশন ব্যবহার করে ZIP ফাইল প্রসেস করুন:

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: `<?php
// Create ZIP archive
$zip = new ZipArchive();
$zip->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);

ডেমো ৪: HTTP রিকোয়েস্ট/রেসপন্স প্যাটার্ন​

রিকোয়েস্ট হ্যান্ডলারের সাহায্যে ওয়েব সার্ভারের আচরণ সিমুলেট করুন:

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',
`<?php
header('Content-Type: application/json');

// Parse request
$method = $_SERVER['REQUEST_METHOD'];
$input = json_decode(file_get_contents('php://input'), true);

// Simple routing
switch ($method) {
case 'GET':
echo json_encode([
'users' => [
['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);

ডেমো ৫: টেমপ্লেট রেন্ডারিং ইঞ্জিন​

ডাইনামিক কনটেন্টের জন্য টেমপ্লেটিং ইঞ্জিন হিসেবে PHP ব্যবহার করুন:

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',
`<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.header { background: #4CAF50; color: white; padding: 20px; }
.content { padding: 20px; }
.footer { background: #f1f1f1; padding: 10px; text-align: center; }
</style>
</head>
<body>
<div class="header">
<h1>Welcome, <?= htmlspecialchars($name) ?>!</h1>
</div>
<div class="content">
<p>Thank you for registering with <?= $appName ?>.</p>
<p>Your account details:</p>
<ul>
<li><strong>Email:</strong> <?= htmlspecialchars($email) ?></li>
<li><strong>Member Since:</strong> <?= date('F j, Y', $timestamp) ?></li>
</ul>
<p>You now have access to the following features:</p>
<ul>
<?php foreach ($features as $feature): ?>
<li><?= htmlspecialchars($feature) ?></li>
<?php endforeach; ?>
</ul>
</div>
<div class="footer">
<p>&copy; <?= date('Y') ?> <?= $appName ?>. All rights reserved.</p>
</div>
</body>
</html>`
);

// 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: `<?php
$data = json_decode(file_get_contents('/template-data.json'), true);
extract($data);
include '/templates/email.php';
?>`,
});

console.log(await result.stdoutText);
// Now you have rendered HTML that can be sent via email or saved

ডেমো ৬: রিয়েল-টাইম কোড এক্সিকিউশন ও স্ট্রিমিং​

PHP আউটপুট তৈরি হওয়ার সাথে সাথেই তা প্রসেস করুন:

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',
`<?php
// Simulate long-running process
echo "Starting process...\\n";
flush();

for ($i = 1; $i <= 10; $i++) {
echo "Processing item $i/10...\\n";
flush();
usleep(100000); // Sleep 100ms
}

echo "Process complete!\\n";
?>`
);

// Run PHP script
const streamedResponse = await php.runStream({
scriptPath: '/stream-demo.php',
});

streamedResponse.stdout.pipeTo(
new WritableStream({
write(chunk) {
console.log(chunk);
},
})
);

ইন্টিগ্রেশন প্যাটার্ন (Integration patterns)​

প্যাটার্ন ১: Express.js মিডলওয়্যার​

একটি Express.js অ্যাপ্লিকেশনে PHP প্রসেসিং যুক্ত করুন:

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<string, string>
).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');
});

প্যাটার্ন ২: অটোমেটেড টেস্টিং​

PHP কোডের জন্য অটোমেটেড টেস্ট তৈরি করুন:

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: `<?php
function sum($a, $b) {
return $a + $b;
}
echo sum(5, 3);
?>`,
});

expect(result.text).toBe('8');
});

it('should handle JSON operations', async () => {
const input = { name: 'Test', value: 42 };
const result = await php.run({
code: `<?php
$input = json_decode('${JSON.stringify(input)}', true);
$output = [
'received' => $input,
'doubled' => $input['value'] * 2
];
echo json_encode($output);
?>`,
});

const output = JSON.parse(result.text);
expect(output.doubled).toBe(84);
});
});

প্যাটার্ন ৩: বিল্ড টুল ইন্টিগ্রেশন​

অন্যান্য Node.js টুলের সাথে বিল্ড স্ক্রিপ্টে ব্যবহার করুন:

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: `<?php
echo "Generating documentation...\\n";

$summary = "# Generated Documentation\\n\\n";
$summary .= "Generated at: " . date('Y-m-d H:i:s') . "\\n\\n";

file_put_contents('/output/summary.md', $summary);
echo "Documentation generated successfully!\\n";
?>`,
});

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)​

এনভায়রনমেন্ট ভ্যারিয়েবল নিয়ে কাজ করা​

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: '<?php echo getenv("CUSTOM_VAR"); ?>',
env: {
CUSTOM_VAR: 'Hello from Node.js!',
},
});

console.log(await result.stdoutText);

এরর হ্যান্ডলিং (Error handling)​

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: '<?php trigger_error("Test error", E_USER_ERROR); ?>',
});

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);
}

কার্যক্ষমতা বিবেচ্য বিষয়সমূহ (Performance considerations)​

  • PHP ইনস্ট্যান্স পুনর্ব্যবহার করুন: নতুন PHP ইনস্ট্যান্স তৈরি করা ব্যয়বহুল। সম্ভব হলে একই ইনস্ট্যান্স পুনরায় ব্যবহার করুন।
  • ব্যাচ অপারেশন: আলাদা আলাদা স্ক্রিপ্ট চালানোর চেয়ে একাধিক ফাইল অপারেশনকে একসাথে গ্রুপ করুন।
  • মেমরি ব্যবস্থাপনা: বড় ফাইল পারফরম্যান্সে প্রভাব ফেলতে পারে। বড় ডেটাসেটের জন্য স্ট্রিমিং বিবেচনা করুন।
  • ক্যাশিং: কম্পাইল করা PHP স্ক্রিপ্ট এবং ঘন ঘন ব্যবহৃত ডেটা ক্যাশ করে রাখুন।