Kā padarīt WordPress aizraujošāku, izmantojot WordPress API, ACF un Express.js

Es strādāju ar Wordpress kopš tā izplatīšanas kā satura pārvaldības sistēmas. Es gandrīz neuztraucos, kad klienti vai kolēģi to vairs piemin. Esmu “atradis gaismu” stabilākos ietvaros un uzzinājis daudz vairāk par dažādām pielāgoto tīmekļa lietojumprogrammu daļām.

Tāpēc, cenšoties atjaunot aizraušanos ar WordPress, es sāku meklēt dažādus veidus, kā ieviest sistēmu. Viens no šiem veidiem ir nošķirt priekšgalu no aizmugures un izvairīties no dažiem sāpju punktiem, lietojot WordPress veidņu tagus un tematisko sistēmu. Apskatīsim.

Monolītās un izplatītās lietotnes

Wordpress ir monolīts ietvars, kas nozīmē, ka ietvara dažādās daļas (datu bāze, failu glabāšana, prezentāciju struktūras un aktīvu faili, biznesa loģikas faili) ir iepakotas kopā. Šī ir liela daļa no tā, kāpēc WordPress ir tik viegli sākt un darboties. Instalējiet MAMP, nokopējiet jaunākos Wordpress failus, izveidojiet datu bāzi un mainiet wp-config.phpfailu. Labi iet.

Mēs gatavojamies pretoties monolītajai konvencijai un sadalīt šo WordPress vietni divās dažādās daļās: priekšējā un aizmugurējā daļa, prezentācija un administrēšana.

Mēs izmantosim Wordpress mūsu lietotnes datu administrēšanai un izmantosim spraudni, kas palīdzēs izveidot un pārvaldīt atribūtus (laukus) mūsu pielāgotajiem ziņu veidiem. Lietu prezentācijas pusē mēs pilnībā atteiksimies no motīva un patērēsim API galapunktus no lietojumprogrammas Express.js.

Piemērs

Šajā piemērā mēs izveidosim vienkāršu produktu sarakstu. Ideja ir tāda, ka jums jau ir vietne, kuru nodrošina Wordpress, un vēlaties pārvaldīt pārdodamo produktu sarakstu, izmantojot to pašu interfeisu. Bet jūs vēlaties izveidot veikalam pavisam citu vietni.

WordPress API

Kopš 4.7 versijas Wordpress automātiski atklāj jūsu publicētās ziņas (un citus datus), izmantojot savu REST API, kas tiek pasniegta JSON formātā. Ja esat izveidojis vietni, izmantojot Wordpress 4.7+, vienkārši pievienojiet /wp-jsonsaknes URL un apbrīnojiet atgrieztā teksta sienu.

Izmantojot šo API, kas automātiski integrēts Wordpress instalācijā, liels sadalītās lietojumprogrammas darbs jau ir paveikts mūsu labā. API veidošana var būt šķērslis, sākot darbu ar šo jauno domāšanas veidu par lietojumprogrammām. WordPress ir izveidojis fantastisku pamata API, lai patērētu mūsu datus jebkādā veidā, kā mēs vēlamies.

Šajā brīdī es tikai pārblīvētu internetu, rakstot apmācību par to, kā lokāli instalēt WordPress. Tā vietā es tevi norādīšu uz uzticamu avotu par šo tēmu.

Neatkarīgi no tā, kuru ceļu izmantojat, lai izveidotu un palaistu WordPress instanci, jums vajadzētu būt iespējai tai piekļūt, izmantojot //localhostvai kādu citu URL. Tiklīdz mums būs vietrādis URL, veiksim ātru pārbaudi, lai pārliecinātos, ka mums ir dati. Es dodu priekšroku tādam rīkam kā Pastnieks, taču mēs to darīsim vienkārši un mūsu pārlūkprogrammā apmeklēsim šo URL (protams, attiecīgi mainot URL).

//localhost/mysite/wp-json

Tam vajadzētu atgriezt visu pieejamo galapunktu sarakstu jūsu Wordpress instalācijas REST API.

Bet pa īstam, pastnieks ...

Pastnieks

Pastnieks ir vienīgā pilnīgā API izstrādes vide, kas paredzēta API izstrādātājiem, kuru izmanto vairāk nekā 5 miljoni izstrādātāju ... www.getpostman.com

Pielāgoti ziņu veidi

Tā kā WordPress ierobežo mūs ar diviem datu tipiem (Ziņas un lapas), mums būs jāizveido pielāgots ziņu veids mūsu produktiem. Tas radīs skaidru nošķiršanu no Produkta ziņām un citām mūsu rīcībā esošajām ziņām.

