WordUp Poznań #9


Programowanie obiektowe w WordPressie

Zalety programowania obiektowego

  • Zgodność z rzeczywistością
  • Reużywalność poszczególnych komponentów
  • Ułatwiona współpraca wielu programistów
  • Szybsze wdrożenie nowych programistów do projektu
  • Oszczędność czasu i pieniędzy

Podejście do programowania obietkowego w Wordpress

  • Kwestia legacy code
  • Programowanie proceduralne
  • Motywy i wtyczki

Jakie elementy w ekosystemie WordPress są napisane w sposób obiektowy

  • Rdzeń CMS WordPress
  • Większość dużych wtyczek
  • Spora część komercyjnych tematów
  • Część API WordPressa

Klasy wbudowane w Wordpress

  • WP_Query, WP_User, WP_Post, WP_Error, WP_User_Query, WP_Theme, WP Styles, wpdb itp..
  • Każda klasa ma zdefiniowane metody i właściwości
  • Często wbudowane metody to odpowiedniki zwykłych funkcji globalnych

Przykład wywołania klasy WP_User

$user = new WP_User( 1 );

echo $user->user_login;

echo $user->user_email;

echo $user->ID;

print_r($user->get_role_caps());

Przestrzenie nazw

  • Dostępne od PHP 5.3 (30 Czerwca 2009)
  • Mniejsze ryzyko zdefiniowania drugi raz tej samej klasy
  • Mapowanie na pliki i katalogi
  • Oszczędnośc pamięci dzięki metodzie automatycznego ładowania klas

Plik function.php

new \Utils\ClassName;
					

Plik z klasą
(katalog Utils, plik ClassName.php)

namespace Utils
class ClassName{
	...
}

Obiektowe wywoływanie metod wbudowanych w Wordpress

class ClassName(){

	__construct (){
		add_action( 'admin_menu', array($this, 'test_plugin' ));
	}

	test_plugin function (){
		...
	}
}						
					

Metody dostępowe (gettery i settery)

  • Pobieranie i ustawianie tylko dozwolonych właściwości obiektu
  • Ułatwienie filtrowania i walidacji danych
  • Ograniczenie ryzyka popełnienia błędu
  • Ograniczenie powtarzania kodu

Przykład gettera i settera

class Person
{
	private $name;
	private $surname;
		              
	public function setFullName($name, $surname)
	{
		$this->name = $name;
		$this->surname = $surname;
	} // end setFullName();
	               
	public function getFullName()
	{
		return $this->name.' '.$this->surname;               
	} // end getFullName();  
}

Metody magiczne

  • Możliwość operowania na metodach i właściwościach, które nie zostały zdefiniowane
  • Ograncznie ilości pisanego kodu
  • Mniejsza czytelność
  • Problem z podpowiadaniem składni w edytorach
  • Mechanizm charakterystyczny dla PHP

Setter i getter metody magiczne

class MyClass {
	private $firstField;
	private $secondField;

	public function __get($property) {
		if (property_exists($this, $property)) {
			return $this->$property;
		}
	}

	public function __set($property, $value) {
		if (property_exists($this, $property)) {
			$this->$property = $value;
   		}

		return $this;
	}
}	

Autoładowanie klas

  • Poprawa wydajności
  • Większa czytelność
  • Możliwość ładowania dodatkowej logiki
  • Możliwość podzielenia projektu na mniejsze częśći
  • Możliwość ładowania pakietów za pomocą Composera

Przykład automacznego ładowania klas

 function myClassLoader($className)
 {
    echo 'Ładuję klasę '.$className;
    require('./'.$className.'.php');
 
    // Zwróć "true", informując, że klasa została znaleziona.
    return true;
 } // end myClassLoader();
 
 spl_autoload_register('myClassLoader');
 
 // Możemy od razu korzystać z klas
 $obiekt1 = new Klasa1;
 $obiekt2 = new Klasa2;
 $obiekt3 = new Klasa1;
					

Wzorce projektowe

  • Wspólne dla większośći obiektowych języków programowania
  • Nie jest są to gotowe rozwiązania
  • Jest to sposób pokonania ograniczeń związanych z dziedzieczeniem klas
  • Wzorce są nazwami na rozwiązania pewnych problemów w większych aplikacjach
  • Przykłady wzorców: singleton, fabyka, strategia, fabryka abstrakcyjna, decorator, dependency injection, obserwator

Wzorzec fabryka

  • Wzorzec metody wytwórczej dostarcza abstrakcji do tworzenia obiektów powiązanych typów
  • Umożliwia także dziedziczącym klasom decydowanie jakiego typu ma to być obiekt

Przykład wzorca fabryka

interface Pizza{
    public function getName();
}
class HawaiianPizza implements Pizza{
    public function getName() {
        return "Hawalian pizza";
    }
}
class DeluxePizza implements Pizza{
    public function getName() {
        return "Deluxe pizza";
    }
}
 
// Kreator tworzacy obiekt produktu
interface Creator{
    public function create($type);
}
class ConcreteCreator implements Creator{
    public function create($type) {
        switch($type) {
            case 'Hawalian':
                return new HawaiianPizza();
                break;
            case 'Deluxe':
                return new DeluxePizza();
                break;
        }
    }
}
				

Przykład wzorca fabryka - wywołanie

$creator = new ConcreteCreator();
$prod1 = $creator->create("Hawalian");
$prod2 = $creator->create("Deluxe");
echo $prod1->getName(); // wyswietli "Hawalian pizza"
echo $prod2->getName(); // wyswietli "Deluxe pizza"
					

Dziękuję za uwagę

Mail: marekwozniak1@gmail.com

Przydatne linki: