I custom field di WordPress

WordPress è uno degli strumenti di pubblicazione di contenuti più apprezzato in rete. Se non sembra temere rivali come piattaforma di sviluppo blog, negli ultimi tempi si è affermato anche come vero e proprio CMS, prestandosi alla messa in opera di siti di ogni tipo: da siti statici e poco aggiornati, a siti dall’architettura decisamente complessa, come siti di e-commerce. Dalla versione 3.0, WordPress dispone di tassonomie multiple e tipi di post personalizzati, che rendono il software utilizzabile per ogni tipo di progetto web. Queste nuove features, però, non sono sempre così innovative quanto ci si potrebbe attendere.

WordPress, infatti, dispone di campi che permettono di associare meta-informazioni ai post e alle pagine del sito, definiti custom fields.
Continua a leggere

Annunci

WordPress tip: generare il link all’archivio dell’autore

Lavorando su WordPress, mi è sorta la necessità di inserire, all’interno dei post, un box con le info dell’autore e con il link all’archivio di tutti gli articoli dello stesso autore.

Ecco la soluzione per la creazione del link:

<?php
if(get_usernumposts(get_the_author_meta('ID')) > 0){
?>
<p><span>Gli articoli di <?php the_author_posts_link(); ?> (<?php the_author_posts(); ?>)</span>
<?
}
?>

La funzione get_usernumposts() restituisce il numero di post dell’autore di cui viene passato l’ID. L’ID è prelevato grazie al template tag get_the_author_meta(‘ID’). Se vi è almeno un post dell’autore corrente, viene mandato a video il codice HTML successivo.

Il template tag the_author_posts_link() manda a video il nome dell’autore con il link all’archivio personale, mentre il template tag the_author_posts() manda a video il numero complessivo di articoli.

Ecco il risultato:

Impaginazione dei dati di un result-set con PHP

Spesso capita di dover mostrare a video un numero limitato di dati rispetto a quelli presenti in un archivio.

Così, sia se lavorate sui vostri database, sia se dovete gestire i dati provenienti da una webapp cui accedete attraverso API, è frequente dover mostrare l’output dei vostri script su più pagine.

I dati che occorrono sono solo 3:

  1. Numero totale degli elementi del result-set
  2. Numero degli elementi da mostrare per ogni pagina
  3. Indice del primo elemento della pagina

Questa è la mia soluzione al problema:

<?php

$totalResults = 100;

// se è passata la variabile itemsperpage, ne preleva il valore 
// altrimenti attribuisce valore 10 
$itemsPerPage = $_GET['itemsperpage'] ? $_GET['itemsperpage'] : 10;

// se è passato lo startindex, ne preleva il valore 
// altrimenti attribuisce valore 1
$startIndex = $_GET['startindex'] ? $_GET['startindex'] : 1;

// lo startIndex della pagina precedente 
// e della pagina successiva
$prevStartIndex = $startIndex - $itemsPerPage;
$nextStartIndex = $startIndex + $itemsPerPage;

// numero della pagina corrente 
// la funzione floor approssima al numero intero immediatamente precedente
$numPage = floor((($startIndex - 1)/$itemsPerPage) + 1);

// numero dell'ultima pagina
$lastPage = (is_int($totalResults/$itemsPerPage)) ? ($totalResults/$itemsPerPage) : (floor($totalResults/$itemsPerPage + 1));

/* in alternativa alla stringa precedente, si può ricorrere alla normale struttura condizionale if (is_int($totalResults/$itemsPerPage)){ $lastPage = $totalResults/$itemsPerPage; }else{ $lastPage = floor($totalResults/$itemsPerPage + 1); } */

// genera il link alla pagina precedente 
// se la pagina attuale è successiva alla prima pagina
if($numPage > 1){
  $prevPageURL = 'miofile.php?startindex=' . $prevStartIndex . '&amp;itemsperpage=' . $itemsPerPage;
  $prevPageLink = '<a href="' . $prevPageURL . '">Precedente</a>';
}else{
  $prevPageLink = "Precedente";
}

// genera il link alla pagina successiva 
// se la pagina attuale è precedente all'ultima pagina
if($numPage < $lastPage){
  $nextPageURL = 'miofile.php&amp;startindex=' . $nextStartIndex . '&amp;itemsperpage=' . $itemsPerPage;
  $nextPageLink = '<a href="' . $nextPageURL . '">Successiva</a>';
}else{
  $nextPageLink = "Successiva";
}

