#API – Dalszy ciąg ewolucji – FOS REST Bundle i małe podsumowanie

Ten post miał pojawić się wcześniej, ale ze względu na  inne zajęcia nie zdążyłem przygotować go do publikacji i umieściłem szybki post, żeby być spokojnym o wymagane 2 posty tygodniowo. Przez ten czas praca poszła już sporo naprzód, więc ten post, będzie trochę takim podsumowaniem. Kiedy zaczynałem prace nad aplikacją, nie chciałem używać żadnych dodatkowych pomocy i tyle na ile to możliwe, chciałem większość napisać sam.

Widząc swoje postępy w pisaniu, doszedłem do wniosku, że mogę się nie wyrobić i stwierdziłem, że chociaż spróbuję skorzystać z tego ułatwienia, do którego byłem tak sceptycznie nastawiony. Okazało się, że wykorzystanie FOSRestBundle w projekcie było strzałem w dziesiątkę. Nie muszę martwić się o routing, czy strony błędów, ponieważ FOSRest robi sporo rzeczy za mnie, więc mogę się skupić na ważniejszych kwestiach. Ogólnie myślę, że trochę chciałem wyważyć otwarte drzwi. Kiedyś na pewno będę chciał napisać większą aplikację w czystym PHP, z wykorzystaniem jedynie wzorców projektowych, PSR itp., żeby polepszyć swoje umiejętności, ale jeszcze nie teraz. Teraz zaufam temu, co wymyślili bardziej doświadczeni.

Instalacja FOS REST, nie różni się niczym od instalacji innych bundle’i. Należy dodać odpowiednią linijkę do composer.json:

//...
"friendsofsymfony/rest-bundle": "^1.7",
//...

a następnie zaktualizować pakiety i dodać odpowiednią linijkę do pliku AppKernel.php, w $bundles:

//...
new FOS\RestBundle\FOSRestBundle(),
//...

Teraz jeszcze tylko konfiguracja w pliku confg.yml:

# FOS REST Bundle
fos_rest:
 body_listener: true
 param_fetcher_listener: true
 view:
 view_response_listener: 'force'
 exception_wrapper_handler: null
 formats:
 jsonp: true
 json: true
 xml: false
 rss: false
 mime_types:
 json: ['application/json', 'application/x-json']
 jpg: 'image/jpeg'
 png: 'image/png'
 jsonp_handler: ~
 routing_loader:
 default_format: json
 include_format: false
 format_listener:
 rules:
 - { path: ^/, priorities: [ json, jsonp ], fallback_format: ~, prefer_extension: true }
 exception:
 enabled: true

Po jego instalacji wszystkie kontrolery odpowiedzialne za API muszę rozszerzać FOSRestController’em, oraz muszę implementować ClassResourceInterface.

Jeśli chodzi o routing, to jedynie muszę się trzymać odpowiedniego nazewnictwa metod:

//...
public function cgetAction()
{} // "get_users"     [GET] /users

public function newAction()
{} // "new_users"     [GET] /users/new

public function getAction($slug)
{} // "get_user"      [GET] /users/{slug}

// ...
public function getCommentsAction($slug)
{} // "get_user_comments"    [GET] /users/{slug}/comments

// ...

I dla każdego kontrolera dopisać  z odpowiedne przekierowanie w routing_api.yml.

Ogólnie FOS REST, znacznie przyspieszył pracę nad projektem. W jeden dzień napisałem praktycznie od zera kontroler dokumentów. Poprzednimi metodami, w tydzień nawet tego jednego nie skończyłem. Do tego zaczęła działać metoda $this->getUser()->getId(), która wcześniej nie wiedzieć czemu, nie działała. Wymyśliłem pewne rozwiązanie tego problemu, ale musiałem bezpośrednio z tokena pobierać nazwę użytkownika i na jej podstawie z bazy pobierać id użytkownika, co było dość niewygodne. Po dodaniu FOS REST, wszystko zaczęło śmigać. Nie będę tutaj się rozpisywał o tym bundle’u, ponieważ wszystko jest zawarte w oficjalnej dokumentacji.

