ma is tanultam valamit

WordPress REST API egyedi mező hozzáadása a /posts végponthoz

WordPress REST API egyedi mező hozzáadása a /posts végponthoz 1000 563 bacsoa

Azért jó fullstack fejlesztőnek lenni, mert mindenből kapsz egy kicsit. Imádom ezt a munkát, mert változatos, minden nap új kihívással. A mai menü egy meglévő WordPress REST API bővítés. A feladat csak annyi, hogy egy már létező szabvány WordPress REST API végponthoz egy új mezőt kellett létrehoznom.

Akit a WordPress saját REST API-ja érdekel, az itt mindent megtud róla. Aki nem tudja, mi az a REST, az pedig innen induljon, vagy esetleg a Wikipedia oldalon. Röviden egy olyan egységes interfész, amelynek különböző elveknek és követelményeknek kell megfelelnie, nekünk fejlesztőknek pedig alkalmazkodnunk kell hozzá. Ez jó, mert így egy elfogadott szabványhoz kell programozni, amit mindenki (el)ismer.

A lényeg, hogy most egy Cikk / Bejegyzés (post) részletes végpontjába fogunk beszúrni plusz mezőt. Mihez is kell ez? Például alkalmazásfejlesztéshez, vagy bármilyen olyan külső alkalmazásokhoz, ami REST-alapon működik és JSON-ban várja az adatokat, majd azt dolgozza fel.