Processare XML con PHP 5

Accedere ai normali nodi di un listato XML è molto semplice con le funzioni SimpleXML (vedi anche su W3schools) di PHP 5. Tuttavia, può nascere qualche perplessità quando ci si trova in presenza di namespace e nomi di nodi in cui vi siano trattini (“-“), in inglese hyphens.
Vediamo, allora, come accedere ai nodi nei tre casi più comuni.

Supponiamo di avere un qualsiasi file XML, come un normale feed. Con PHP 5 si accede ai nodi con una semplicità disarmante:

$url = "http://www.esempio.com/file.xml";
$xml = simplexml_load_file($url);

In alcuni casi, potrebbe essere necessario ricorrere alla libreria cURL:

$url = "http://www.esempio.com/file.xml";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
curl_close($ch);
$xml = simplexml_load_string($result);

In questo caso è stato chiesto il listato XML sottoforma di stringa di testo. Come si nota, si accede ai nodi con la funzione simplexml_load_string(), e non con simplexml_load_file(), come nell’esempio precedente.

Ok. Ora abbiamo l’oggetto $xml e accederemo ai nodi e ai relativi attributi con un normale ciclo floreach():

foreach($xml->item as $item){
  $title = $item->title;
  $attrib = $title['attribute'];
}

Che succede quando ci si trova in presenza di namespace? Prima di tutto, va cercato l’elemento root del blocco XML, e l’attributo xmlns con cui viene dichiarato il namespace (si noti che il browser normalmente non accederà alla risorsa indicata, ma ne terrà conto solo come riferimento univoco al namespace).

Facciamo un esempio, prendendo a riferimento un feed generato da FeedBurner. L’elemento root è <rss>:

<rss xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  xmlns:media="http://search.yahoo.com/mrss/" version="2.0">

Se volessimo l’autore di un post, all’interno del nodo item dovremmo cercare il nodo <dc:creator>:

<dc:creator>carlodaniele</dc:creator>

Non rimane che accedere ai nodi con solito ciclo foreach():

foreach($xml->item as $item){
  $dc = $item->children("http://purl.org/dc/elements/1.1/");
  $creator = $dc->creator;
}

La differenza rispetto all’esempio precedente è che abbiamo fatto ricorso al metodo children(), passando come argomento la URI della dichiarazione precedente. A questo punto si può accedere ai nodi come nel primo esempio.

Infine, i nodi con gli hyphen. In realtà, non è frequente incontrare i trattini nei nomi dei nodi… ma può succedere. Nelle risposte dell’API di Tumblr, ad esempio, vi sono un mucchio di trattini…

Il ciclo foreach() è sempre lo stesso. In realtà, cambia ben poco: bisognerà solo ricorrere a parentesi graffe e virgolette (o apostrofi):

foreach($xml->posts->post as $post){
  $caption = $post->{'photo-caption'};
}

cURL, Php e l’API di Flickr

In passato ho parlato più volte di come accedere all’API di Flickr via Php. Non avevo, però, ancora provato ad accedere via cURL, e gli script erano abbastanza lunghi.

flickr

Poi mi è venuta la curiosità di provare ad accedere inviando una richiesta REST via libcurl e, con poche righe viene fuori l’output a video.
Insomma, il codice si semplifica moltissimo (ah, se non avete mai usato cURL, è indispensabile leggere i due post precedenti).

E quindi, qui seguiamo lo schema degli ultimi post, con l’avvertenza che sarò sbrigativo sui concetti introduttivi dell’API di Flickr, rinviandovi alla lettura dei post in cui ne ho già parlato.

