Как получить данные из 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;
Author: Marc_L, 2021-01-30

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

Поэтому я надеюсь, что это поможет, и просто дайте мне знать, если вам понадобятся какие-либо разъяснения. Однако не торопитесь просматривать первую, третью и четвертую ссылки выше.:)

 4
Author: Sally CJ, 2021-02-06 05:39:54