Cách làm ngắn gọn: mở playground.wordpress.net, chờ window.playgroundSites.isReady(), định nghĩa các tổ hợp phiên bản rồi gọi createNewSavedSite() cho từng tổ hợp. Sau đó dùng list(), setActiveSite() và một phép kiểm tra PHP để xác minh kết quả.
Trong tài liệu hiện tại, tên chính thức là Sites API; “Site Manager API” là cách gọi mô tả chức năng quản lý site. API này phù hợp để tạo, lưu, đổi tên, chuyển đổi và xóa site Playground. API không nhận trực tiếp plugin, theme hoặc blueprint-url; các bước đó thuộc về Blueprints hoặc JavaScript API (theo wordpress.github.io).
Bài viết dùng các chuỗi phiên bản minh họa. Hãy thay <wp-version> và <php-version> bằng phiên bản mà Playground và bài kiểm thử của bạn hỗ trợ. Không dùng một phiên bản chỉ vì nó xuất hiện trong ví dụ; phiên bản được hỗ trợ có thể thay đổi theo thời điểm.
Chọn API theo việc bạn cần làm
| Mục tiêu | Công cụ nên dùng | Kết quả |
|---|---|---|
| So sánh WordPress, PHP hoặc networking | Sites API | Nhiều site được tạo và lưu trong trình duyệt |
| Cài plugin, theme hoặc nội dung mẫu | Blueprints | Một cấu hình khởi tạo có các bước định trước |
| Khởi tạo nhiều môi trường kiểm thử độc lập | JavaScript API + Blueprints | Mỗi client hoặc iframe là một môi trường riêng |
| Đổi tên, chuyển site hoặc xóa site đã lưu | Sites API | Quản lý vòng đời site |
Nếu ma trận chỉ gồm WordPress × PHP × networking, hãy bắt đầu với Sites API. Nếu mỗi ô còn phải cài plugin, theme hoặc dữ liệu mẫu, hãy giữ phần ma trận nhưng khởi tạo từng ô bằng Blueprint và JavaScript API.
Chuẩn bị và định nghĩa ma trận
Bạn cần trình duyệt hỗ trợ JavaScript, quyền truy cập Playground và danh sách phiên bản muốn kiểm tra. Mã dưới đây chạy trong DevTools của trang Playground, không chạy trong bảng điều khiển quản trị WordPress hay trong máy chủ sản xuất.
Ví dụ sau tạo bốn tổ hợp. Các giá trị có dấu <...> là chỗ giữ chỗ bắt buộc phải thay trước khi chạy:
const matrix = [
{ wp: '<wp-version>', php: '<php-version-1>', networking: false },
{ wp: '<wp-version>', php: '<php-version-1>', networking: true },
{ wp: '<wp-version>', php: '<php-version-2>', networking: false },
{ wp: '<wp-version>', php: '<php-version-2>', networking: true },
];
Ví dụ này chỉ minh họa cách tạo ma trận, không chứng minh mọi tổ hợp đều tương thích. Trước khi chạy, hãy kiểm tra rằng các chuỗi phiên bản là phiên bản cụ thể mà Playground hỗ trợ. Dùng phiên bản cụ thể thay vì latest khi cần tái lập kết quả.
Chờ Sites API sẵn sàng
window.playgroundSites có thể chưa xuất hiện ngay sau khi trang tải. Hàm dưới đây chờ tối đa 30 giây, rồi gọi isReady(). Giới hạn thời gian giúp tránh để vòng lặp chờ chạy vô hạn nếu trang bị lỗi hoặc bị chặn lưu trữ.
async function waitForSitesAPI(timeoutMs = 30000) {
const startedAt = Date.now();
while (!window.playgroundSites) {
if (Date.now() - startedAt > timeoutMs) {
throw new Error('Không tìm thấy window.playgroundSites trong thời gian chờ.');
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
await window.playgroundSites.isReady();
return window.playgroundSites;
}
const sites = await waitForSitesAPI();
console.table(sites.list());
Chạy đoạn mã trong Console của DevTools trên chính tab Playground. Kết quả mong đợi là bảng các site hiện có. Nếu Console không cho phép await ở cấp cao nhất, bọc các lệnh trong một hàm async hoặc chạy từng đoạn sau khi API đã sẵn sàng.
Nếu nhận lỗi playgroundSites is undefined, hãy kiểm tra lại URL, chờ trang tải xong và thử lại. Nếu isReady() không hoàn tất, mở lại tab Playground trước khi tạo site; không nên tiếp tục chạy các lệnh tạo site khi ứng dụng chưa sẵn sàng.
Tạo site tuần tự từ ma trận
Đoạn mã sau dùng createNewSavedSite(slug, settings, options). Mỗi site được lưu với persistence: 'explicit', có slug riêng và không thay đổi URL trình duyệt nhờ updateUrl: false. Hãy chạy sau đoạn mã định nghĩa matrix và waitForSitesAPI().
async function createMatrixSites(matrix) {
const sites = await waitForSitesAPI();
const created = [];
for (const item of matrix) {
const slug = [
'matrix',
`wp-${item.wp.replace(/\./g, '-')}`,
`php-${item.php.replace(/\./g, '-')}`,
item.networking ? 'net-on' : 'net-off',
].join('-');
const name = `WordPress ${item.wp} / PHP ${item.php} / ${item.networking ? 'networking bật' : 'networking tắt'}`;
try {
const createdSlug = await sites.createNewSavedSite(
slug,
{
wpVersion: item.wp,
phpVersion: item.php,
networking: item.networking,
},
{
persistence: 'explicit',
updateUrl: false,
}
);
await sites.rename(name, createdSlug);
created.push({
slug: createdSlug,
name,
wp: item.wp,
php: item.php,
networking: item.networking,
status: 'created',
});
console.log(`Đã tạo: ${name}`);
} catch (error) {
created.push({
slug,
name,
wp: item.wp,
php: item.php,
networking: item.networking,
status: 'failed',
error: String(error),
});
console.error(`Không tạo được ${name}`, error);
}
}
return created;
}
const result = await createMatrixSites(matrix);
console.table(result);
console.table(window.playgroundSites.list());
Đoạn mã chạy tuần tự để mỗi lần tạo hoàn tất trước khi chuyển sang tổ hợp tiếp theo. Cách này dễ theo dõi site đang hoạt động và lỗi của từng ô hơn so với việc tạo đồng thời. Kết quả created chỉ cho biết thao tác tạo đã hoàn tất; chưa chứng minh plugin, theme hoặc chức năng ứng dụng tương thích.
Cách xác minh danh sách site
Trong kết quả của list(), hãy đối chiếu slug, tên, kiểu lưu trữ và trạng thái hoạt động theo các trường mà phiên bản API của bạn trả về. Không nên coi tên hiển thị là bằng chứng phiên bản runtime; phiên bản cần được đọc lại từ site đang hoạt động ở bước kiểm tra PHP.
Để chuyển sang một site cụ thể, thay slug dưới đây bằng slug thật trong kết quả list():
const slugToCheck = 'matrix-wp-<wp-version>-php-<php-version-1>-net-on';
await window.playgroundSites.setActiveSite(slugToCheck);
await window.playgroundSites.isReady();
console.log(window.playgroundSites.getClient());
Nếu slug không tồn tại, setActiveSite() sẽ lỗi hoặc không chuyển được site. Hãy sao chép slug từ kết quả thực tế thay vì tự đoán cách viết dấu chấm hoặc tên biến thể.
Kiểm tra phiên bản và trạng thái WordPress
Sau khi chọn site, dùng client của site đang hoạt động để chạy một đoạn PHP tối thiểu. Đoạn mã này chỉ kiểm tra WordPress có thể nạp và báo phiên bản nào; nó không kiểm tra chức năng plugin hoặc theme.
const client = window.playgroundSites.getClient();
if (!client) {
throw new Error('Site hiện tại chưa sẵn sàng.');
}
const response = await client.run({
code: `<?php
require '/wordpress/wp-load.php';
echo wp_json_encode([
'wp_version' => get_bloginfo('version'),
'php_version' => PHP_VERSION,
'site_url' => site_url(),
]);
`,
});
console.log(response);
Đối chiếu wp_version và php_version với tổ hợp bạn đang kiểm tra. Nếu giá trị không khớp, dừng việc so sánh; kiểm tra lại slug, phiên bản đã dùng khi khởi tạo và trạng thái site trước khi thử lại. Nếu site khởi động nhưng phép kiểm tra này thất bại, đó là lỗi khởi tạo hoặc nạp WordPress, không phải bằng chứng tương thích.
Với plugin hoặc theme, cần thêm kiểm tra riêng: plugin có được cài và kích hoạt không, trang hoặc lệnh chính có chạy không, log có lỗi không, và kết quả có đáp ứng tiêu chí của bài kiểm thử không. Một site khởi động thành công không thay thế cho bộ kiểm thử chức năng.
Dùng Blueprints khi cần plugin hoặc theme

createNewSavedSite() không phải nơi để truyền plugin, theme hoặc blueprint-url. Blueprints mô tả các bước khởi tạo như installPlugin, installTheme, login và runPHP (theo wordpress.github.io).
Blueprint dưới đây là mẫu hợp lệ về cấu trúc. Thay your-plugin-slug và your-theme-slug bằng slug thật từ WordPress.org trước khi sử dụng:
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"preferredVersions": {
"wp": "<wp-version>",
"php": "<php-version>"
},
"login": true,
"steps": [
{
"step": "installPlugin",
"pluginData": {
"resource": "wordpress.org/plugins",
"slug": "your-plugin-slug"
}
},
{
"step": "installTheme",
"themeData": {
"resource": "wordpress.org/themes",
"slug": "your-theme-slug"
},
"options": {
"activate": true
}
}
]
}
Đây là dữ liệu JSON, không phải lệnh chạy trực tiếp trong Console. Lưu thành tệp Blueprint hoặc truyền vào JavaScript API theo cách mà ứng dụng của bạn sử dụng. Với plugin hoặc theme riêng, dùng URL tải trực tiếp đến tệp ZIP hoặc tài nguyên được hỗ trợ; không dùng trang HTML của kho mã thay cho tệp cài đặt (theo wordpress.github.io).
Khởi tạo nhiều môi trường plugin bằng JavaScript API
Khi mỗi ô của ma trận phải có plugin riêng, hãy tạo một client Playground cho từng ô. Ví dụ dưới đây tạo iframe, khởi tạo client và chờ từng client sẵn sàng. Thay các placeholder trước khi chạy trong một trang HTML có hỗ trợ module:
<div id="playgrounds"></div>
<script type="module">
import { startPlaygroundWeb } from 'https://playground.wordpress.net/client/index.js';
const testCases = [
{ wp: '<wp-version>', php: '<php-version-1>', plugin: 'your-plugin-slug' },
{ wp: '<wp-version>', php: '<php-version-2>', plugin: 'your-plugin-slug' },
];
async function startCase(testCase) {
const iframe = document.createElement('iframe');
iframe.title = `WordPress ${testCase.wp} / PHP ${testCase.php}`;
iframe.width = '100%';
iframe.height = '600';
document.querySelector('#playgrounds').appendChild(iframe);
const client = await startPlaygroundWeb({
iframe,
remoteUrl: 'https://playground.wordpress.net/remote.html',
blueprint: {
preferredVersions: {
wp: testCase.wp,
php: testCase.php,
},
login: true,
steps: [
{
step: 'installPlugin',
pluginData: {
resource: 'wordpress.org/plugins',
slug: testCase.plugin,
},
},
],
},
});
await client.isReady();
return client;
}
const clients = [];
for (const testCase of testCases) {
clients.push(await startCase(testCase));
}
console.log(`Đã khởi tạo ${clients.length} môi trường.`);
</script>
Đoạn mã này dùng JavaScript API trực tiếp cho các iframe; các iframe không tự trở thành site do window.playgroundSites quản lý. Sites API được cung cấp ở lớp ứng dụng Playground, còn client nhúng được quản lý trong mã của bạn (theo wordpress.github.io).
Dọn dẹp và khôi phục sau thử nghiệm
Site explicit được giữ lại cho đến khi bạn xóa. Trước khi xóa, hãy lưu kết quả kiểm thử hoặc xuất thông tin cần thiết; thao tác xóa là bước dọn dẹp, không phải cách khôi phục dữ liệu.
const sitesToDelete = window.playgroundSites
.list()
.filter((site) => site.slug.startsWith('matrix-'));
for (const site of sitesToDelete) {
await window.playgroundSites.delete(site.slug);
console.log(`Đã xóa ${site.slug}`);
}
console.table(window.playgroundSites.list());
Chỉ xóa các slug mà bạn đã xác định thuộc ma trận thử nghiệm. Không dùng tiền tố chung nếu trong trình duyệt còn site cần giữ. Với thử nghiệm không cần lưu lại, cân nhắc createNewTemporarySite(); site tạm không phải lựa chọn phù hợp để lưu kết quả giữa các phiên.
Nếu một ô bị lỗi, hãy giữ lại log và slug của ô đó, sửa đúng cấu hình rồi tạo lại riêng ô bị lỗi. Không xóa toàn bộ ma trận trước khi xác định nguyên nhân. Nếu cần kết quả có thể lặp lại, khóa phiên bản WordPress/PHP và dùng release hoặc commit cố định cho tài nguyên plugin/theme.
Chẩn đoán nhanh các lỗi thường gặp
| Triệu chứng | Nguyên nhân có thể | Cách xử lý |
|---|---|---|
window.playgroundSites chưa tồn tại | Ứng dụng Playground chưa tải xong | Chạy waitForSitesAPI(), kiểm tra đúng trang và thử lại sau khi trang hoàn tất tải. |
| Không tạo được phiên bản | Chuỗi phiên bản không được runtime hỗ trợ hoặc sai định dạng | Thay placeholder bằng phiên bản cụ thể được hỗ trợ và đọc toàn bộ lỗi trả về. |
Site không xuất hiện trong list() | Thao tác thất bại, lưu trữ trình duyệt bị chặn hoặc site được tạo tạm thời | Kiểm tra result, quyền lưu trữ của trình duyệt và tùy chọn persistence: 'explicit'. |
| Plugin hoặc theme bị bỏ qua | Đã truyền nhầm tham số vào Sites API | Dùng Blueprint trong JavaScript API hoặc chạy quy trình cài đặt riêng bằng client. |
| Không tải được ZIP plugin/theme | URL trả về HTML, yêu cầu đăng nhập, hết hạn hoặc không đáp ứng yêu cầu truy cập | Kiểm tra URL tải trực tiếp, quyền truy cập, định dạng ZIP và tài nguyên được Playground hỗ trợ. |
| Kết quả giữa các lần chạy khác nhau | Dùng latest, tài nguyên thay đổi hoặc plugin tự cập nhật | Khóa phiên bản và dùng release hoặc commit cụ thể khi cần tái lập. |
| Không còn đủ bộ nhớ hoặc khó tìm site | Tạo quá nhiều site explicit | Ghi kết quả, xóa các site thử nghiệm không cần giữ và dùng site tạm cho thử nghiệm ngắn. |
Nếu mục tiêu là kiểm thử plugin trước khi cập nhật website thật, hãy tách hai việc: tạo môi trường sạch và thực hiện bộ kiểm thử chức năng. Xem thêm checklist kiểm thử plugin và theme WordPress và quy trình kiểm tra plugin trước khi cập nhật. Playground giúp kiểm tra trong môi trường trình duyệt; không nên xem đó là bản sao hoàn toàn của hạ tầng sản xuất.
Checklist hoàn tất
- Đã chạy mã trong DevTools của Playground, không phải trong dashboard WordPress.
- Đã gọi
isReady()trước khi dùng Sites API. - Đã thay toàn bộ placeholder bằng phiên bản và slug tài nguyên thực tế.
- Mỗi tổ hợp có slug riêng và được tạo tuần tự.
- Đã dùng
list()để đối chiếu site, sau đó dùngsetActiveSite()vàgetClient()để kiểm tra. - Đã đọc lại phiên bản WordPress/PHP từ site đang hoạt động thay vì chỉ tin vào tên site.
- Đã dùng Blueprint hoặc JavaScript API cho plugin, theme và dữ liệu mẫu.
- Đã lưu kết quả cần thiết và xóa site explicit không còn dùng.
Ranh giới cần nhớ là: Sites API quản lý site nào tồn tại và được lưu ra sao; Blueprints mô tả site được khởi tạo với những thành phần nào. Tách hai nhiệm vụ này giúp ma trận phiên bản dễ quản lý hơn và tránh kỳ vọng sai vào tham số của API.