Ovviamente, prima ricordatevi di chiedere la chiave API (http://www.flickr.com/services/api/keys/apply/).

La URL della richiesta

Il percorso da seguire per accedere via cURL all’API di Flickr parte sempre dall’endpoint REST:

http://api.flickr.com/services/rest/

Alla URL dovremo aggiungere i parametri della richiesta, cioè chiave api, metodo, formato di risposta e argomenti aggiuntivi.
Se utilizziamo il metodo flickr.photos.getInfo, che ci consente di ottenere una serie (corposa) di informazioni su singole fotografie, dovremo specificare tra gli argomenti l’ID della foto:

$api_hey = "MIA_CHIAVE_API";
$format = "rest";
$method = "flickr.photos.getInfo";
$photo_id = "ID_MIA_FOTO";

Il codice necessario alla costruzione dell’URL diventa:

$params = array(
'api_key' => '787b8623c59bd1c17434d988108711a3',
'method' => 'flickr.photos.getInfo',
'photo_id' => '3569999657',
'format' => 'rest',
);
$encoded_params = array();
foreach ($params as $k => $v){
$encoded_params[] = urlencode($k).'='.urlencode($v);
}
$url = "http://api.flickr.com/services/rest/?".implode('&', $encoded_params);

Invochiamo l’API via libcurl

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
curl_close($ch);

Avrete notato che il protocollo di trasmissione è http, e non https come nel caso di delicious. Questo significa che non ci servirà la versione di cURL con supporto SSL (Se siete utenti di sistemi win32, l’istallazione della versione SSL di cURL potrebbe essere alquanto noiosa).
Ripeto ancora che, se lavorate su un sistema *nix, cURL è già presente nella vostra istallazione lampp, quindi dovrete solo preoccuparvi del codice.

Manipoliamo i dati

$xml = simplexml_load_string($result);
if($xml['stat'] == "ok"){
echo "Photo id: " . $xml->photo['id'] . "<br />";
echo "Photo secret: " . $xml->photo['secret'] . "<br />";
echo "Photo server: " . $xml->photo['server'] . "<br />";
echo "Photo farm: " . $xml->photo['farm'] . "<br />";
echo "Photo originalsecret: " . $xml->photo['originalsecret'] . "<br />";
echo "Photo originalformat: " . $xml->photo['originalformat'] . "<br />";
echo "Owner nsid: " . $xml->photo->owner['nsid'] . "<br />";
echo "Owner username: " . $xml->photo->owner['username'] . "<br />";
echo "Title: " . $xml->photo->title . "<br />";
}else{
echo "non hai vinto, ritenta.";
}

Se avete letto il post precedente, questo codice non ha bisogno di commenti. Se Flickr risponde positivamente, allora mostriamo i dati a schermo.

Vediamo la foto

Ora che abbiamo tutti i dati, possiamo utilizzarli per costruire le URL delle fotografie e, quindi, mostrarle a schermo.
Per visualizzare una foto è, ovviamente, necessario conoscere la struttura della URL:

http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstb].jpg

I parametri da inserire, quindi, sono:

{farm-id}
{server-id}
{id}
{secret}
[mstb]

I primi 4 dati vengono restituiti da Flickr nel blocco XML. Dando un’occhiata al codice di sopra, i valori sono dati da:

$xml->photo['farm']
$xml->photo['server']
$xml->photo['id']
$xml->photo['secret']

L’ultimo dato, invece, lo stabiliamo noi quando impostiamo le dimensioni dell’immagine da visualizzare:

s: quadratino 75 x 75
t: miniatura, 100 sul lato più lungo
m: piccolo, 240 sul lato più lungo
: medio, 500 sul lato più lungo
b: grande, 1024 sul lato più lungo (solo per immagini originali molto grandi)
o: immagine originale jpg, gif o png, in base al formato di origine

Un miniatura di 240px della foto di sopra, avrà la seguente URL:

http://farm4.static.flickr.com/3324/3569999657_47a970a1ca_m.jpg

E questa è l’anteprima. Ma la pagina originale? Anche in questo caso, la URL si struttura secondo un modello stabilito:

http://www.flickr.com/photos/{user-id}/{photo-id}

Anche in questo caso, dal codice precedente ricaviamo i dati che occorrono:

$xml->photo->owner['nsid']
$xml->photo['id']

e quindi:

http://www.flickr.com/photos/13667501@N02/3569999657

A questo punto, possiamo inserire nella nostra pagina sia la miniatura, sia il link alla foto originale:

Detto questo, rinvio alla lettura della reference ufficiale alla costruzione delle URL di Flickr:
http://www.flickr.com/services/api/misc.urls.html

Continua…

cURL, Php e l’API di delicious

Letto l’ultimo post?

