Composer to dzisiaj bez wątpienia podstawa każdego projektu w PHP. Dzięki Composerowi nie tylko dodamy interesujące nas biblioteki, ale też m.in. zarządzimy przestrzeniami nazw (ang. namespace). Dodatkowo Composer wczytuje za nas (ang. autoload) wszystkie plików PHP w naszym projekcie. Żeby to lepiej zrozumieć, stwórzmy prosty projekt.

Nowy projekt w Composer

Naszym prostym projektem będzie wyświetlanie kursu walut. Zaczniemy zatem wchodząc do pustego folderu projektu i wpisując komendę:
composer init

Zostaniemy spytani najpierw o Package name. Z założenia używa się nazwy w formacie „<vendor>/<name>”, co oznacza, że jeśli np. publikujemy kod na GitHub, to <vendor> będzie nazwa użytkownika lub organizacji (w moim przypadku luklewluk), a <name> to po prostu będzie nazwa repozytorium, dowolna pasująca do projektu czyli na przykład „exchange”. Czyli pełna nazwa: luklewluk/exchange .

Żeby nie utrudniać sobie na początek, to każde kolejne pytanie możemy na razie pominąć, zwłaszcza, że nie będzie to projekt publiczny 😄
Pytanie, którego nie chcemy pominąć to pytanie odnośnie PSR-4:
Add PSR-4 autoload mapping? Maps namespace „Luklewluk\Exchange” to the entered relative path. [src/, n to skip]:.
Naciskamy Enter, gdyż chcemy dodać PSR-4 autoload. Później wyjaśnię dlaczego.

Po tej operacji, powinniśmy mieć wygenerowany plik „composer.json” oraz folder „vendor”. Następnie tworzymy plik PHP przez który wystartujemy projekt. Nazwijmy go „run.php”. Teraz zgodnie z podpowiedzią którą otrzymaliśmy na koniec, powinniśmy „zaincludować” autoloader Composera w naszym projekcie dodając:
require 'vendor/autoload.php';

Dodawanie bibliotek do projektu

Tak jak założyliśmy, nasza aplikacja powinna pokazywać nam kurs walut, np. ile PLN musimy zapłacić za 1 EUR. Najprościej możemy to rozwiązać znajdując interesującą nas bibliotekę i dodając ją do naszego projektu. Żeby znaleźć bibliotekę można wejść na stronę repozytorium paczek dla PHP czyli Packagist i użyć tamtejszej wyszukiwarki. Dla uproszczenia niech to będzie kurs NBP, gdyż dostęp do ich API jest publiczny, bez wymogu rejestracji. W wyszukiwarce Packagista wpisuję więc „nbp”:



Najpopularniejsza obecnie biblioteka to maciej-sz/nbp-php. Żeby ją dodać do naszego projektu wpisujemy komendę:
composer require maciej-sz/nbp-php



Gdy biblioteka została prawidłowo dodana, to możemy zacząć z niej korzystać. Gdy korzystamy z zewnętrznych bibliotek, należy korzystać z ich dokumentacji, gdyż wtedy dowiemy się, jak możemy daną bibliotekę zaimplementować w naszym kodzie. W naszym przypadku dodajemy do naszego pliku run.php następujące linie:

$nbp = new \MaciejSz\NbpPhp\NbpRepository();
$currencyData = $nbp->getRate('2023-01-25', 'EUR');

echo $currencyData->avg;

Powyższym kodem sprawdzamy średni kurs NBP dla Euro, z dnia 25 stycznia 2023. Po uruchomieniu naszego skryptu powinniśmy zobaczyć wartość 4.7079:

Tworzenie klas

Mamy już działający kod, używający zewnętrznej biblioteki. Można więc w tym miejscu skończyć wpis, ale jeśli dobrze pamiętacie, to przy tworzeniu projektu przez komendę composer init, na końcu poprosiliśmy o stworzenie dla nas „autoloadera PSR-4”. Dzięki temu, do naszego composer.json zostały dodane następujące linie:

    "autoload": {
        "psr-4": {
            "Luklewluk\\Exchange\\": "src/"
        }
    },

Przeanalizujemy je po kolei:
1) Autoload – ustawienie, że są pliki PHP w naszym projekcie, które byśmy chcieli „includować”
2) PSR-4 – to metoda jaką użyje Composer do autoloadingu. Można więcej poczytać o niej tutaj
3) „Luklewluk\\Exchange\\” – oznacza, że Composer zarezerwował namespace dla moich klas w PHP
4) „src/” – to nic innego jak folder, w którym będą znajdować się pliki projektu

Wiem że obecnie może nie być to zbyt jasne, dlatego przejdźmy od razu do praktyki 😄

Zacznijmy od stworzenia folderu „src”, a w tym projekcie stwórzmy klasę Rate. Prawidłowy plik src/Rate.php będzie wyglądać tak:

<?php

namespace Luklewluk\Exchange;

class Rate
{

}

Do tej pustej klasy dodajmy metodę „getEurRate”, której zadaniem będzie zwracać nam kurs Euro. Metoda jako argument niech przyjmuje datę w formacie string oraz niech zwraca wartość kursu też w jako string.
Przenosząc wcześniejszą logikę z pliku run.php, nasza klasa będzie wyglądać tak:

<?php

namespace Luklewluk\Exchange;

use MaciejSz\NbpPhp\NbpRepository;

class Rate
{
    public function getEurRate(string $date): string
    {
        $nbp = new NbpRepository();
        $currencyData = $nbp->getRate($date, 'EUR');

        return $currencyData->avg;
    }
}

Klasa Rate jest już ukończona i gotowa do używania.
Ważna uwaga: Tak na prawdę, powinniśmy tutaj zastosować DI (Dependency Injection), czyli obiekt NbpRepository powinien być „wstrzyknięty” w konstruktorze klasy. Zrobiłem więc małe uproszczenie, gdyż temat DI poruszę głębiej w jednym z kolejnych wpisów.

Wracamy do naszego pliku run.php, zmieniamy go by odwoływał się jedynie do naszej klasy, którą właśnie utworzyliśmy:

<?php

require_once 'vendor/autoload.php';

$rate = new \Luklewluk\Exchange\Rate();
echo $rate->getEurRate('2023-01-26');

Zmieniłem dodatkowo datę odczytu kursu z 25 na 26 stycznia, by wynik nieco różnił się od poprzedniego. Kod uruchamiamy tak samo jak wcześniej, czyli używając „php run.php”.

Podsumowanie

Tematy poruszone w tym wpisie są absolutnym fundamentem w tworzeniu aplikacji w PHP. Jeśli zaczynacie pracę z dowolnym frameworkiem, projekt praktycznie zawsze będzie korzystać z Composera. Jest to ogromne ułatwienie, gdyż jak widzicie, napisaliśmy działającą i użyteczną aplikację, pisząc minimalną ilość kodu.

Jeśli chodzi o kwestie związane z klasami, to obecna praktyka w PHP nakazuje pisać jedynie obiektowo (pomijamy tu wyjątki od reguły typu WordPress). Możesz też zauważyć, że Composer w pewien sposób też narzuca OOP (Object-Oriented Programming). Zaznaczę tutaj, że rozpoczynając przygodę z innymi językami np. Java lub C#, również od razu zostaniemy wrzucani na głęboką wodę, czyli pisanie kodu w klasach. Dlatego im wcześniej zaczniecie korzystać z obiektów, tym lepiej dla Was 💪

Related Posts