În Tutoriale

Crearea unei teme WordPress: dezvoltarea temei (II)

temă de wordpress

În prima parte a tutorialului, am discutat despre lucrurile de bază, necesare dezvoltării unei teme WordPress. Am aflat că nu avem nevoie de cunoștințe avansate de programare, iar crearea unei teme WordPress nu este chiar un lucru greu de făcut, dar pentru a face o tema perfectă, trebuie să muncim puțin.

Dacă deja ai experiență în programare web și deții cunoștințe solide de PHP și MySQL, programarea folosind platforma WordPress îți poate părea puțin banală. Sunt de acord cu tine, sunt aspecte în WordPress care au fost construite folosind nu tocmai cele mai bune practici. Acest lucru se datorează faptului că evoluția platformei a fost uimitor de rapidă. Sunt sigur că în timp se vor găsi soluții pentru rezolvarea tuturor problemelor.

La începutul primei părți ale tutorialului am specificat că sunt necesare cunoștințe minime de PHP, HTML si CSS, de aceea aici nu vom prezenta un tutorial step by step. În cazul în care nu deții cunoștințele minime necesare, îți recomand să citești bazele pe website-ul php.net sau w3schools.com și să revii pentru a putea termina tutorialul.

WordPress Development Workflow

Workflow-ul nu este unul prestabilit – acesta se face în funcție de preferințele fiecărui programator sau în funcție de necesitățile proiectului.

Workflow-ul folosit în această temă este unul simplu. Am început prin conversia designului în fișiere HTML/CSS, apoi am folosit codul HTML împreună cu funcțiile PHP să construiesc tema. Desigur, am avut în minte anumite reguli de structură explicate deja în prima parte a tutorialului.

După crearea fișierelor HTML/CSS, am mutat resursele folosite în fișierele HTML/CSS (fișiere de stil, fișiere JS, imagini etc.) în folderul temei și am împărțit codul HTML în template-urile necesare temei WordPress, apoi le-am conectat între ele folosind funcțiile oferite de WordPress (numite Template Tags). A rezultat structura prezentată mai jos.

Pașii pe care o să îi parcurgem sunt foarte simpli, iar dacă tema însăși este simplă nu trebuie să folosim un workflow complicat.

rohastheme/
| -- assets/
     | -- css
          | -- main.css
     | -- images
     | -- js
          | -- scripts.js
     | -- scss
          | -- _cf.scss
          | -- _colors.scss
          | -- _mixins.scss
          | -- _reset.scss
          | -- style.scss
| -- parts/
     | -- content-page.php
     | -- content-post.php
     | -- content-single.php
| -- archive.php
| -- comments.php
| -- footer.php
| -- functions.php
| -- header.php
| -- index.php
| -- page.php
| -- search.php
| -- single.php
| -- style.css

SCSS + Grunt + WordPress = LOVE

Pentru codarea designului HTML/CSS am folosit preprocesorul CSS, SCSS compilat cu ajutorul Grunt-ului. În repository-ul temei o să găsiți și fișierul de configurare Grunt.

Pentru a integra fișierele SCSS cu WordPress am separat fișierele .css generate de SCSS, de fișierul style.css necesar temei, dar am inclus fișierul main.css aflat în /assets/css/main.css generat în fișierul principal.

Hello World!

Ca să rezulte o temă WordPress funcțională, trebuie să începem prin codarea fișierelor necesare. Fișierul style.css necesită un set de comentarii CSS la începutul fișierului care stabilesc numele, slug-ul, descrierea, autorul, tag-urile sau versiunea temei. Mai jos se poate vedea un exemplu al fișierul style.css.

/*
Theme Name: Rohas Theme
Theme URI: http://hapiucrobert.ro
Author: Hapiuc Robert
Author URI: http://hapiucrobert.ro
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: rohas
Version: 1.0.0
*/
@import url("assets/css/main.css");

În index.php putem scrie un voios Hello World! apoi mergem în Dashboard > Appearance, căutăm tema noastră și o activăm.

Header & Footer

Deoarece presupun că v-ați documentat despre structura temei WordPress și presupun că aveți deschisă diagrama cu ierarhia template-urilor și Codex-ul, este timpul să începem cu cele mai repetitive și importante părți ale temei.

Începem prin copierea HTML-ului necesar pentru header și footer în fișierele specifice din temă, header.php si footer.php.

Header