Ir vairāki dažādi veidi, kā izveidot pielāgotus ziņojumu veidus. Šeit mēs izveidosim vienu failu WordPress spraudnis, lai reģistrētu produktu ziņas veidu.


    
function create_product_cpt() { $labels = array( 'name' => __( 'Products', 'Post Type General Name', 'products' ), 'singular_name' => __( 'Product', 'Post Type Singular Name', 'products' ), 'menu_name' => __( 'Products', 'products' ), 'name_admin_bar' => __( 'Product', 'products' ), 'archives' => __( 'Product Archives', 'products' ), 'attributes' => __( 'Product Attributes', 'products' ), 'parent_item_colon' => __( 'Parent Product:', 'products' ), 'all_items' => __( 'All Products', 'products' ), 'add_new_item' => __( 'Add New Product', 'products' ), 'add_new' => __( 'Add New', 'products' ), 'new_item' => __( 'New Product', 'products' ), 'edit_item' => __( 'Edit Product', 'products' ), 'update_item' => __( 'Update Product', 'products' ), 'view_item' => __( 'View Product', 'products' ), 'view_items' => __( 'View Products', 'products' ), 'search_items' => __( 'Search Product', 'products' ), 'not_found' => __( 'Not found', 'products' ), 'not_found_in_trash' => __( 'Not found in Trash', 'products' ), 'featured_image' => __( 'Featured Image', 'products' ), 'set_featured_image' => __( 'Set featured image', 'products' ), 'remove_featured_image' => __( 'Remove featured image', 'products' ), 'use_featured_image' => __( 'Use as featured image', 'products' ), 'insert_into_item' => __( 'Insert into Product', 'products' ), 'uploaded_to_this_item' => __( 'Uploaded to this Product', 'products' ), 'items_list' => __( 'Products list', 'products' ), 'items_list_navigation' => __( 'Products list navigation', 'products' ), 'filter_items_list' => __( 'Filter Products list', 'products' ), );
 $args = array( 'label' => __( 'Product', 'products' ), 'description' => __( '', 'products' ), 'labels' => $labels, 'menu_icon' => 'dashicons-products', 'supports' => array('title', 'editor', 'excerpt', 'thumbnail'), 'taxonomies' => array('products'), 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_position' => 5, 'show_in_admin_bar' => true, 'show_in_nav_menus' => true, 'can_export' => true, 'has_archive' => true, 'hierarchical' => false, 'exclude_from_search' => false, 'show_in_rest' => true, 'rest_base' => 'products', 'publicly_queryable' => true, 'capability_type' => 'post', );
 register_post_type( "product", $args );}%>

While long-winded, this is pretty standard code for creating a custom post type in Wordpress. Two things to note in our $args array:

  • 'show_in_rest' => true makes the custom post type accessible via the REST API
  • 'rest_base' => 'products' sets the name we use to access Products via the REST API endpoints

Once you have your custom post type showing in the Wordpress admin, let’s make sure we can get a response via the API (you’ll need to create a product so it doesn’t return empty).

//localhost/mysite/wp-json/wp/v2/products

And here’s what we get…

Sweet!

Advanced Custom Fields

I try to limit my usage of plugins as much as possible, but I’ll make an exception for Advanced Custom Fields (ACF). ACF takes all the work out of creating and managing custom fields for post types. Head to your Plugins page, search for Advanced Custom Fields then click “Install” & “Activate”. All done.

It would also be redundant for me to walk you through creating a Field Group using Advanced Custom Fields, so I’ll let their documentation walk you through it if you don’t know how.

Let’s create a Field Group called “Product Meta” and add fields for “Normal Price”, “Discount Price” and “Inventory Quantity” and position them in the sidebar area.

Good.

Now comes the tricky part. The fields we just created through ACF aren’t exposed via the REST API by default. We will have to leverage add_filter and rest_prepare_{$post_type} to add the custom field values to the JSON response. Here, I’ve simply added this bit of code to the bottom of our custom post type plugin file for the sake of brevity.

function my_rest_prepare_post($data, $post, $request) { $_data = $data->data; $fields = get_fields($post->ID);
 foreach ($fields as $key => $value){ $_data[$key] = get_field($key, $post->ID); }
 $data->data = $_data; return $data;}
add_filter("rest_prepare_product", 'my_rest_prepare_post', 10, 3);

Thanks to Cody Sand for the tidbit above.

Express.js

Our Express.js app will provide us a framework for consuming the Wordpress API and presenting products in our store website. Since we are simply consuming an API, we could use any framework of our choosing. Vue.js. Angular. Backbone. React. Rails. Django. Middleman. Jekyll. The front-end world is your oyster.

I’ll assume you already have Node.js installed. If you don’t, it’s dead simple. Let’s start a new Express.js app.

npm install -g express-generator nodemonexpress --css=sass --view=jade --git mystorecd mystorenpm install --save request request-promise && npm install

Here, we are using the Express Generator package to generate a skeleton for our Express app. We’ll also be using SASS for stylesheets and Jade Template Engine. Choose whatever you’re comfortable with. Nodemon will restart our app automatically for us when a file changes, and the Request library will help us make HTTP requests to the Wordpress API. Let’s serve up our Express app:

nodemon

Now, when we pull up //localhost:3000 we should see our Express app running.

Alright, now let’s pull in our products.

var express = require('express');var router = express.Router();const rp = require('request-promise');
/* GET index page. */router.get('/', function(req, res, next) { rp({uri: '//127.0.0.1:8888/test/wp-json/wp/v2/products', json: true}) .then((response) => { console.log(response); res.render('index', {products: response}); }) .catch((err) => { console.log(err); });});
module.exports = router;

In our index.js route file, let’s include the Request-Promise library then make a call to the products endpoint within our root route (/).

If the request is successful, then we render our index view. If there’s an error with the request, we simply log it. Now, the view…

extends layout
block content h1 MyStore ul each product in products li product.title.rendered product.price

Using Jade, we will simply list the products out. Ok, let’s check out our store site.

? There’s your prize. I’ll leave it up to you to continue down the Express road and figure out how to get product listing and index pages working.

Beyond

This is a fairly simple example of how distributed apps work using Wordpress. We could have continued to separate the app into even more parts by integrating a CDN for media storage or moving the database to a separate server. We also didn’t cover authentication for the Wordpress API which is something you would absolutely need in production.

From here, you could implement Stripe or another payment processor and have a fully functional store site. I hope this has inspired some of you to leverage Wordpress in different ways and continue using one of the most ubiquitous CMS solutions out there. Happy coding!