PHP i Python – środowisko developerskie

Jakiś czas temu zacząłem pracować dla klienta, który realizuje swój projekt w oparciu o koncepcję mikroserwisów Martina Fowlera. Nowe serwisy pisane są w Pythonie ale utrzymanie i dalszy rozwój starszych częściej architektury wymaga znajomości języka PHP. Mam ponad pięcioletnie, ciągłe doświadczenie w programowaniu w PHP, ale sięga ono czasów kiedy użycie JavaScriptu na serwerze wydawało się być pomysłem absurdalnym, kiedy konto na Naszej Klasie było tak powszechne jak dziś profil na Facebooku, a na współdzielonych hostingach królowało PHP w wersji 5.3, która zasłynęła m.in z wprowadzenia instrukcji goto.

Odkąd porzuciłem PHP na rzecz Pythona nie tylko zacząłem tworzyć bardziej pythoniczny kod, ale wzbogaciłem też swój warsztat deweloperski o nowe narzędzia, praktyki i metodologie. Po tych kilku latach patrzę już na PHP przez pryzmat doświadczeń zdobytych w trakcie programowania w innych językach. Nie dawno miała miejsce premiera PHP w wersji 7, która zbiera dobre recenzje i ma rewelacyjne wyniki w benchmarkach. Postanowiłem zapoznać się z tą nową odsłoną – dla mnie zapomnianego już lekko – języka. Pierwsza krok jaki musiałem wykonać to instalacja najnowszej wersji PHP na komputerze.

PHPbrew

Dwie wersje Pythona 2 i 3 zainstalowane równolegle w systemie to standard jednak chcąc mieć możliwość skorzystania z mniej popularnych wersji warto posłużyć się dodatkowym oprogramowaniem takim jak pythonz będącego forkiem nie wspieranego już projektu pythonbrew, który oficjalnie odsyła do pyenv (nie mylić z pyvenv, o którym za chwilę).

PHP ma swój odpowiednik pythonbrew – PHPbrew. Instalacja tego narzędzia jest bezproblemowa i szczegółowo opisana na stronie projektu http://phpbrew.github.io/phpbrew/ więc nie będę jej powielał. Po instalacji PHPbrew możemy przystąpić do instalacji samego PHP w różnych wersjach. Podobnie jak analogiczne narzędzia Pythona – PHPbrew do zainstalowania PHP oraz jego rozszerzeń wymaga także zadbania o zależności. Ja np. spotkałem się z komunikatem configure: error: Please reinstall readline – I cannot find readline.h, który w uprzejmy sposób poinformował mnie o konieczności doinstalowania pakietu deweloperskiego redline

sudo aptitude install libreadline-dev
phpbrew install php-5.5.9

albo instalacji PHP bez obsługi tego rozszerzenia np w wersji 7.

phpbrew install php-7.0.6 -readline

Przełączenie się na wybraną wersję PHP wymaga wydania prostej komendy w konsoli:

phpbrew use php-7.0.6

Od tej chwili możemy rozpocząć pracę z wybraną wersją PHP w konsoli lub też odpalić wbudowany w PHP od wersji 5.4 serwer, a po zakończeniu pracy wrócić do domyślnie zainstalowanej w systemie wersji.

phpbrew off

virtPHP

Zarówno Python, jak i PHP stale się rozwijają. Wciąż dochodzą mniejsze lub większe usprawnienia, pojawiają się nowe rozszerzenia, biblioteki, moduły. Przełomowe zmiany, takie jak w przypadku wydania siódmej odsłony PHP następują stosunkowo rzadko, a co za tym idzie mechanizmy zarządzania wersjami danego języka w systemie przydają się sporadycznie. O wiele częściej deweloperzy spotykają się z potrzebą konfiguracji środowiska deweloperskiego dobraną specjalnie pod dany projekt.

Python ze swoim wirtualnym środowiskiem virtualenv trochę mnie rozpieścił jako dewelopera. Virtualenv lub też jego funkcjonalny następca – wbudowany w Pythona 3 moduł pyvenv pokazał mi że praca nad różnymi aplikacjami, wymagającymi często odmiennego zestawu bibliotek i konfiguracji może być łatwa i przyjemna.