Miałem jeszcze kilka problemów z walidacją. Jednym z nich był format daty i czasu. Formularz oczekiwał otrzymania od razu obiektów typu DateTime, natomiast JSON może jedynie zwrócić tekst. Pomogło dodanie tablicy do formularza w pliku DocumentType.php:

->add('date', DateTimeType::class, ['widget' => 'single_text'])

Po tej małej zmianie wszystko działa bez problemu.

Napisałem już obsługę prawie wszystkich elementów, została jedynie lista usług, terminarz zleceń i użytkownik. Już teraz widzę, że kilka rzeczy będzie trzeba pozmieniać, ale będę to robił już na bieżąco podczas tworzenia frontendu.

W tym projekcie zrezygnowałem z testów, ponieważ ich napisanie zajęłoby mi więcej czasu, niż ręczne testowanie (nie mam doświadczenia) i pewnie w samych testach miałbym sporo błędów. Kiedy po raz pierwszy usłyszałem o testach automatycznych, nie wiedziałem, o co chodzi. Myślałem, że ktoś wymyślił jakiś magiczny sposób, żeby testować programy i wykrywać w nich błędy. Teraz już wiem, że nie jest to nic bardzo różnego, od tego, jak normalnie testuje się aplikacje, z tym że zostało to zautomatyzowane.

Normalnie trzeba uruchomić przeglądarkę albo Postmana, czy inne narzędzie, wpisać adres i sprawdzić wynik. Wszystko fajnie, tylko czas. Pisząc testy jednostkowe, nie muszę za każdym razem uruchamiać przeglądarki i sprawdzać, czy aplikacja zwróciła właściwy wynik. Wystarczy napisać odpowiedni test, uruchomić go po każdej zmianie w kodzie i on za nas sprawdzi, czy otrzymaliśmy pożądany wynik.

Zastanawiałem się nad przerobieniem skryptu z ostatniego wpisu, wg tego, co było w komentarzach. Cały czas mam to na uwadze, z tym że aktualne rozwiązanie działa, dopisałem tylko fragment odpowiedzialny za sprawdzenie roku (inaczej, dokumenty dodane po roku przerwy, kontynuowałyby numerację) i póki co tak zostawiam, ponieważ zmiana tego wprowadza sporo zamieszania i muszę szukać kilku nowych rozwiązań. Może pod koniec, jak zostanie mi trochę czasu, to się tym zajmę.

Myśląc dzisiaj nad projektem, stwierdziłem, że zapomniałem o jednej istotnej rzeczy. Nie dodałem pola na słowną cenę. Rozwiążę to prostym skryptem, który zmieni cenę wpisaną liczbowo, na cenę wpisaną słownie, ale to już raczej w frontend’zie i nie będę tego zapisywał w bazie.

Pisząc kontrolery pozycji dokumentów i historii wypożyczeń, muszę dopisywać fragmenty odpowiedzialne za aktualizacje cen w dokumencie, oraz przebiegu w historii. W dokumentach był to niewielki problem, dopisałem tylko kilka linijek odpowiedzialnych za przeliczenie i aktualizację i wszystko działa. Jeśli chodzi natomiast o wypożyczenia, to usunąłem pole ze stanem paliwa (w samochodach i tak ciężko sprawdzić, jaki jest aktualny stan), natomiast dodałem pole z różnicą przebiegu po wypożyczeniu. Dzięki temu łatwiej jest mi przywrócić przebieg przy usuwaniu pozycji z historii podczas pomyłki. Jedyny problem to taki, że można usuwać tylko ostatnią pozycję, ale myślę, że nie będzie to dużym utrudnieniem.

Mam nadzieję, że to już końcówka pracy nad API, bo chce już zacząć frontend. Na pewno w Angularze będzie fajniejsza zabawa, bo będzie to dla mnie coś całkowicie nowego.

Pozdrawiam!
MTK

 

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