Så här skapar du en ny tweets-widget

I denna handledning tittar vi på hur man skapar en widget för senaste tweets. Det finns ett ganska stort antal Twitter-relaterade plugin-program i förvaret, men jag hoppas att denna handledning kommer att täcka några av de viktiga (och allmänt tillämpliga) metoderna som behövs för att skapa en sådan plugin (om det är Twitter-baserat eller inte).


Widget-klassen

Widget-klassen, WP_Widget, är en hjälpklass för att skapa widgets. För att skapa en widget skapar du helt enkelt en förlängning av den här klassen med fyra metoder: __konstruera, widget, uppdatering och form.

 klass WP_Widget_Wptuts_Twitter_Widget utökar WP_Widget var $ w_arg; // En klassvariabel för att lagra en rad av våra widgetinställningar och deras standardvärden fungerar __construct ()  funktionsdisplay ($ args, $ instance)  funktionsuppdatering ($ new_instance, $ old_instance)  funktionsform ($ instans) 
  • __konstruera initialiserar widgeten. Här ställer du in widgetens unika ID, titel, beskrivning (för administratörssidan) och klassen (er) för att ge widgetens behållare i frontänden.
  • widget - Metoden som är ansvarig för att skriva ut widgetens innehåll på fronten.
  • form - den här metoden ska skriva ut widgetens inställningar i Utseende> Widget-formuläret
  • uppdatering - den här funktionen är ansvarig för validera alternativen som skickas från widgetens formulär (via form). Arrayen $ new_instance innehåller alternativ som ska valideras och arrayen$ old_instance innehåller de för tillfället sparade alternativen. Den förväntar sig att de validerade alternativen ska returneras, eller felaktigt att avbryta uppdateringen av alternativen.

Klasskonstruktion

Vi börjar med att bygga klassen. För att registrera din widget (er) måste du koppla till åtgärden widgets_init och ringa register_widget, passerar namnet på widgetens klass (WP_Widget_Wptuts_Twitter I detta fall). Det här utdraget sitter strax efter vår widget klass:

 add_action ('widgets_init', 'wptuts_register_widget'); funktion wptuts_register_widget () register_widget ('WP_Widget_Wptuts_Twitter_Widget'); 

register_widget skapar en instans av vår widget, och så kallas __konstruera metod. Detta bör ställa in några av klasskonstanterna, till exempel en unik identifierare (the id_base) och widgetens konfigurationsinställningar, i synnerhet:

  • beskrivning - en beskrivning av widgeten (detta kommer att visas på widgetadministratörssidan).
  • klassnamn - Klass (er) som ska läggas till i widgetens klassattribut.

Du kan också ange en "kontrollalternativ" -matris - det här låter dig ange bredden på widgetens administratörsform (vanligtvis 250px), om du behöver mer utrymme. Estetiskt är det dock att föredra att inte ändra detta och att inte överbelasta dina widgets med överdrivna alternativ.

För att ställa in dessa konfigurationer kan du använda WP_Widget :: __ konstruktion metod (dvs. förälder :: __ konstruktion). Detta förväntar sig:

  • ID Base - en unik identifierare för Widget-klassen
  • namn - Namnet på din widget, som används på adminskärmen.
  • Widget Options - anger klassnamnet och beskrivningen.
  • Kontrollalternativ - (valfritt) utbud av widgetens längd och bredd.

Då (valfritt) kan vi ställa in widgetens inställningar och deras standardvärden.

 funktion __construct () $ widget_ops = array ('classname' => 'wptuts_widget_twitter', 'description' => __ ('Visar en lista över senaste tweets', 'wptuts_twitter')); förälder :: __ konstruera ('WP_Widget_Wptuts_Twitter', __ ('Twitter', 'wptuts_twitter'), $ widget_ops); // Inställ widgetens inställningar och standardvärden $ this-> w_arg = array ('title' => ", 'screen_name' =>", 'count' => '5', 'published_when' => '1'); 

Du borde ge dina widgets en unik klass, eftersom det skulle hjälpa till att se till att någon styling du ger mål endast din widget.


Hämtar tweets

Innan vi går längre, kommer vi att skapa en hjälpmetod som skickar en begäran till Twitter API. Den här enkla metoden tar begäran (en URL) och använder funktionen wp_remote_get för att hämta svaret. wp_remote_get utgör en del av HTTP API som omfattades av denna handledning.

Metoden kontrollerar sedan för eventuella fel: antingen kastas upp av WordPress (med is_wp_error) eller via Twitter (genom att kontrollera svarskoden). Omkopplingsdeklarationen i metoden gör att du kan agera olika enligt den här koden - i exemplet nedan konverteras alla felsvar till ett WordPress-felobjekt eller på annat sätt returneras det framgångsrika svaret (en rad tweets).