Instalacja, utworzenie wirtualnego środowiska – w tym wypadku w katalogu projektu – i uruchomienie go poprzez wywołanie skryptu, który ustawia wszelkie zmienne środowiskowe.

sudo apt-get install python-virtualenv
cd ~/my_project/
virtualenv .ve
source .ve/bin/activate

Do wersji 3.3 Pythona zalecane jest używanie virtualenv zamiast pyvenv bo dopiero w wersji 3.4 pyvenv ma wbudowanego menagera pakietów pip umożliwiającego łatwą instalację zależności.

pip install django

Pip umożliwia zrzucenie listy zainstalowanych pakietów do pliku dzięki czemu możliwe jest np. zachowanie konfiguracji wirtualnego środowiska w repozytorium Git

pip freeze > requirements.txt

i późniejsze jego odtworzenie na innej maszynie.

pip install -r requirements.txt

Komfort pracy, jaki daje wirtualne środowisko jest nie do przecenienia. W katalogu projektu mamy tylko i wyłącznie pliki projektu. Wszystkie zależności – niezbędne moduły i biblioteki dostarczane przez zewnętrznych developerów trzymane są w odmiennej lokalizacji i jedyne czego potrzebujemy do odtworzenia środowiska niezbędnego do uruchomienia projektu jest plik requirements.txt. Python dał mi zupełnie odmienne doświadczenie w tej kwestii w stosunku do projektów realizowanych w PHP gdzie wszelkie zależności – nie licząc wbudowanych funkcji języka oraz wkompilowanych w niego rozszerzeń – były trzymane, najczęściej w podkatalogu „vendors” i razem z plikami projektu do repozytorium pchane były całe feameworki i inne rozbudowane biblioteki, ewentualnie zaciągane zewnętrzne repozytoria.

Jak wspomniałem przez ostatnie lata nie obcowałem z PHP zbyt intensywnie więc szukałem funkcjonalnego odpowiednika virtualenv. Znalazłem virtPHP. Twórcy virtPHP nie ukrywają, że wzorowali się na swym pythonowym odpowiedniku starając się stworzyć narzędzie równie łatwe a nawet podobne w użyciu. Biblioteka ta nie została jeszcze ustabilizowana. Ostatnia póki co wersja virtPHP 0.5.2-alpha jest dedykowana jedynie na systemy unixopochodne. Trochę martwi brak aktywności developerów przez ostatni rok – nie mniej zachęcam do wypróbowania możliwości wirtualnych środowisk w PHP.

Kiedy już uporamy się z zainstalowaniem virtPHP, możemy przystąpić do utworzenia pierwszego wirtualnego środowiska dla projektu w PHP.

cd ~/my_php_project/
php virtphp.phar create .my-ve
source .my-ve/bin/activate

VirtPHP można łaczyć także z PHPbrew

php virtphp.phar create --php-bin-dir="/home/user/.phpbrew/php/php-5.5.9/bin" .my-ve

Od tej chwili można instalować biblioteki z repozytoriów PECL i PEAR

pecl install mongo
pear install pear.phpunit.de/PHPUnit

Potencjał tego narzędzia oceniałbym jako wysoki gdyby nie problem z repozytoriami PHP. PECL to repozytorium rozszerzeń PHP napisanymi w języku C. Trudno mi ocenić jego aktualność – zwłaszcza w związku z wydaniem wersji PHP 7. PEAR to biblioteki napisane w PHP tyle, że to staroć nieuaktualniany o nowe wydania bibliotek (np. Symfony Framework). Ponieważ trzymanie zależności w podkatalogu „vendor” stało się powszechnie stosowaną praktyką w świecie PHP popularność zdobył sobie menadżer zależności, który niejako podtrzymał tradycję.

Composer

Menadżer zależności Composer może być uruchomiony w kontekście wirtualnego środowiska virtPHP co niesie ze sobą dodatkowe korzyści, ale równie dobrze może być używany niezależnie. Koncepcyjnie Composerowi najbliżej do npm znanego z Node.js.

Instalacja Composera sprowadza się do ściągnięcia pliku composer.phar do katalogu głównego projektu.

cd ~/my_php_project/
php -r "readfile('https://getcomposer.org/installer');" | php

Zależności są instalowane w podkatalogu vendors.