HTML-ul pentru header se găsește aici iar aici este fișierul header.php final. Acum să discutăm ce s-a întâmplat în fișier.

Pe tag-ul <html> am adăugat funcția language_attributes() care returnează atributele dir și lang conform setărilor de limbă făcute ulterior de către utilizator în dashboard.

Folosind funcția bloginfo() cu parametrul ‘charset’ am returnat tipul de caractere în header-ul fișierului. Funcția are o mulțime de alți parametri utili, te invit sa îi citești în codex.

Iar la sfârșitul tag-ului <head> observăm funcția wp_head() care nu pare să facă nimic, dar ea este foarte importantă și necesară. Funcția este defapt un hook, adică un cârlig care permite altor funcții să se execute în acel loc specific, o să acoperim această parte (hooks, actions și filters) a WordPress-ului într-o lecție viitoare. În cazul de față, funcția wp_head() face output la fișierele .css, fișierele .js sau la titlul paginii, lucruri pe care o să le setăm în fișierul functions.php folosind alte funcții specifice.

Observăm pe tag-ul <body> o funcție numită body_class(), aceasta returnează diverse clase CSS în mod automat. Clasele sunt specifice paginii pe care te afli și te pot ajuta la identificarea unei pagini, page-template, custom post type sau tip de arhivă în CSS.

Pentru a afișa imaginea de fundal din header o să ne folosim de funcția header_image(), care returnează URL-ul imaginii adăugate in Appearance > Customizer > Header Image.

Trebuie să menționez că funcția nu funcționează singură. Înainte să returnăm URL-ul imaginii trebuie să declarăm suportul pentru această funcție în functions.php. O să discutăm despre theme support functions puțin mai jos.

Începând de la linia 14 din fișierul header.php avem logo-ul temei, care este format din numele website-ului și descrierea acestuia, scoatem informațiile din baza de date folosind funcția bloginfo() amintită mai sus.

Ca tema să suporte meniuri de navigare, trebuie să le declarăm în functions.php la fel ca în cazul imaginii din header. Fiecare meniu va fi definit folosind un ID unic, în cazul nostru acesta este ‘header_menu’. Am atribuit numele meniului ca și string unei variabile pentru a menține codul mai curat. Apoi verificăm dacă meniul există, folosind funcția has_nav_menu() care acceptă ca parametru numele meniului și returnează o valoare de tip bool. Urmează apoi să afisăm meniul folosind funcția wp_menu_nav() căreia îi asignăm un array cu două valori, prima fiind numele meniului pe care dorim să îl afișăm, iar cu al doilea ne alegem ce fel de container (div, ul etc) dorim. Noi deja avem un container #main_navigation și nu dorim să folosim containerul oferit de WordPress, așa că lăsăm valoarea goală dar definită. În cazul în care nu o definim, valoarea default va fi folosită. Facem această verificare din cauză că nu dorim să afișăm un meniu gol sau mark-up nedorit.

Footer & Sidebars

HTML-ul pentru footer se află aici, iar aici se află fișierul footer.php final.

Footer-ul nostru conține trei sidebar-uri, împărțite în trei coloane și o secțiune de copyright. Este necesar să definim fiecare sidebar și în functions.php folosind un ID unic. Deoarece avem trei coloane, trebuie să ținem cont de mai multe aspecte când facem output la sidebar-uri. În cazul de față, acestea sunt:

  1. Rămâne markup nefolosit dacă nu există nici un sidebar activ?
  2. Rămâne markup nefolosit dacă nu există unul sau mai multe sidebar-uri active?
  3. Se strică designul dacă nu există unul sau mai multe sidebar-uri active?

Ca să prevenim cele trei edge-case-uri, trebuie să verificăm dacă oricare dintre cele trei sidebar-uri este activ. Dacă este, returnăm wrapper-ul HTML și sidebar-urile. Apoi verificăm câte dintre acele sidebar-uri sunt active și atribuim valoarea unei clase css. Iar la final verificăm dacă acel sidebar specific există și îl returnăm.

Pentru a obține rezultatul de mai sus într-un mod elegant, atribuim valorile returnate de funcția is_active_sidebar() (funcție care acceptă ca și parametru ID-ul sidebar-ului și returnează valoare de tip bool) unui array. Apoi ca să numărăm câte sidebar-uri sunt disponibile, trebuie să numărăm cate valori de true sunt în array. Am făcut asta folosind funcția count() pe rezultatul funcției array_filter(). Funcția în mod normal este folosită pentru a filtra un array folosind condițiile definite într-o altă funcție și folosită pe post de callback, dar în documentație era specificat faptul că funcția returnează numai valorile true, așa că am folosit funcția fără un call back și am obținut rezultatul dorit. De aici, lucrurile se simplifică.