Genom att hålla både felkoden och meddelandet kan vi göra det mycket lättare att felsöka senare, om något fel uppstår.

 funktionen retrieve_remote_tweets ($ request_url) $ raw_response = wp_remote_get ($ request_url, array ('timeout' => 1)); om (is_wp_error ($ raw_response)) returnera $ raw_response; $ code = (int) wp_remote_retrieve_response_code ($ raw_response); $ response = json_decode (wp_remote_retrieve_body ($ raw_response)); växla ($ code): case 200: returnera $ response; fall 304: fall 400: fall 401: fall 403: fall 404: fall 406: fall 420: fall 500: fall 502: fall 503: fall 504: returnera nytt WP_Error ($ code, $ response-> error); standard: returnera nya WP_Error ($ code, __ ('Ogiltigt svar', 'wptuts_twitter')); endswitch; 

Twitter API

Twitter har omfattande dokumentation om dess API - vilket bland annat låter dig hämta dina senaste tweets, tweets från din hemsida eller tweets som matchar en sökterm. Några av de mer avancerade API-funktionerna kräver autentisering via OAuth.

I den här handledningen är vi efter en specifik användares tweets (eller användartidslinje). URL: n för att hämta dessa tweets har en mycket enkel struktur:

 https://api.twitter.com/1/statuses/user_timeline.json?screen_name=screen-name&arg1=val1&arg2=val2

var skärmnamn ska vara användarens skärmnamn och de andra argumenten kan vara någon av de som listas här. Vanligtvis argument som include_entities skulle vara satt för att få metadata om tweets (som alla webbadresser eller hashtags de innehåller).


caching

Twitter ställer in en gräns för antalet förfrågningar du kan göra: 150 en timme för obehöriga förfrågningar och 350 annars. Inte bara det, men att hämta tweets tar tid - vilket ökar din webbplatss laddningstid. Att hämta dina tweets från Twitter på varje sidlast är onödigt dyrt - och särskilt så om det inte är nödvändigt att dina tweets visas på din webbplats direkt efter att ha publicerats dem.

Caching, i synnerhet WordPress 'transienter, kan användas för att lagra dina tweets (eller någon data för den delen) lokalt i din databas. Att hämta dem från databasen är mycket snabbare än att hämta dem på distans, och det bidrar inte till någon API-gräns. Naturligtvis kommer uppgifterna snart att bli outdated - det är därför, lagras tillsammans med tweets är en utgångstid.

Tanken är att när du visar dina tweets, om uppgifterna har löpt ut (eller tweetsna inte finns i databasen) hämtar du dem från Twitter och uppdaterar cacheminnet. På så sätt kan du begränsa antalet förfrågningar till Twitter till var 20: e minut, timme eller dag beroende på hur länge du är villig att vänta på att dina tweets ska uppdateras. Dessutom, när tweetsna inte uppdateras, kommer du njuta av snabbare belastningstider. Cachning, när den används ordentligt, är ett bra sätt att öka din plugin-eller temat prestanda. Om du inte har använt det tidigare rekommenderar jag att du tittar på den här videon och följer den här handledningen.

Men - anta att din tweet-cache löper ut och kvittens tjänst är nere för underhåll. Tweetsna raderas från databasen, men du kan inte hämta några tweets från Twitter för att ersätta dem, så det kommer inte att visas något. Lösningen till detta är "Soft Caching".


Soft Caching

Mjuk caching, som caching, försöker uppdatera dina tweets när en viss tid har gått. I motsats till "hård" cachning raderas dock inte de föregående dataen förrän ett giltigt svar har mottagits för att ersätta det. Resultatet är, att Twitter-API ska vara nere - din webbplats visar fortfarande tweetsna från den senaste framgångsrika uppdateringen.

Mjuk cachning stöds inte av WordPress, men Mark Jaquith och Aaron Campbell har producerat en utmärkt klassimplementering av det. Jag kommer att använda en något förenklad metod, som jag hoppas kommer att illustrera hur mjuk cache kan fungera i WordPress.

Tanken är att manuellt hantera övergångsperiodens utgång. Snarare än att lagra tweetsna som en övergångsperiod med en utgångstid lagrar du en array som innehåller tweetsna och utgångstiden inom en transient som inte har någon utgångstid. Vi kan implementera denna metod genom att använda följande funktion i stället för set_transient.

 funktion set_twitter_transient ($ key, $ data, $ expiration) // Tid när övergående utgår $ expire = time () + $ expiration; set_transient ($ key, array ($ expire, $ data)); 