A cikk részletes WordPress REST API URL alapértelmezett URL-je a következő (nyilván a https://domain.hu az a te weboldalad tetszőlegesen behelyettesíthető URL-je), a 999 pedig a post_id (bejegyzésed WordPress-ben tárolt egyedi azonosítója) jelöli:

https://domain.hu/wp-json/wp/v2/posts/999

Ide akarunk egy plusz mezőt, mondjuk a szerző nevét. Alapból ugyanis csak a szerző (author) user_id-ja szerepel itt, de miért ne szeretnénk egyből a szerző nevét megjeleníteni? Abból is mondjuk a display_name részben beállított értéket. Nyilván ez tetszőlegesen változtatható, bővíthető. Az én megoldásom:

add_action( 'rest_api_init',  'exibio_register_custom_field' );
function exibio_register_custom_field() {

    // Register author_name field

    register_rest_field( 'post', 'author_name',
        array(
            'get_callback'          => 'get_author_name',
            'show_in_rest'          => true,
            'auth_callback'	        => 'permission_check',
        )
    );

	function get_author_name( $post,  $field_name, $request ) {
		
		$post_id = (int) $post['id'];
		$user_id = (int) $post['author']; // author user_id
		$author = get_userdata( $user_id ); // author object
		$user_name = (string) $author->display_name;
	    
	    return $user_name;

	}

}

Először inicializáljuk a rest_api_init nevű hook-ot, majd hozzáadunk egy új author_name nevű mezőt (ezen a néven fogjuk megtalálni a /v2/posts végpontban lévő JSON-ban) és végül megmondjuk, hogy az új mezőben mi szerepeljen. (get_author_name nevű függvény). A függvény a felhasználó nevével fog visszatérni (azon belül is a display_name, azaz a Nyilvánosan megjelenő névvel), ami a WordPress-ből már ismert user object-ből származik.

Rövid és eredményes kódolást!

Az egyik leghasznosabb ármódosító WooCommerce metódus, a wc_price()

Az egyik leghasznosabb ármódosító WooCommerce metódus, a wc_price() 1600 700 bacsoa

Minden héten szembejön valami, de amivel ma találkoztam, azt muszáj megosztanom, mert ugyan nekem új volt (mint a múltkori Chrome Easter Egg), de attól még lehet, hogy másnak is az lesz és az egyik leggyakrabban használt dologgal kapcsolatos: a termékek árával.

A feladat, hogy változtassunk meg egy termék árát bizonyos feltételek mentén, majd írjuk ki az eredeti és a módosított árat is. A mostani példában annyi a feladat, hogy a bejelentkezett felhasználók kapjanak 10% kedvezményt.

Ez a bejegyzés nyilván nem a pluginokról fog szólni, habár biztos meg lehetne oldani legalább két különbözővel 🙂

A következő két WooCommerce hookra van szükségünk:

  1. woocommerce_get_price
  2. woocommerce_get_price_html

Az első magát az árat, mint numerikus értéket állítja, a 2. pedig a megjelenített, tehát lerenderelt HTML kimenetet. Igazából ha csak a desszert érdekel, akkor a 2. pontot elhagyhatod, de azért olvass tovább, hátha érdekel a köret is.

Először nézzük az 1. példát, állítsuk be az árat:

add_filter('woocommerce_get_price', 'exibio_return_custom_price', 10, 2);
function exibio_return_custom_price( $price, $product ) {

    $post_id = $product->get_id(); # a termék azonosító (post_id)
    $user_id = get_current_user_id(); # a felhasználói azonosító (user_id)
    $original_price = $price; # az eredeti ár

    if ( is_user_logged_in() ) {
        $discount = $price / 100 * 10; # a kedvezmény mértéke: 10%
        $price -= $discount; # a kedvezménnyel csökkentett új ár
    }

    return $price;

}

Igazából a post_id és  a user_id nem kell ehhez a feladathoz, de odaírtam, hátha valaki csak egy konkrét termékre, vagy felhasználóra akarja megadni a kedvezményt. A fenti hook módosítja a WooCommerce terméknek admin felületen beállított árát. A megoldás ennyi, viszont nem ez volt a heti újdonság, hanem az, hogy szeretném kiírni az új árat úgy, hogy mellé/fölé kiírom az eredeti árat.

Ehhez kell a 2. hook, a woocommerce_get_price_html.

A probléma azzal van, hogy az árat numerikus (float azaz lebegőpontos) formátumban kapjuk meg, majd  formázottan szeretnénk megjeleníteni, pl. ezres elválasztóval, devizanem megjelenítéssel, stb. Tehát bejön ez:

15000

És ezt szeretnénk kiírni:

15 000 Ft

Ekkor jön az, hogy az a számot elkezdjük a jól ismert number_format függvénnyel alakítgatni, majd hozzátesszük a devizanemet, de ez elég macerás (újabb WooCommerce függvény kell hozzá, amivel a beállított devizanemet is le kell kérni a get_woocommerce_currency() metódussal). Plusz, ha esetleg kétnyelvű a webáruházunk és az egyikben HUF-nak, a másikban Ft-nak hívjuk a devizanemet, vagy esetleg eleve két különböző devizanem van, akkor még tovább kell bonyolítani. Arról nem is beszéltem, hogy néha £400 kell kiírnunk, nem pedig 400 £, ugye.

Ezt az egész problémát megoldja egy lépésben a wc_price nevű metódus. Egyetlen paramétert vár, ez pedig az ár numerikus (lebegőpontos vagy integer) formátumban, majd szépen visszaadja a WooCommerce-ben beállított formátumú devizában, ezres elválasztó karakterrel, szépen HTML formátumban.

add_filter( 'woocommerce_get_price_html', 'exibio_return_custom_price_html', 10, 2 );
function exibio_return_custom_price_html( $price, $product ) {
    
    $post_id = $product->get_id();
    $user_id = get_current_user_id();
    $original_price = (float) get_post_meta( $post_id, '_price', true ); // az eredeti ár numerikus formátumban

    if ( is_user_logged_in() ) {
        
        // az eredeti adatbázisban tárolt ár formázva, mielőtt még a 10% kedvezményt megadtuk volna
        $output = "<abbr class='original_price_label'>Eredeti ár:</abbr> <del class='original_price' aria-hidden='true'>" . wc_price($original_price) .  "</del>";
        
        $output .= "<abbr class='discount_price_label'>Akciós ár 10% kedvezménnyel:</abbr>";

        // ez pedig már a 10%-kal csökkentett / módosított ár        
        $output .= $price;
        $price = $output;
    }

    return $price;

}

A woocommerce_get_price előbb fut le, mint a woocommerce_get_price_html hook. Az eredeti ötletet innen nyúltam.

Összegezve, röviden így működik. Nézzük ezt a számot, mint eredeti ár:

15000

Hívjuk meg a wc_price metódust:

echo wc_price( 15000 );

Majd megkapjuk a generált WooCommerce formátumú HTML kimenetet:

<span class="woocommerce-Price-amount amount">
	<bdi>15 000&nbsp;<span class="woocommerce-Price-currencySymbol">Ft</span></bdi>
</span>

Örülünk Vincent. Rövid és eredményes kódolást!