Urmează să verificăm dacă fiecare dintre sidebar-uri există și să facem echo la wrapper, să atribuim numărul de coloane unei variabile și să facem output la sidebar folosind funcția dynamic_sidebar(), care acceptă ca parametru ID-ul sidebar-ului.

La final avem secțiunea de copyright, unde am folosit funcția bloginfo() și funcția date(), pentru a returna anul curent.

Întâlnim și în footer.php același tip de hook ca în header.php, wp_footer() este un hook necesar. Acesta împreună cu wp_head() nu trebuie să lipsească din temele create de voi.
După ce avem structura fișierelor header.php și footer.php pregătită, putem începe să adăugăm restul setărilor ca să facem tema funcțională, deoarece în acest moment nu sunt definite sidebar-urile, meniul, fișierele de stil sau fișierele JavaScript. Toate acestea le vom face în fișierul destinat funcțiilor, functions.php.

Functions

Fișierul functions.php este responsabil pentru setarea temei noastre. În el urmează să înregistrăm fișierele de stil, fișierele JavaScript, sidebar-urile, meniul din header și alte funcții custom.

Practic, acest fișier se comportă ca un plugin WordPress, doar că funcțiile definite în el sunt disponibile numai în tema din care face parte și nu pot fi dezactivate din Dashboard ca orice alt plugin obișnuit.

 

Mini introducere în ‘hooks’

Deși o să discutam despre ‘hooks, actions și filters’ într-o lecție viitoare, trebuie să fac o mică introducere acum, ca să putem continua tutorialul.

Un hook este o funcție care îți permite să te legi de un anumit loc sau să modifici o anumită funcție. Hook-urile sunt de două feluri, action hooks și filter hooks.

Un hook de tip action îți permite să execuți alte funcții în locul în care hook-ul este declarat, de exemplu mai sus am discutat despre wp_head() și wp_footer(). Acestea două sunt cele mai importante action hook-uri disponibile în WordPress.

Dacă doresc să execut banala funcție “Hello World!” în locul unde este plasat wp_head(), trimit către acest hook rezultatul unei alte funcții custom folosind funcția add_action().
În schimb, un hook de tip filter îți permite să alterezi conținutul unei expresii.

Theme Setup

Ca tema noastră să beneficieze de funcționalități precum featured image sau menus, trebuie ca noi să le definim într-o funcție și să inițiem funcția imediat ce tema este activată în Dashboard. Ca să inițiem funcția imediat ce tema este activată, trebuie să facem un action hook pe ‘after_setup_theme’ astfel:

function rohas_theme_setup() {
//Functionalitati
}
add_action( 'after_setup_theme', 'rohas_theme_setup' );

În cazul de față, ne interesează ca în funcția rohas_theme_setup() să adăugăm toate funcțiile de add_theme_support(), meniurile și să definim variabila $content_width. Theme Support Deoarece nu toate temele împărtășesc aceleași funcționalități, WordPress ne-a pus la dispoziție încă din versiunea 2.9 funcția add_theme_support() cu ajutorul căreia definim ce funcționalități deja existente în WordPress va suporta tema noastră. Funcția acceptă numele unui anumit feature (lista cu toate funcționalitățile disponibile se găsește în codex) și atributele acesteia. În tema noastră, am folosit această funcție să definim următoarele funcționalități: ‘title-tag’ Adaugă tag-ul <title> în head-ul fiecărui fișier. Această metodă se folosește pentru a maximiza flexibilitatea titlului, astfel dacă ulterior doriți să faceți modificări la structura titlului, o puteți face folosind un filter hook. ‘post-thumbnail’ Folosit pentru a permite adăugarea de post thumbnail sau featured image la postări. imagine featured ‘custom-header’ Deși numele nu este foarte sugestiv, funcționalitatea constă în posibilitatea de a adauga imagine de fundal pentru header. Dupa ce definiți acest theme support, veți putea adăuga imaginea in Appearance > Customize > Header Image header image Observăm că pentru această funcționalitate am adăugat și câteva atribute într-un array, și anume ‘height’ și ‘default-image’. Asta înseamnă că în momentul în care utilizatorul urcă o imagine cu o înălțime mai mare decât cea definită aici, va fi îndrumat să facă resize la imagine. Iar dacă utilizatorul nu adaugă nicio imagine, imaginea definita ca și ‘default-image’ va fi folosită. NOTĂ: Atributele se pot defini in-line cu un array ca și parametru al funcției sau cu o variabilă care ține un array, ca în cazul de față. ‘html5’ Aceasta soluție a fost implementată în versiunea 3.6. În acest parametru definim tipul de mark-up returnat de WordPress pentru anumite secțiuni și funcționalități. Această soluție a fost abordată în acest mod din cauza compatibilității cu temele deja existente (backwards compatibility). Dacă se implementa noul mark-up fără această soluție, temele făcute până la lansarea versiunii 3.6 erau forțate să facă update la mark-up, lucru aproape imposibil din cauza existenței al unui procent mare de teme bune, dar neîntreținute în repository-ul wordpress.org. Practic soluția este pentru temele noi. (la acestă funcție avem și un exemplu de atribut definit in-line)