Naturligtvis, utan utgångsdatum, blir data aldrig (eller faktiskt inte garanterat) avlägsnats och ersatt med nya data. Vi måste nu ta hand om detta själv.

När du hämtar den här icke-utgående övergången kontrollerar du om den lagrade utgångstiden har gått. Om det har du då försök för att hämta de nya tweetsna med ovanstående metod retrieve_remote_tweets. Om det lyckas uppdaterar du transienten (med nya data och en ny utgångstid) och använder den nya data. Om det inte är så använder du helt enkelt de för tillfället lagrade uppgifterna tills du får ett framgångsrikt svar från Twitter.

För att hämta tweets (fjärran eller lokalt) och hantera cachen definierar vi metoden get_tweets. Detta tar en rad argument, som genererar Twitter-förfrågan. Till exempel:

  • skärmnamn - Namnet på Twitter-kontot följer
  • räkna - Antalet tweets för att hämta
  • include_rts - 1 | 0 - 1 för att inkludera retweets, 0 för att utesluta retweets.

Metoden använder sedan add_query_arg att bygga förfrågningsadressen, och därigenom genererar en nyckel för vår övergående. Detta är viktigt - eftersom du vill använda samma nyckel för en annan konfiguration av widgeten, särskilt om du har flera instanser av widgeten.

Hårdkodad till denna funktion är en utgångstid på 1 timme.

 funktion get_tweets ($ args) // Bygg begäran URL $ args ['screen_name'] = '@'. $ args ['screen_name']; $ request_url = 'https://api.twitter.com/1/statuses/user_timeline.json'; $ request_url = add_query_arg ($ args, $ request_url); // Generera nyckel $ key = 'wptt _'. Md5 ($ request_url); // löper ut varje timme $ expiration = 60 * 60; $ transient = get_transient ($ key); om (false === $ transient) // Hard expiration $ data = $ this-> retrieve_remote_tweets ($ request_url); om (! is_wp_error ($ data)) // Uppdatera övergående $ this-> set_twitter_transient ($ key, $ data, $ expiration);  returnera $ data;  annat // Mjukt utfall. $ transient = array (utgångstid, data) om ($ transient [0]! == 0 && $ transient [0] <= time() )  // Expiration time passed, attempt to get new data $new_data = $this->retrieve_remote_tweets ($ request_url); om (! is_wp_error ($ new_data)) // Om framgångsrik returuppdatering övergående och nya data $ this-> set_twitter_transient ($ key, $ new_data, $ expiration); $ transient [1] = $ new_data;  returnera $ transient [1]; 

När du använder WordPress 'transient API, skulle du kolla om get_transient hittar din data i cacheminnet, och om inte hämta eller generera data (säg från Twitter) och uppdatera sedan transienten. Men get_tweets Metoden ovan kommer att hantera allt detta - och kommer att returnera din "gamla data" om den inte kan uppdateras. Det är fortfarande inte säkert att returnera data, dock: det kanske är att det inte finns några tweets i databasen (t.ex. körs för första gången) och det blir inte ett framgångsrikt svar från Twitter. I dessa fall a WP_Error objektet returneras - och vi måste se till att din plug-in hanterar detta och försämras graciöst.


Formuläret

Arbetet med formulärmetoden är att visa widgetens alternativformulär på sidan Utseende> Widget. Den skickar de sparade alternativen som ett argument (en array). Naturligtvis kan du då använda wp_parse_args att ersätta några "saknas" värden med standardvärden.

I allmänhet bör widgetformen vara ganska liten (och ofta inuti den smala sidofältet) - det här kan förstoras med de tidigare inställda kontrollalternativen, men det är föredraget att du behåller estetiken i WordPress. Av denna anledning följer jag layouten i WordPress standard widget.

Jag ska också använda metoderna $ This-> get_field_id och $ This-> get_field_name att generera namn och ID-värden för ingångarna för varje instans av en widget, så WordPress kan hantera sin behandling för oss.