Se non l’avete letto, vi consiglio di darci un’occhiata prima di passare a questo.

Dopo aver gettato le basi del discorso sulla libcurl, cominciamo il viaggio tra le APIs di alcune tra le webapps più popolari. Qui parliamo di delicious.

delicious

Non farò cenno alcuno a cosa sia il social bookmarking e la folksonomy; non parlerò affatto degli aspetti concettuali e sociali dei tag e dei machinetags. Per questi discorsi, indispensabili e propedeutici allo sviluppo di un’applicazione che utilizzi le API di delicious, rinvio ad altre fonti. Qui si parla solo di codice!

Sarà codice estremamente semplice e poco raffinato, ma ci poniamo solo obiettivi dimostrativi.

Composizione delle URL di richiesta

L’API di delicious viene invocata con semplici URL (abbiamo già parlato del formato REST nel post precedente).

La URL sarà composta dall’endpoint REST, comune a tutte le richieste, dal metodo invocato e dai parametri obbligatori o facoltativi che completano la richiesta.

La URL dell’endpoint sarà sempre:

https://api.del.icio.us/v1/

Ciò significa che tutte le nostre richieste avranno questa prima parte di URL in comune. Come potete notare, il protocollo di trasmissione è https. Qui non ne parlo, rinviandovi a letture più importanti. Lo faccio notare solo perchè, se non usate un sistema Linux (locale o remoto che sia), dovrete istallarvi la vostra versione di cURL (ne abbiamo parlato nel post precedente). Per accedere all’API di delicious sarà indispensabile scaricare la versione con supporto SSL.

La seconda parte dell’URL specificherà il metodo invocato. Se desideriamo avere una lista di bokmarks aggiunti di recente, utilizzeremo il metodo posts/recent. La nostra URL diventa:

https://api.del.icio.us/v1/posts/recent

Così, però, avremo solo una lista ordinata cronologicamente. Specificando dei parametri di richiesta, stabiliremo i filtri che consentiranno di raffinare la ricerca.
Se vogliamo avere tutti i bookmarks etichettati con la parola “delicious”, aggiungeremo il parametro tag=delicious. Possiamo anche specificare più tag: basterà concatenarli col silbolo +: tag=delicious+api.
La URL diventa:

https://api.del.icio.us/v1/posts/recent?tag=delicious

Ovviamente, possiamo aggiungere anche altri parametri. Per una lista completa, date un’occhiata alla guida ufficiale: http://delicious.com/help/api.

Avete provato a digitare la URL nel browser? Take a try… avrete un listato XML.

User Agent e utente

Non possiamo parlare di User Agent, ovviamente. Sapete tutti di cosa si tratta (se avete dei dubbi, date una lettura qui e qui).
Diciamo solo che delicious gradisce sapere chi bussa alla porta, prima di aprire. Per questo è opportuno specificare il nome dell’applicazione che sta invocando l’API tra i parametri trasmessi via cURL.

Possiamo forzare il nome del nostro browser preferito (“Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6”), oppure specificare il nome della nostra applicazione (“Mash-up con cURL e PHP”).

Oltre a specificare lo user agent, è necessario autenticarsi col proprio nome utente e pw (questo significa che se non avete un account, delicious non vi darà accesso all’API).

Stabiliamo la connessione

Fatte le debite premesse, passiamo al codice:

$url = "https://api.del.icio.us/v1/posts/recent?tag=delicious&count=20";
$user_agent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_USERPWD, "username:password");
$result = curl_exec($ch);
curl_close($ch);

Oltre a richiedere i bookmarks etichettati con la parola “delicious”, stabiliamo che ci vengano mostrati i 20 più recenti. Se non stabilissimo questo parametro, delicious ce ne restituirebbe 15. Il valore massimo di count è 100.

Manipoliamo i dati

$posts = simplexml_load_string($result);
foreach ($posts->post as $bookmark) {
  $href = $bookmark['href'];
  $hash = $bookmark['hash'];
  $description = $bookmark['description'];
  $tags = explode(" ", $bookmark['tag']);
  $time = $bookmark['time'];
  $extended = $bookmark['extended'];
}

Un giorno mi dedicherò alle funzioni di Php5 per la manipolazione dei dati in formato XML. Ma non oggi…
L’opzione passata a cURL

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