$custom_header_args = array(
 'height' => 222,
 'default-image' => get_template_directory_uri() . '/assets/images/header_image.jpg',
 );
 //Theme Support
 add_theme_support( 'title-tag' );
 add_theme_support( 'post-thumbnails' );
 add_theme_support( 'custom-header', $custom_header_args );
 add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption') );

Meniuri

Înregistrarea meniurilor se face cu ajutorul funcției register_nav_menus(), funcție care acceptă ca și parametru un array asociativ. Fiecare poziție a array-ului reprezintă un array unde key-ul array-ul este ID-ul meniului, iar valoarea este numele lui.

register_nav_menus( array(
 'header_menu' => esc_html__( 'Header Menu', 'rohas' )
 ) );

Content Width

Cel mai des am întâlnit developeri care nu au auzit de variabila $content_width sau care pur și simplu nu au definit-o. Durează foarte putin să o definești, 3 linii de cod mai exact, dar va ajuta viitorii programatori care vor interacționa cu tema. Variabila stabilește lătimea div-ului în care este făcut output la conținut. Astfel WordPress va seta un width maxim pentru imaginile din postarea ta, dar și pentru alte tipuri de conținut. Iar dacă ai nevoie de această valoare într-o variabilă PHP, o ai disponibilă, evitând un întreg ciclu de preluare a lățimii din front-end sau direct din CSS.

Stiluri

Tema noastră încă nu a prins prea mult contur în acest pas, probabil din cauză că lipsesc stilurile, fișierele JavaScript și conținutul. Pentru a adăuga un stil în WordPress, este necesar să înregistrăm stilul și să îl adăugăm în coada de dependințe. Știu că sună foarte ciudat această procedură, dar și înregistrarea și punerea în coadă se fac folosind o singură funcție wp_enqueue_style(), care ne va ușura munca în această privință. Dependințele de stiluri sau scripturi JS sunt necesare pentru a evita conflictele cauzate de modalitatea de încărcare a DOM-ului. Presupun că știți deja că DOM-ul se încarcă de sus în jos, linie cu linie, iar dacă stilul widgets.css se folosește de sidebars.css, acesta trebuie să se încarce mereu după sidebars.css, dacă se va încărca înaintea lui cu siguranță nu va funcționa corect. Odată cu crearea unei dependințe, este necesar să și înregistrăm stilul în temă. Înregistrarea înseamnă că stilul va fi disponibil într-un array ținut de o variabilă globală $wp_styles, respectiv $wp_scripts. Asta înseamnă că dacă dorim eliminarea unui fișier CSS adăugat în front-end de către un plugin, avem posibilitatea să facem asta folosind ID-ul fișierului și funcția wp_dequeue_style(), funcție care va elimina stilul din variabila globală. Acum să discutăm puțin despre această funcție și despre parametrii acesteia. Pentru fiecare stil pe care dorim să îl adăugăm, o să folosim această funcție. Astfel, mulțimea de funcții cu stiluri o punem într-o altă funcție, pe care o vom folosi apoi ca și call-back pentru action hook-ul ‘wp_enqueue_scripts’.  
Funcția wp_enqueue_style($handle, $src, $deps, $ver, $media) acceptă cinci parametri adăugați în aceeași ordine ca în exemplu.

$handle

Este de tip string și reprezintă ID-ul de identificare al stilului. ID-ul este necesar să fie unic. De foarte multe ori, ID-ul “style” este folosit în cazul temelor. Vă recomand folosirea unui ID unic.