I det här exemplet tillåter jag användaren att ge en titel för widgeten, skärmens namn vars tweets ska visas, ett maximalt antal tweets och huruvida det ska inkluderas när tweeten publicerades.

 ($ inst ?> 

typ = "checkbox" value = "1" />


Validering av alternativ

När du har byggt formuläret behöver du uppdatera widgetalternativen när de sparas. WordPress hanterar det mesta för oss - men vi behöver fortfarande bekräfta uppgifterna. Valideringen har behandlats på lite djup i den här artikeln, och om du inte är säker på vad du behöver göra, eller hur du validerar dina data, rekommenderar jag att du kolla in det.

Vad som returneras från den här funktionen läggs till i databasen, så väl som att validera data ska vi se till att det bara innehåller data som vi förväntar oss. En bra teknik är att börja med en tom array och bara lägga till validerad data i den. Om du vill avbryta spara kan du återvända falsk.

 funktionsuppdatering ($ new_instance = array (), $ old_instance = array ()) $ validated = array (); $ validated ['title'] = sanitize_text_field ($ new_instance ['title']); $ validated ['screen_name'] = preg_replace ('/ [^ A-Za-z0-9 _] /', ", $ new_instance ['screen_name']); $ validated ['count'] = absint ($ new_instance [' räkna ']); $ validated [' published_when '] = (isset ($ new_instance [' published_when ']) 1: 0); returnera $ validated;

Skärmnamnet valideras genom att ta bort allt utom alfanumeriska och underskrifter.


Visar widgeten

Slutligen kommer vi till metoden för att visa widgeten. Alla bitar är på plats, allt som återstår är att producera widgetens innehåll själv. De widget Metoden som ansvarar för detta passerar två argument: den första är en rad argument som motsvarar sidbjälkens widgetinställningar - visningsargumenten inklusive before_title, after_title, before_widget, och after_widget. Den andra är inställningarna för den här speciella instansen av widgeten - det här är en rad inställningar som sparats från vårt formulär.

Jag ska använda en annan hjälparfunktion för att generera listan med tweets, men följande ska vara konturerna för alla widgets:

 funktion widget ($ args, $ instance) extrakt ($ args); $ title = apply_filters ('widget_title', $ instance ['title']); echo $ before_widget; echo $ before_title.esc_html ($ title). $ after_title; echo $ this-> generate_tweet_list ($ instans); echo $ after_widget; 

De generate_tweet_list Metoden hämtar bara tweets med get_tweets - och om det inte fanns några fel, loopar du igenom tweetsna och visar dem i en lista. För varje tweet gäller det metoden make_clickable - detta skannar tweeten och gör något skärmnamn, hashtag eller länk till en faktisk länk (se nedan).

Beroende på inställningarna läggs det också till när tweeten publicerades med hjälp av WordPress-funktionen human_time_diff.

 Funktionen generate_tweet_list ($ args = array ()) $ args = shortcode_atts (array ('include_entities' => 'true', 'include_rts' => 1, 'screen_name' => "," count "=> 5," published_when '=> 1), $ args); // Hämta tweets $ tweets = $ this-> get_tweets ($ args); $ content ='
    '; om (is_wp_error ($ tweets) ||! is_array ($ tweets) || count ($ tweets) == 0) $ content. = '
  • '. __ ('Inga tweets tillgängliga', 'wptuts_twitter'). '
  • '; annat $ count = 0; foreach ($ tweets som $ tweet) $ content. = '
  • '; $ content. = ""$ This-> make_clickable ($ tweet)."
    "; om ($ args ['published_when']) $ content. =""; $ href = esc_url (" http://twitter.com/$tweet->user->screen_name/statuses/$tweet->id_str "); $ time_diff = human_time_diff (strtotime ($ tweet-> skapad vid)).' sedan '; $ content. = "". $ time_diff. ""; $ content. =''; $ content. = '
  • '; om (++ $ count> = $ args ['count']) rast; $ content. = '
'; // wp_enqueue_script ('wptuts_twitter_script'); // wp_enqueue_style ('wptuts_twitter_style'); returnera $ content;

Du kommer märka att jag har tagit samtal till wp_enqueue_script och wp_enqueue_style. Dessa kommenteras eftersom jag inte har behövt inkludera någon styling eller skript. Men sedan 3.3 kan du använda dessa funktioner medan sidans kropp genereras (dvs i widget eller kortnummer återkopplingar). Om jag behövde skicka några skript för att denna widget ska fungera, så gör det här så att de bara laddas när de verkligen behövs. Du bör se till att du inte behöver ladda skript och stilar.


Gör Clickable

Här definierar vi metoden make_clickable. Detta tar ett tweet-objekt och returnerar tweets innehåll, efter att ha ersatt några webbadresser, hashtags, användare eller mediaadresser med en lämplig länk. Sedan vi satt include_entities till sannhet innehåller tweet-objektet tweetens "enheter". En enhet är någon webbadress, användarnamn, hashtag eller media som ingår i tweet. För att göra detta använder vi den otillräckliga funktionen str_ireplace.

 funktion make_clickable ($ tweet) $ entities = $ tweet-> enheter; $ content = $ tweet-> text; // Gör några länkar klickbara om (! Tomt ($ entities-> urls)) foreach ($ entities-> webbadresser som $ url) $ content = str_ireplace ($ url-> url, 'expanded_url).' . $ // $ $, $ content); // Gör några hashtags klickbara om (! tomt ($ entities-> hashtags)) foreach ($ entities-> hashtags som $ hashtag) $ url = 'http://search.twitter.com/search?q='. urlencode ($ hashtag-> text); $ content = str_ireplace ('#'. $ hashtag-> text, '#'. $ hashtag-> text . // Gör några användare klickbara om (! tomt ($ entities-> user_mentions)) foreach ($ entities-> user_mentions som $ användare) $ url = 'http: // twitter .com / '. urlencode ($ user-> screen_name); $ content = str_ireplace ('@'.$ user-> screen_name,' @ '. $ user-> screen_name.' ', $ content); // Gör eventuella mediaadresser klickbara om (! Tomt ($ entities-> media)) foreach ($ entities-> media som $ media) $ content = str_ireplace ($ media-> url, 'expanded_url).' "> '. $ media-> display_url. '', $ content);  returnera $ innehåll 

Den färdiga produkten (med förbehåll för ditt temas styling) ska se ut så här:


kortkod

I denna handledning har jag försökt att hålla mig till en grundläggande men viktig princip: dela upp problemen. Vår klass är en samling metoder, och tanken är att varje metod ska vara ansvarig för ett visst syfte. Jag har en återuppringning för att visa översikten av widgeten, som samtalar generate_tweet_list att producera listan själv, vilken användning get_tweets att hämta tweets - själv använder retrieve_remote_tweets att interagera direkt med Twitter API.

Det finns flera anledningar till detta:

  • Läsbarhet - bryta kod i mindre bitar, gör det mycket lättare att läsa, och mycket lättare att felsöka
  • Minska dubbletter av kod - utan att separera ut min kod, om jag hade två metoder som båda försöker hämta tweets från Twitter, måste båda inkludera alla nödvändiga kontroller och cachemanagning. Men genom att skilja mina funktioner som visat kunde de båda använda get_tweets metod.
  • Lätt att redigera - Om Twitter någonsin ändrar deras API har jag nu bara en funktion att redigera, och jag kan vara säker på att resten av plug-in fortsätter att fungera bra.
  • utbyggbarhet - Layouten på denna kod är mer lik Lego än Plasticine. Lego är väldigt mycket bättre. Vi har nu en samling av "Lego Brick" -funktioner som vi kan göra fler saker.

För att illustrera den sista punkten. Vi har skapat en widget som visar en lista över senaste tweets. På grund av separation av bekymmer, med bara några extra linjer (läggs utanför klassen) kan vi skapa en kortnummer som gör exakt samma sak:

 funktion wptuts_twitter_shortcode_cb ($ atts) $ args = shortcode_atts (array ('screen_name' => ", 'count' => 5, 'published_when' => 5, 'include_rts' => 1,) = nya WP_Widget_Wptuts_Twitter_Widget (); returnera $ tw-> generate_tweet_list ($ args); add_shortcode ('wptuts_twtter', 'wptuts_twitter_shortcode_cb');

Tweetsna kan sedan visas med kortnummer: [wptuts_twtter screen_name = "stephenharris88"]. Det accepterar också attributen räkna, published_when och include_rts.

Vi har också den mycket användbara och generiska metoden retrieve_remote_tweets som kan interagera med Twitter på något sätt som vi gillar. Det kommer att returnera antingen ett giltigt svar eller ett WordPress-felobjekt med felmeddelandet.


Slutliga kommentarer

WP-TLC-Transients-klassen, som nämnts tidigare, är en mer generisk implementering av mjukcache, så att du kan ange funktioner för att uppdatera cacheminnet. Det implementerar också bakgrundsuppdatering: Uppdaterar bara cacheminnet när sidan har laddats. Klassen är utformad för att antas i plug-ins (efter omdöpning för att förebygga konflikter), och gör det möjligt för effektiv mjukcachinghantering. Det är faktiskt vad Aaron Campbells Twitter Widget Pro-plugin gör.

Notera: Om du använder delad hosting kan andra webbplatser dela din IP. Twitter API-förfrågningar från dessa webbplatser kommer att bidra till din gränsgräns. Om du upptäcker att du ständigt är begränsad, är det här sannolikt orsaken.

Plugin-programmet som skapades i denna handledning finns på min GitHub.