stabilisce che i dati vengano passati come stringa di testo e non come file. In questo modo saranno accessibili via Php5 con la funzione simplexml_load_string().

That’s all falks. Non c’è altro da fare che mostrare l’output a video. E la cosa bella è che accederemo alle altre webapps cui ho accennato nel precedente post, quasi nello stesso modo: definizione dei parametri, accesso a cURL, trasmissione della richiesta, manipolazione dei dati.

Forse sono stato un po’ sbrigativo. Ho voluto più che altro tracciare delle linee guida per consentire poi di approfondire il discorso, rinviandovi alle sedi più opportune.

Un articolo senza dubbio più completo ed esauriente sull’API di delicious l’ho scritto per ioProgrammo, ed è in edicola proprio in questi giorni. Su ioProgrammo, inoltre, ho offerto lo spunto per un simpatico mash-up delicious/Google Maps.

Il riferimento obbligatorio, comunque, è la guida ufficiale: http://delicious.com/help/api

Continua …

cURL, Php e le API pubbliche

Questo post vuole essere un’introduzione al discorso che svilupperò nelle prossime settimane sulle API pubbliche di diverse webapps, tra cui quelle di flickr, twitter, delicious e slideshare. A queste ne aggiungerò probabilmente delle altre, ma, prima di sbilanciarmi, mi riservo un’analisi di fattibilità…

Il frutto di questo lavoro dovrebbe essere presentato al romagnacamp di settembre, assemblato in un’applicazione unica messa su con la collaborazione di Valentino.

Le API di cui parlerò nei prossimi post sono tutte accessibili con richieste trasmesse attraverso delle semplici URL, cioè che rispettano il cosiddetto formato REST (Representational State Transfer).

Ad una richiesta REST, le API in questione risponderanno sempre con un blocco XML, che noi manipoleremo con del codice PHP.

Lo schema che seguiremo sarà sempre lo stesso, per tutte le webapps. Per accedere alle API ricorreremo alla libreria cURL.

curl is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS and FILE. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos…), file transfer resume, proxy tunneling and a busload of other useful tricks.

In pratica, cURL è un’applicazione che funziona da prompt dei comandi e consente il trasferimento di file trasmettendo richieste sotto forma di URL. La libreria cURL può essere richiamata anche via PHP.

L’applicazione è supportata nativamente dai sistemi *nix, mentre va istallata sui sistemi Win e Mac.

Non mi soffermerò sul download e sull’istallazione di cURL per sistemi non *nix, rinviandovi all’ottimo tutorial di effetti collaterali.

Il mio suggerimento è, ovviamente, quello di utilizzare un servizio di hosting Linux. Se lavorate in locale, l’optimum è sempre LAMPP per Linux. Su un sistema Linux non c’è bisogno, come detto, di istallare cURL.

Se proprio non avete a portata di mano un sistema Linux, scaricate il pacchetto XAMPP (di XAMPP ho parlato qui).

Una volta istallato il server, con un semplice phpinfo() potrete verificare la presenza della libreria:

curl

Quando invocheremo le API dei vari servizi, seguiremo sempre lo stesso schema:

  • definizione dei parametri da trasmettere
  • connessione alla libreria curl
  • trasmissione della richiesta via curl
  • prelievo dei dati di risposta
  • manipolazione dei dati
  • output a video

Visto che dedichiamo a cURL questo post, vediamo come si accede alla libreria via PHP:

$url = "http://www.miosito.com/params";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
curl_close($ch);

$url è la URL della richiesta. La URL può contenere o meno una serie di parametri aggiuntivi. Questi possono essere definiti nella URL, ma possono anche essere impostati successivamente, con curl_setopt().
curl_init() apre la connessione a curl; curl_setopt() imposta una serie di opzioni. Nel primo (semplicissimo) esempio qui sopra, CURLOPT_RETURNTRANSFER chiede in risposta una stringa di testo (nei prossimi post vedremo perchè), mentre CURLOPT_URL passa a cURL la URL (con o senza i parametri); curl_exec() esegue la richiesta e curl_close() chiude la connessione.

Un elenco completo dei parametri, lo trovate qui.

Ora che abbiamo il materiale, possiamo passare alle prime richieste.

Continua…