$src

Este de tip string și reprezintă calea (URL-ul) către fișierul CSS.

$deps

Este de tip array și reprezintă dependințele fișierului. Se completează fiecare poziție din array cu ID-ul fișierelor deja înregistrate. Dacă dorim ca fișierul nostru să fie încărcat după fișierele cu ID-urile ‘general-style’ și ‘another-style’, atunci valoarea array-ul va fi array(‘general-style’, ‘another-style’).

$ver

Este de tip string și reprezintă versiunea fișierului CSS.

$media

Este de tip string și reprezintă mediul media pentru care este destinat fișierul CSS ‘aural’, ‘braille’, ‘handheld’, ‘projection’, ‘print’, ‘screen’, ‘tty’, sau ‘tv’. Valoarea default este ‘all’.

Din perspectiva codului/documentației, numai primul argument $handle este necesar, dar pentru a adăuga un stil/script funcțional este necesar și al 2-lea atribut $src, ceea ce ne creează o excepție de la regulă pentru stilul principal. Stilul principal al temei (style.css localizat în root-ul temei) nu are nevoie și de restul dependințelor, el se poate înregistra numai cu id-ul și src-ul.

La final, hook-ul nostru care înregistrează stiluri va arăta astfel:

function rohas_styles() {
 wp_enqueue_style( 'main-style', get_stylesheet_uri() );
 wp_enqueue_style( 'font-awesome', '//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css', array('main-style'), '4.5.0');
}
add_action( 'wp_enqueue_scripts', 'rohas_styles' );

Scripturi JavaScript

Adăugarea scripturilor JavaScript este foarte asemanătoare cu cea a stilurilor. Se schimba numai numele funcției și un atribut. Funcția care ne ajută sa adăugăm scripturi este wp_enqueue_script(), acceptă aceiași parametrii ca și wp_enqueue_style() cu excepția unuia, parametrul $media. Ultimul parametru din funcție este $in_footer, de tip boolean cu valoarea default false, pe care dacă îl setăm true, ne va adăuga scriptul în footer și nu în header.

Dacă la stiluri aveam o metodă simplificată să adăugăm stilul principal, la scripturi nu avem o metodă pentru înregistrarea fișierului jQuery. Dacă avem un fișier JS care se folosește de jQuery, pur și simplu când înregistrăm respectivul fișier, adăugăm în parametrul de dependințe ID-ul fișierul jQuery, care este ‘jquery’ .

Numele hook-ului rămâne la fel.

function rohas_scripts() {
 wp_enqueue_script( 'scripts', get_template_directory_uri() . '/assets/js/scripts.js', array('jquery'), '1.0', true );
}
add_action( 'wp_enqueue_scripts', 'rohas_scripts' );

Sidebars

Un sidebar este o locație unde se pot adăuga Widget-uri din Dashboard > Appearance > Widgets. Un sidebar se înregistrează prin aceeași pași prin care am înregistrat și stilurile sau scripturile, adică folosind un grup de funcții puse într-un call-back al unui hook.

Funcția necesară pentru înregistrarea unui sidebar este register_sidebar() și acceptă un singur parametru, un array asociativ care nu este neapărat necesar. Array-ul asociativ are următoarele key-uri:

name – Numele sidebar-ului

id – Cheie de identificare unică a sidebar-ului

description – Descrierea sidebar-ului

class – Clasa CSS care va fi afișată numai în dashboard, nu și în front-end. Foarte folositor parametrul când se creează sidebar-uri în cadrul unui plugin

before_widget – Cod HTML care va fi afișat înainte de fiecare widget în parte. Cel mai probabil un tag <div>. Acceptă sprintf() cu doi parametri  %1$s pentru afișarea ID-ului și %2$s pentru afișarea claselor specifice

after_widget – Cod HTML afișat la sfarșitul fiecărui widget. Aici se poate închide div-ul deschis în before_widget

before_title –  Cod HTML afișat înainte de titlul widget-ului

after_title – Cod HTML afișat după titlul widget-ului

Eu am ales să definesc array-ul în exteriorul funcției și să adaug variabila ca și parametru în funcție, astfel codul se menține mai curat.

Până în acest punct am acoperit funcțiile de bază ale unei teme WordPress, necesare pentru funcționarea temei. În următoarea lecție o să integrăm paginile necesare pentru afișarea conținutului.