php composer.phar require monolog/monolog
php composer.phar require twig/twig

natomiast w katalogu głównym tworzone są trzy pliki:

./vendors/autoload.php
./composer.json
./composer.lock

Plik composer.json, zawiera bieżącą konfigurację zależności.

{
    "require": {
        "monolog/monolog": "^1.19",
        "twig/twig": "^1.24"
    }
}

Z kolei w pliku composer.lock – również w formacie json – zapisane są szczegóły na temat zainstalowanych paczek i ich wersji. Tan plik jest bardzo rozbudowany. W repozytorium kodu zalecane jest przechowywanie obu plików, gdyż w przypadku próby odwzorowania konfiguracji na innej maszynie,

php composer.phar install

polecenie composer install korzysta właśnie z pliku composer.lock i dopiero w przypadku jego braku, z konfiguracji zapisanej w composer.json, ale wtedy nie ma pewności, że dostaniemy dokładnie taki sam wynik.

Deweloperzy PHP są leniwi jak przystało na każdego szanującego się programistę i unikają pisania zbędnego kodu związanego z dołączaniem wymaganych klas i funkcji. Mają do dyspozycji autoloader. Sam byłem zakochany w koncepcie autoloadera dopóki nie zacząłem na full etat kodować w Pythonie. Okazało się, że importy są całkowicie wystarczające a do tego stanowią jeden z aspektów samodokumentującego się kodu. Jeśli unikasz tzw. importowania z gwiazdką, nie potrzebujesz zaawansowanego IDE aby wiedzieć, gdzie co jest i czego możesz się spodziewać w danym module. Pythonowcy nie wiedzą co to autoloader. PHP-owcy nie potrafią bez niego żyć tak więc Composer wspiera również ten mechanizm. Po zainstalowaniu zależności w katalogu vendors generowany jest plik autoload.php, który wystarczy tylko zaimportować.

require __DIR__ . '/vendor/autoload.php';

PHP przez wiele lat królowało na współdzielonych hostingach dając PHP dużą przewagę nad innymi językami skryptowymi używanymi w web developmencie. Wystarczyło połączenie FTP do przesłania plików na serwer i początkujący webmaster mógł się cieszyć z działającej strony www. Composer wymaga dostępu do shella tak więc z pełni jego zalet będą cieszyć się osoby pracujące nad serwisami publikowanymi na kontach z dostępem przez ssh np. na VPN-ach albo serwerach dedykowanych.

Docker

Przez ostatnie parę lat mocno rozwinęła się wirtualizacja. Deweloperzy bardzo chętnie sięgają dziś po narzędzia typu Vagrant lub Docker, które umożliwiają utworzenie niemal całkowicie odseparowanego środowiska deweloperskiego, niezależnego od konfiguracji komputera programisty, dającego się przenieść na inną maszynę. W kontenerze można dziś zamknąć zarówno aplikacje pisane w PHP, Pythonie jak i w wielu innych językach programowania więc to nie czyni różnicy między nimi. Docker ma ogromne możliwości, których nie zamierzam tutaj opisywać. Jest to temat na grubą książkę. Chcę jedynie zaprezentować przykład podstawowego użycia kontenera, w którym zamknięte jest PHP w wersji 7 do sprawdzenia możliwości nowej odsłony tego języka.

PHP ma swoje oficjalne obrazy w repozytorium Dockera i w domyślnej konfiguracji, wraz z pełni funkcjonalnym Apachem daje się uruchomić po wydaniu zaledwie dwóch komend .

docker pull php:7.0.6-apache
docker run -p 8080:80 -v "~/my_php_project":/var/www/html --name my-php7-container php:7.0.6-apache

Po wrzuceniu pliku do katalogu my_php_project

echo '<?php phpinfo();' > ~/my_php_project/info.php

I wybranie w przeglądarce adresu

localhost:8080/info.php

możemy obejrzeć sobie konfigurację PHP 7.

Naturalnie trzeba mieś już zainstalowanego i skonfigurowanego Dockera. Warto ten wysiłek podjąć i rozpocząć przygodę z kontenerami. Już najprostsze przypadki użycia są przydatne i wcale nie trzeba pracować nad wielkim projektem o rozbudowanej architekturze aby docenić zalety konteneryzacji. Choć rozwiązanie to nie jest bez wad – obrazy Dockera sporo ważą, a uruchomione instancje zabierają sporo zasobów będąc bądź co bądź pełnoprawnymi systemami – w zamian dostajemy odseparowane pudełko, w którym możemy zamknąć np. wersję 2.4 blendera, która jako ostatnia obsługuje skrypty pisane w Pythonie 2.

