Как получить данные из Wordpress $wpdb во внешний интерфейс блоков React Gutenberg?
Я использую $wpdb для выполнения запроса mysql и получения данных из файла php.
$results = $wpdb->get_results("SELECT * FROM table_name");
Теперь я зарегистрировал блок Гутенберга с помощью api wordpress..
Компонент представляет собой файл .js, который использует (Wordpress React) под капотом:
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import edit from "./pruefungenEdit";
registerBlockType("mytheme-blocks/pruefungen", {
title: __("Pruefungen Block", "mytheme-blocks"),
description: __("Display a Table of exams", "mytheme-blocks"),
category: "mytheme-category",
icon: {
background: "#f03",
foreground: "#fff",
src: "dashicons-database",
},
keywords: [__("pruefungenBlock", "mytheme-blocks")],
edit: edit,
save: () => {
return <p>Test</p>;
},
});
Это мой компонент React, который я использую для вышеупомянутой функции edit():
import { Component } from "@wordpress/element";
import { withSelect } from "@wordpress/data";
import { __ } from "@wordpress/i18n";
class PruefungenEdit extends Component {
render() {
//where to get the data from the query in .php file??
return <div>Data...</div>;
}
}
export default PruefungenEdit;
Очевидно, что я не могу использовать php-код в своем файле .js react.. Я подумал о настройке небольшого сервера nodejs, который запрашивает мой локальный хост таблица mysql и отправляет эти данные по пользовательскому маршруту api. Затем я запрашиваю этот маршрут на своем интерфейсе react и отображаю данные... но для меня это выглядит слишком сложным обходным путем, я имею в виду, что php сам по себе является своего рода бэкэндом, разве Wordpress не предлагает такую возможность запрашивать данные mysql и каким-то образом отправлять их на интерфейс?
Теперь у меня вопрос: как мне перенести данные из php-файла в мой блок гутенберга, который я зарегистрировал для интерфейса редактора блоков?
РЕДАКТИРОВАТЬ - РЕШЕНИЕ: Это было это легко сделать, зарегистрировав пользовательскую конечную точку и просто запросив эту конечную точку внутри интерфейса react...
add_action( 'rest_api_init', function () {
register_rest_route( 'wp/v1', '/employees', array(
'methods' => 'GET',
'callback' => 'get_employees'
));
});
function get_employees() {
global $wpdb;
$xmlArr = getparsedXMLArray();
$uniqueIDArr = getUniqueID($xmlArr);
$kurs_db = $wpdb->get_results(" SELECT DISTINCT kurs_ort_id, kurs_ort FROM ".$wpdb->prefix . "bsa_location ");
$objJsonDocument = json_encode($kurs_db);
$pruefungen = json_decode($objJsonDocument, TRUE);
$foundPlaces = getAssociatedPlaces($pruefungen, $uniqueIDArr);
$finishedData = addPlace($xmlArr, $foundPlaces);
return $finishedData;
}
Интерфейс:
import { Component } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import apiFetch from "@wordpress/api-fetch";
class PruefungenEdit extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
employees: [],
};
}
componentDidMount() {
try {
apiFetch({
path: "/wp/v1/employees",
}).then((employees) => {
this.setState({ employees, isLoaded: true });
});
} catch (error) {
console.log(error);
this.setState({
error: error,
isLoaded: true,
});
}
}
render() {
const { error, isLoaded, employees } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"container"}>
<div className="row">
<div className="col-xs-12">
<table
id="pruefungentable"
className="table striped dark"
style={{ width: "100%" }}
>
<thead className="thead-dark ">
<tr scope="row" className="table-danger">
<th>#</th>
<th>{__("KursID")}</th>
<th>{__("KursOrt")}</th>
<th>{__("Modul")}</th>
<th>{__("Datum")}</th>
</tr>
</thead>
<tbody>
{employees.map((employee, index) => (
<tr key={index}>
<td>{index}</td>
<td>{employee.KursID}</td>
<td>{employee.KursOrt}</td>
<td>{employee.Modul}</td>
<td>{employee.Datum}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
}
}
export default PruefungenEdit;
1 answers
На самом деле, есть много способов сделать то, что вы просили, но я приведу вам пример, основанный на этом примере на официальном веб-сайте React, который использует AJAX с компонентом на основе класса (но там также есть пример использования функционального компонента с крючками ).
Итак, для части PHP мы создадим пользовательскую конечную точку API REST и просто для целей тестирования мы просто вернем массив с двумя элементами, каждый из которых имеет три свойства: id
, name
и price
.
Что касается части AJAX, мы будем использовать apiFetch()
в пакете @wordpress/api-fetch для извлечения данных из пользовательской конечной точки - вы можете просто использовать встроенную функцию fetch()
в JavaScript, но с помощью apiFetch()
это упрощает задачу, если ваша конечная точка требует/нуждается в аутентификации, потому что вам не нужно беспокоиться о том, что файл cookie не используется, так как он уже включен пользователем. apiFetch()
.
Код
-
PHP - Регистрация пользовательского API REST конечная точка:
add_action( 'rest_api_init', 'my_rest_api_init', 10, 1 ); function my_rest_api_init() { register_rest_route( 'my-plugin/v1', '/items', array( 'methods' => 'GET', 'permission_callback' => '__return_true', // *always set a permission callback 'callback' => function ( $request ) { return array( array( 'id' => 1, 'name' => 'Apples', 'price' => '$2' ), // I used is_user_logged_in() so you can see that apiFetch() by default // sends the cookie nonce when making an API request. array( 'id' => 2, 'name' => 'Peaches', // wrapped 'price' => is_user_logged_in() ? 'FREE :)' : '$5' ), ); }, ) ); }
-
JS и AJAX - Компонент
PruefungenEdit
:// don't forget to import the apiFetch() import apiFetch from '@wordpress/api-fetch'; class PruefungenEdit extends Component { constructor( props ) { super( props ); this.state = { error: null, isLoaded: false, items: [], }; } componentDidMount() { apiFetch( { path: 'my-plugin/v1/items' } ) .then( ( items ) => { this.setState( { isLoaded: true, items, } ); }, // Note: It's important to handle errors here instead of a catch() block // so that we don't swallow exceptions from actual bugs in components. ( error ) => { this.setState( { isLoaded: true, error, } ); } ); } render() { const { error, isLoaded, items } = this.state; // If there's an error in fetching the remote data, display the error. if ( error ) { return <div>Error: { error.message }</div>; // If the data is still being loaded, show a loading message/icon/etc. } else if ( ! isLoaded ) { return <div>Loading...</div>; // Data loaded successfully; so let's show it. } else { return ( <ul> { items.map( item => ( <li key={ item.id }> { item.name } <i>{ item.price }</i> </li> ) ) } </ul> ); } } }
Поэтому я надеюсь, что это поможет, и просто дайте мне знать, если вам понадобятся какие-либо разъяснения. Однако не торопитесь просматривать первую, третью и четвертую ссылки выше.:)