Każdy człowiek ucząc się nowej rzeczy czerpie ze swoich dotychczasowych doświadczeń. Programiści rozpoczynający pisanie oprogramowania w nowym dla nich języku starają się zorganizować swój warsztat pracy w sposób, który jest im znany. Udaje się to mniej lub bardziej bo każdy język programowania ma swoją specyfikę uwarunkowaną przyjętymi założeniami, filozofią, techniczną implementacją i wypracowaną praktyką. To co jest przyjęte za standard w jednej technologii w innej może być uważane za niemile widziane. Sztuką jest dostosować się i nauczyć poprawnie każystać z dedykowanych narzędzi. Zarówno PHP, jak i Python umożliwiają organizację pracy dewelopera w sposób umożliwiający łatwe przełączanie się pomiędzy różnymi projektami posiadającymi swoją konfigurację i zależności. Choć robią to w nieco odmienny sposób w mojej ocenie wygoda rozwiązań stoi na porównywalnym poziomie.

Jednak VirtualBox

Po moich próbach z qemu i KVM postanowiłem wypróbować VirtualBox. Obsługa qemu z konsoli okazała się na dłuższą metę niewygodna z kolei KVM działało zbyt niestabilnie.

Sama instalacja VirtualBoxa pod Kubuntu nie sprawiła trudności.

sudo aptitude install virtualbox

Jednak zaraz po stworzeniu wirtualnego dysku i podjęciu próby instalacji na nim Windowsa otrzymałem komunikat błędu:

VirtualBox can’t operate in VMX root mode. Please disable the KVM kernel extension, recompile your kernel and reboot (VERR_VMX_IN_VMX_ROOT_MODE).

Cuż pozostało uruchomić Boot-up Managera i wyłączyć usługę „Full virtualization on i386 and amd64 hardware – kvm”. Boot-up Manager nie jest domyślnie instalowany (przynajmniej w Kubuntu), ale to nie problem.

sudo aptitude install bum

Dalej poszło już bez niespodzianek. Windows zainstalował się i od razu miał połączenie z netem, widział CDROM-a (z czym była problem w KVM). Współdzielenie katalogów też nie okazało się trudnym do osiągnięcia. Właściwie wszystko załatwił dodatek Guest Additions instalowany na systemie gościu. O ile katalog, który ma być współdzielony wyklikuje się po wybraniu opcji „Urządzenia -> Współdzielone katalogi” w menu VirtualBoxa o tyle dostęp do tego katalogu z poziomu systemu gościa w przypadku windowsa uzyskuje się wklepując w linii komend następujące polecenie

net use x: \\\vboxsvr\shared

gdzie shared jest nazwą nadaną współdzielonemu katalogowi. Jeszcze tylko restart Windowsa i wszystko hula 🙂

Troszkę mnie to rozbawiło, że lokalizację w Linuksie wyklikuję a w Windowsie wklepuję 😉

KVM

Drążąc dalej temat wirtualizacji odkryłem – piszę tak wcześniej zagadnienie to mnie nie interesowało – że w Ubuntu dostępne jest środowisko wirtualizacyjne KVM (Kernel-based Virtual Machine). Oprogramowanie to oparte jest o Qemu z tym, że wkompilowane w jądro Linuksa. W połączeniu z Menadżerem Maszyn Wirtualnych (ang. Virtual Machine Manager) będącym graficznym gui ułatwiającym zarządzanie KVM oraz innymi kompatybilnymi systemami wirtualizacyjnymi, stanowi całkiem przyjemny zestaw narzędzi.

Niestety nie udało mi się z poziomu Menadżera uruchomić wirtualki utworzonej przy pomocy Qemu i musiałem tworzyć dysk na nowo i instalować system od początku. Nie zbadałem jeszcze czy tak jak w przypadku samego Qemu wirtualne dyski da się po prostu kopiować, konwertować i co tam nam jeszcze przyjdzie do głowy. Jedno co fajne to możliwość bieżącego monitorowania poziomu zajęcia pamięci RAM lub obciążenia procesora.

Testy trwają dalej i zobaczymy co z tego wyniknie. Na celowniku mam jeszcze virtual boxa.

Wirtualne Internet Explorery

Wolę klepać kod w php niż bawić się w stylowanie stron lub projektowanie grafik. Dzięki temu nie potrzebuję w zasadzie Windowsa, a Linux zaspokaja wszystkie moje softwarowe potrzeby. Niestety czasami jednak muszę wklepać kilka reguł css-owych. W końcu nie mogę się z każdą pierdołą zwracać do znajomego web-developera. W takich, rzadkich przypadkach pojawia się potrzeba uruchomienia Windowsa choć by po to aby sprawdzić jak dana strona wygląda w Internet Explorerze 6. Aż dziw bierze, że niektórzy jeszcze tego używają?

Powiecie, że jest coś takiego jak [IE4Linux](http://www.tatanka.com.br/ies4linux/), a ja wam odpowiem, że strony w IE4Linux nie wyglądają tak samo jak w IE zainstalowanym na Windowsie 😉 Jeśli jesteście „zawodowcami” możecie podarować sobie IE4Linux podobnie zresztą, jak używający Windowsa mogą sobie podarować IETestera. To są niuanse, drobne różnice w renderowaniu czcionek, marginesów, dopełnień itp., nie mniej każdy kto toczył kiedyś bój o 2px wie o co chodzi. Tak na marginesie wspomnę, że ciekawie zapowiada się projekt [Expression Web SuperPreview](http://blogs.msdn.com/xweb/archive/2009/03/18/Microsoft-Expression-Web-SuperPreview-for-Windows-Internet-Explorer.aspx), ale nie miałem z nim dotychczas w praktyce do czynienia więc powstrzymam się od opinii.

Czyli zostaje Windows, a najlepiej trzy Windowsy z trzema wersjami Internet Explorera. Powiedzmy, że wersje < 6 można sobie podarować. Jak większość posiadaczy laptopów, również ja mam oryginalnego Windowsa, jednak mam na nim zainstalowaną tylko jedną wersję IE, a do tego nie lubię być zmuszany do wylogowywania się z Linuxa i uruchamiania microsoftowego systemu tylko po to aby zobaczyć jak wygląda strona www, nad którą aktualnie pracuję. Idąc z duchem czasu postanowiłem wiec wypróbować wirtualizacji. Swego czasu Microsoft udostępnił [obrazy wirtualnych maszyn ze specjalnie przygotowanymi wersjami Windowsa XP dla webdeweloperów](http://blogs.msdn.com/ie/archive/2007/04/17/ie7-virtual-pc-image-and-ie6-virtual-pc-image-refresh.aspx). Uruchomić je można korzystając z oprogramowania Virtual PC. Będąc szczęśliwym posiadaczem mało używanego Windowsa zapragnąłem stworzyć swoją wirtualkę i uruchomić "okna" pod Linuxem. Poczytałem troszkę o różnych narzędziach do wirtualizacji i ostatecznie postanowiłem użyć [qemu](http://www.nongnu.org/qemu/) akceleracją kqemu. Do uruchomienia przydatne okazały się [dokumentacja qemu](http://calamari.reverse-dns.net:980/cgi-bin/moin.cgi/QuickStartGuide) oraz tutorial [QEMU - HowTo](http://kaka.ovh.org/howto/qemu/) opisujący krok po kroku instalację i "aktywację" kqemu. Poszukując informacji na temat możliwości zwiększenia pojemności wirtualnego dysku trafiłem też na ciekawy artykuł [qemu i WindowsXP dysko żerca edition](http://wariat.jogger.pl/2007/06/21/qemu-i-windowsxp-dysko-zerca-edition/). Pewien problem sprawiło mi zagadnienie wymiany danych między systemem gospodarzem, a wirtualnym gościem, ale tylko dlatego, że nie mogłem się zdecydować czy wybrać sambę, ftp-a, czy może współdzielenie jakiegoś wirtualnego dysku wymiany. Najłatwiejsze okazało się postawienie serwera ftp na Linuksie i łączenie z nim za pomocą ftp.