Google adwords UserList

Posted by vandall on 21st grudzień , 2013

Komunikując się z google adwords API jeśli potrzebujesz przypisać do kampanii audience (Campaign -> UserList wg nazw google API) skuteczniejszym rozwiązaniem jest przypisanie UserList do każdej AdGroup oddzielnie.

przypisując w PHP API obiekt BasicUserList (lub tożsamy) do RetargetingUserList

(przykładowo przez :)

$service = $adx->GetService(’CampaignCriterionService’, ‘v201309′);
$userList = new CriterionUserList;
$userList->userListId = $audienceId; // pobrane jak niżej w przypisaniu do adgroup
$criterion = new CampaignCriterion($campaignId, null, $userList);
$operation = new CampaignCriterionOperation();
$operation->operator = “ADD”;
$operation->operand = $criterion;
$operations[] = $operation;
$results = $service->mutate($operations);

google zwraca komunikat

SoapFault exception: [soap:Server] [CriterionError.CANNOT_ADD_CRITERIA_TYPE @ operations[0].operand.criterion]

i niewiele z tym da się zrobić.

więc lepiej zrealizować to przez :

/** stworzenie audience
$conversionType = new UserListConversionType();
$conversionType->name = $audName; // nazwa

$userList = new BasicUserList();

$userList->name = $audListName;
$userList->conversionTypes = array($conversionType);

wysłać do SOAP UserListService

a następnie przydzielić do agrup kampanii

$service = $adx->GetService(’AdGroupCriterionService’, ADWORDS_VERSION);
$operations = array();
$userList = new CriterionUserList;
$userList->userListId = $audienceId; //z poprz punktu z response
$criterion = new BiddableAdGroupCriterion;
$criterion->criterion = $userList;
$criterion->adGroupId = $adgroup; // dla każdej z adgrup.
$operation = new AdGroupCriterionOperation();
$operation->operator = “ADD”;
$operation->operand = $criterion;
$operations[] = $operation;
$results = $service->mutate($operations);

uprości to tworzenie adgrup ;)

Citrix XenServer i local storage w ovh

Posted by vandall on 14th listopad , 2013

Serwerownia ovh oferuje całkiem wygodne w użyciu (choć ze stabilnością – różnie ;) ) narzędzia do samodzielnego zarządzania serwerami. jedna z funkcjonalności to możliwość preinstalacji citrix XenServer. do średnio rozbudowanych projektów nie wymagających dostępności online klasy Tier IV i wyżej sprawdza się to całkiem nieźle.

niestety jednak standardowy szablon instalacji średnio radzi sobie z dyskami (a dokładnie z LocalStorage).

Podobnie jest z dodawaniem nowych dysków.

w przypadku gdyby była potrzeba ręcznego zestawienia storage z pomocą przyjdzie taka komenda :

xe sr-create content-type=user device-config:device=/dev/sda3 host-uuid=qwe-qwe-qwe-qwe name-label=”LocalStorage” shared=false type=lvm

gdzie :
* w przypadku definiowania nowego serwera (jeśli nie widać automatycznie storage) wprowadzamy partycję pierwszego dysku
* w przypadku dodawania nowych dysków – wprowadzamy “nową” literkę.
* host-uuid to informacja osiągalna z XenCenter (zakładka general)
* name-label to nazwa widoczna w xencenter (w zasadzie dowolna)
* type lvm – pozwala na pewne operacje później dot. archiwizacji
* shared=false – podłączony w ten sposób dysk nie może być współdzielony.

poprawnie uruchomiona komenda stworzy dysk :)

pomocne przy poszukiwaniach napewno będą :
* cat /proc/partitions
* xe pbd-list (lista gdzie podłączany jest storage)
* xe sr-list (lista storage repo)

HA dla adresów IP

Posted by vandall on 18th marzec , 2013

szybki i prosty sposób jak skonfigurować adres IP tak, by był dostępny na 2 maszynach.

ten pomysł powoduje przygotowanie 2 firewalii “współdzielących” między sobą adres IP oraz maszynę za nimi do serwowania contentu.

1. potrzebny serwer, który prezentuje usługę (nie musi to być www ale tym posłużę się w opisie) : jego IP prywatne to będzie 192.168.1.1

2. firewall na który trafia ruch : jego IP prywatne to będzie 192.168.0.1

3. z oczywistych względów potrzebny nam drugi firewall : konfiguracja przewiduje zmianę tej maszyny w przypadku awarii jednej z nich : IP 192.168.0.2

4. publiczny adres IP mozliwy do przypisania do dwóch maszyn (jeżeli to jest niemożliwe do uzyskania – patrz koniec tekstu i instalacja keepalive na końcówkach).

konfigurujemy tak :

1. maszyna serwująca (192.168.1.1) robi to co robiła czyli po prostu jest (ma serwować content)

2. na każdej z pozostałych maszyn instalujemy keepalived (emerge keepalived dla gentoo, aptitude install keepalived dla ubuntu)

3. konfigurujemy na obu keepalived dla tego adresu (idea keepalived jest taka iż dokładnie jedna z maszyn z puli wskazanej przez keepalived będzie miała ten adres). konfiguracja ogranicza się do wskazania w keepalived maszyn, które adres otrzymują (po prywatnym IP) oraz IP który jest współdzielony. w kernelu trzeba uruchomić opcję “shared IP”. (konkretnie sysctl)

4. firewall na obu maszynach powinien mieć te same reguły – ruch z publicznego IP kieruje na 192.168.1.1 (w przykładzie – porty 80 i 443)

w przypadku niemożności przypisania jednego publicznego IP do 2 maszyn (zdarza się pewnie) wstawiamy na firewallu jeden IP a duplikujemy maszyny prywatne. wtedy na nich instalujemy keepalived (po adresacji prywatnej). wada : firewall wciąż może paść. ale unikamy awarii pojedyńczego hosta serwującego content. można też pomiędzy firewallem a hostem prezentującym content (hostami, bo inaczej mały to ma sens ;) ) wstawić reverse proxy (np. haproxy) które dostanie adresację prywatną i będzie kierować ruch na końcówki ale samo w sobie będzie miało wirtualne IP współdzielone.

zbieranie tresci powiazanych tabel

Posted by vandall on 12th wrzesień , 2012

Z góry uprzedzam – nie zalecam korzystać w wysokoobciążonych serwisach ani jako rozwiązania produkcyjnego. pomysł – w systemach, gdzie w różnych tabelach leżą wartości kumulowane w jednej tabeli wiążącej pozwala pobrać treść wszystkich przypisanych wartości.

np. jeżeli mamy elementy, do których są atrybuty, których same wartości słownikowane są w zależności od typu w różnych tabelach (a bywa, że tak jest optymalniej).
potrzebujemy do jakiegoś celu pobrać wartość niezależnie od tego gdzie leży i to jednym query.

zapytania też nie są pięknie sprawne ale sposób ma szanse komuś pomóc :)

opiera się na cocnat() od selectów z różnych tabel.

próba z group_concat na podzapytaniach z union w mysql niestety niekoniecznie sprawdza się (podzapytanie w podzapytaniu – które byłoby tu potrzebne nie posiada danych z zapytania podstawowego co w efekcie nie pozwala odpowiednio filtrować).

create table attribs(
id int,
type enum(’texts’, ‘attribute’),
name varchar(20)
) engine=innodb;
create table attribute (
id int,
name varchar(20),
active tinyint
) engine=innodb;
create table texts (
id int,
value varchar(20),
active tinyint
) engine=innodb;

SELECT DISTINCT
(…),
concat(
case
when (select n_ta.name from attribute n_ta where n_ta.id = tpa.id
and n_ta.active = 1 limit 1) is null
then ”
else (select group_concat(n_ta.name separator ‘ ‘) from attribute
n_ta where n_ta.id = tpa.id and n_ta.active = 1 )
end,
case
when (select n_tt.value from texts n_tt where n_tt.id = tpa.id and
n_tt.active = 1 limit 1) is null
then ”
else (select group_concat(n_tt.value separator ‘ ‘) from texts n_tt
where n_tt.id = tpa.id and n_tt.active = 1)
end
) as fullVal

FROM attribs AS tpa
(…)
;

Relatywne skrypty i css w przeglądarce

Posted by vandall on 12th wrzesień , 2012

Wiele rozwiązań w sieci (od największych, do mniejszych) stosowało rozmaite zabiegi dotyczące rozpoznawania czy jesteśmy w trybie SSL czy nie w przeglądarce. jak zapewne wiadomo poruszając się po stronie w SSL elementy ze zwykłego HTTP powodują “wredny” komunikat.

w każdym razie zamiast kombinować z https itp można wykorzystać relatywne do protokołu linki do elementów :

<img src=”//moja.domena.pl/plik-js.js” alt=”" />

to wyklucza konieczność budowania zależności dot. document.location, protocol i wielu innych magicznych trików :) polecam uproszczenia ;)

awaryjne duplikowanie maszyny

Posted by vandall on 30th sierpień , 2012

jeżeli potrzeba awaryjnie (albo i nie) zduplikować maszynę – czasami się zdarzyć może jeden ze sposobów to przeniesienie dysku na inną maszynę. jeżeli sprzętowo są zgodne (na poziomie architektury) to powinno ruszyć bez problemu (z dokładnością do ew. tuningu kernela i driverów). w wirtualkach jednak sprawuje się znakomicie.

opis sposobu na wirtualce:
1. konfigurujemy drugą maszynę o identycznych parametrach (przede wszystkim rozmiar(y) dysków)
2. oba odpalamy z livecd, konfigurujemy sieć i ssh
3. na DOCELOWEJ maszynie robimy taki myk :

ssh 192.168.111.232 “dd if=/dev/sda” | dd of=”/dev/sda”

gdzie 192.168.111.232 – to IP źródłowej maszyny.

oczywiście zakładamy że userzy to root (tak, w tym przypadku to konieczne).

w/w powtarzaj dla każdego kopiowanego dysku.

Rozwiązanie zadziała zawsze, gdy rozmiar dysku będzie zgodny. w innych przypadkach można kopiować pojedyńcze partycje, system plików, albo klasycznie przesuwać serwer.

w/w przydatne jest na niższym poziomie jeśli źródłem jest partycja lvm snapshot (pozwala na kopie stanu serwera praktycznie w locie ale pełne zastosowanie w innym miejscu…).

php, referencje, backtrace

Posted by vandall on 18th sierpień , 2012

korzystając z PHP czasem potrzeba budować dość zaawansowane realizacje. przykładowo obsługa błędów oraz związane z nimi operacje często będzie wymagać korzystania z obiektów z grupy Reflection, funkcji typu debug_backtrace() itp.

korzystając z tej ostatniej do jakichkolwiek zastosowań pamiętaj, że w całym trace (np. stosie wywołań) posiada referencje do tego, co zostało przekazane. jeżeli więc wykonasz na nich operacje licz się z tym, że zmienisz ich zawartość (Co może mieć duże znaczenie przy rozbudowanych klasach wyjątków zbierających stan systemu z momentu błędu).

przykładowo :

jeśli w funkcji function a(&$b){/*tu gdzieś nastąpił błąd */} padnie błąd. przekierowane to zostanie do obsługi błędów, tam aby pobrać dokładne informacje skorzystasz z debug_backtrace (lub innego dostępu do stosu wywołania) pracujesz na referencji. i np. realizując rzutowanie do prezentacji zmienisz te zmienne. W wyjątkach używaj kopii danych – bezpieczniejsze ;)

APC PHP Warning unable to allocate memory pool – jak to działa?

Posted by vandall on 27th czerwiec , 2012

Przy dużych ilościach plików aplikacji na serwerze czasem zauważymy w logach spore ilości takiego błędu PHP. W systemach, gdzie błędy nie są ignorowane tylko np. Tłumaczone na wyjątki jest to o tyle niemiłe, że będzie blokowało aplikację.
Problem wynika z poprawności działania samego APC: w obciążonym serwisie akcelerator ten nie radzi sobie prawidłowo ze zwalnianiem pamięci na prekompilowane pliki.
Jest kilka sposobów na rozwiązanie problemu.
W php.ini lub konfiguracji apc możemy zmienić czas życia pliku, apc.ttl na mniejszy np. 1800. Możemy też zwiększyć ilość segmentów pamięci na większą lub zwyczajnie w kernelu powiększyć rozmiar segmentu.

wifi @ laptop &linux

Posted by vandall on 28th luty , 2012

z cyklu “jak zainstalować” wspomnę o aktualnym kernelu (3.*) i instalacji sieci WIFI (czasy, gdy to niedziałały zdają się przechodzić do dalekiej przeszłości ;) ).
gotowego przepisu dla każdej karty tu nie ma, jest to raczej “notatka” mająca na celu zapamiętanie procesu zrealizowania tej operacji.

1. w kernelu włączamy odpowiedni moduł sieci (drivers -> network drivers ->wireless)
* aby znaleźć jaki jest używany (np. na livecd / livedvd) używamy np. lshw (wyszukując driver=) a potem w kernelu odpowiedniej opcji. oczywiście to jedna z możliwości i czasem potrzeba lspci bądź wyszukiwarki internetowej ;)
* aby zadziałało poprawnie – musi być firmware. przy pozostawieniu tylko potrzebnego ci sterownika (a jest to dobra droga bo po co przeciążać kernel ;) ) wyszukaj odpowiedni via google / emerge -s / eix. np. ipw* to pakiety dotyczące intelowskich kart itp.
* na koniec make (dla kernela w katalogu /usr/src/linux) i przenosimy bzImage w odpowiednie miejsce do partycji /boot.

W zasadzie to wszystko w kernelu.

pozostaje :
emerge wireless-tools wpa_supplicant

w/w instaluje nam narzędzia po stronie systemu które potrzebować będziemy do obsługiwania sieci.

konfiguracja wpa_supplicant – czyli możliwości uruchomienia sieci z ssid-ów obsługiwanych przez WPA (np. PSK) sprowadza się do stworzenia pliku /etc/wpa_supplicant/wpa_supplicant.conf i dodania odpowiedniej sekcji network

przykładowo
network={
ssid=”mojessid”
psk=”moj-klucz-autoryzacji”
key_mgmt=WPA-PSK
}

wrzucamy odpowiednie demony do startu :
rc-update add net.wlan0 default
rc-update add wpa_supplicant default

i w zasadzie jeżeli sieć jest dhcp, znalazłeś firmware itp to wszystko załatwione – masz sieć ;P ;)
}

PHP “nie jest językiem programowania”?

Posted by vandall on 4th luty , 2012

Dwudziesty pierwszy wiek. Internet rozwija się w najlepsze. Rządy i “potentaci” usilnie i dramatycznie usiłują utrzymać swoją niepodważalną pozycję – próby wprowadzenia ACTA – jako paktu cenzurowania (choć ten dokument daleki jest od tego by dotykać “wolności słowa” w internecie – zaryzykowałbym nawet stwierdzenie, że to tylko “zasłona dymna dla innych celów” ale nie w tym rzecz w tym wpisie).

Kilka lat temu porzuciłem studia. Były nudne, czasochłonne. W aktualnym roku akademickim zdecydowałem się na powrót. Cóż. Warto wiedzieć, czego uczy się przyszłość informatyków. jednak zauważyłem przerażające tendencje. Zarówno właśnie w szkołach jak i wśród samozwańców.

Tematyką baz danych i sensu ich stosowania zajmę się przy okazji innego pisania.

Dziś skoncentruję się na temacie, który owija się wszędzie (a właśnie w szkole przyjął u niektórych przerażający obraz). Rozchodzi się o PHP – obiektowy język programowania, który nie tyle jest przez “profesjonalistów” i biznes niedoceniany, co wręcz obrażany. dlaczego? cóż : nie wiem.

PHP to język pierwotnie przeznaczony jak sama nazwa wskazuje do w wolnym tłumaczeniu “przetwarzania hipertekstu przed serwowaniem z serwera”. ni mniej ni więcej – jest to jedno z pierwszych rozwiązań na świecie, które pozwalało na publikowanie w internecie dynamicznie modyfikowanych treści.

Stworzony jedynie jako narzędzie. nie tam “język” czy cokolwiek takiego. Kiedy z nim “zaczynałem” istniała sobie (otwarta dla wszystkich zresztą) wersa PHP 3. Internet był wolny, człowiek starał się ograniczyć to, co do internetu trafia. Wtedy w internecie użytkowników liczyło się w tysiącach (no, może milionach). a już napewno w Polsce – kiedy to TPSA zbijała fortunę na wdzwanianym płatnym za czas dostępie do sieci.

Od tego czasu minęło sporo czasu. Ładnych parę lat. Internet stał się bardzo popularny (dostęp do sieci ma jakieś 2 mld ludzkości). idąc za tym – stał się mniej techniczny (ech ta “użyteczność”).

w między czasie rozwijano masę innych technologii : Java, dotNet, C++, C# i wiele innych (tak jest wymieniłem głównie środowiska programistyczne). programowani strukturalne usiłują “odstawić w niepamięć” w wielu miejscach itp itd.

W szczególności osoby “profesjonalne” dramatycznie często twierdzą iż php to nie język programowania. umniejszają wielkość tego narzędzia. W moim przekonaniu – takie stwierdzenie zdecydowanie pasuje do Javy (choć jak najbardziej masa rozwiązań i modeli które właśnie w Java zostały wymyślone lub zaproponowane jest genialna). ale nieumiejętne korzystanie z Java – może doprowadzić do dramatu (np. wydajnościowego).

Czy obrzucanie błotem PHP ma sens?

Współcześnie programowanie obiektowe jest podstawą. polega ono na tworzeniu ‘obiektów” mniej lub bardziej ułomnie modelujących rzeczywistość. i tu zaczynają się schody bo każdy może to zrobić po swojemu. Chodzi jednak o te techniczne możliwości dawane przez programowanie obiektowe.

Więc przejrzyjmy kilka zarzucanych problemów:

Dziedziczenie i rozszerzanie obiektów: Obiektowość w zasadzie o to się opiera. mamy opisywać świat. Modelować go. Jednocześnie kilka innych zasad sprawia, że te obiekty się wzajemnie rozszerzają (dziedziczą). Przykładowo może być sobie pojazd. ma koła (no bo ma jeździć, tak?), ma napęd (przecież nie pojedzie bez tego). ale nie wiemy jaki. na jego bazie powstaje np. pojazd do transportu osób. jest pojazdem, ale dodatkowo ma miejsce na ludzi. idąc dalej takie pojazdy to np. rower (manualny napęd, miejsce na człowieka, 2 koła) albo samochód (4 koła, miejsce na x osób, silnik mechaniczny). samochód może być napędzany dieslem, bęzyną, elektrycznie – to znów będą kolejne doprecyzowania. idąc dalej wszystkie mogą być różnych kolorów. więc znów rozszerzymy. I tak dalej. Tutaj się zatrzymam, gdyż dziedziczenie zrealizowane będzie np. mniej więcej tak :

class pojazd

{

protected $koła;

protected $napęd;

}

class pojazdDlaLudzi extends pojazd

{

protected $osoby;

}

class samochód extends pojazdDlaLudzi

{
protected $napęd = ’silnik’;

protected $napędType;

protected $osoby = 4;

}

class samochódDiesel extends samochód

{

protected $napędType = ‘diesel’;

}

itp itd. pomijając polskie znaczki itp spowoduje to, że ostatni obiekt będzie zawierał nam samochód. i tu właśnie te kolory. kolejne co dodajemy to kolory. no ale trzeba by robić sobie klasy samochódDieselCzerwony, samochódBęzynaCzerwony itp. bez sensu. przecież czerwony może być też rower.

poza dziedziczeniem powstało w obiektowości coś takiego jak rozszerzanie z wielu klas. Php (od wersji 5.4 która dopiero kończy się pojawiać) to też wspiera.

można sobie zrobić coś takiego :

trait kolorCzerwony

{

protected $kolor = ‘czerwony’;

}

trait kolorZielony

{

protected $kolor = ‘zielony’;

}

class mójSamochód extends samochódDiesel

{

use kolorZielony;

}

class mójRower extends rower

{

use kolorZielony;

}

i w wielkim uproszczeniu mamy częściowe wielokrotne dziedziczenie. od tego momentu możliwe jest tworzenie “traits” które będą miały zunifikowane elementy wykorzystywane w wielu obiektach (np. logowanie zdarzeń, dostęp do bazy itp) w jednym miejscu a włączanie ich w kod klas jedną linią. pewnie idealnym rozwiązaniem toto nie jest ale… cóż : ideał zależy od tego, co idywiduum sobie samo określi za ideał. w każdym razie toto istnieje, czy działa dovbrze – przekonamy się kiedy PHP będzie już “kompletne”.

Hermetyzacja danych : sposób programowania taki, by obiekt posiadał swój interfejs dla “innych”  obiektów a dane zawsze były wewnątrz niego “hermetyczne” i niemodyfikowalne z zewnątrz (pomijam problemy dotyczące łamania zabezpieczeń czy dostępu – w każdym rozwiązaniu i każdej technologii znajdą się tacy, co będą próbowali to zrobić). PHP w pełni to wspiera. własności oraz metody z powodzeniem mogą być dostępne publicznie (jako ogólnie pojęty interfejs), w sposób chroniony (wyłącznie obiekty dziedziczące mogą mieć do nich dostęp) oraz prywatne (wyłącznie ten obiekt ma tam dostęp). i za wyjątkiem korzystania z Reflection w odpowiedni sposób nie sposób sposobu dostępu obchodzić. Zatem teoria “hermetyzacji” jest spełniona.

własności statyczne: służą do przechowywania danych (lub udostępniania metod) związanych z danymi obiektami ale nie istniejących dla każdego obiektu – a dla całej rodziny (że się tak wyraże). czyli każdy z “samochodów” będzie miał toto, co jest statyczne dla niego. php wspiera to na dwa sposoby : klasyczne static $własność tudzież metoda – które powoduje, że obiekt będzie miał dostęp dokładnie do danych w TYM obiekcie oraz odwołanie static (static::$cośtam) – które ma dostęp do danych statycznych aczkolwiek na poziomie obiektu który woła o dane. mamy w ten sposób pełne własności statyczne.

brak kompilatora: spotkałem się nawet  z argumentem iż php nie kompiluje się. cóż. nie dośc, że nie jest to w pełni prawda to osobiście uważam to za znakomity plus. przede wszystkim php jak najbardziej się kompiluje – tylko w “locie”. dziś standardem jest odpalenie przy serwerze np. APC. ni mniej ni więcej rozwiązanie powoduje prekompilację kodu i zapamiętanie go w buforze – operacja wykonuje się raz. ponadto php jak najbardziej posiada kompilatory (nawet wspierane przez microsoft! – phalanger dla przykładu), narzędzia do tłumaczenia kodu na C++ (hiphop php chociażby). jednak to właśnie wręcz daje PHPowi całkiem pokaźne zalety (Szczególnie dla developerów). możliwe jest dynamiczne tworzenie kodu aplikacji (tak, jak się chce możesz stworzyć kod który sam się będzie optymalizował i takie rozwiązania w niektórych przypadkach są w 100% stosowane), a w prostszym przypadku – w locie tworzyć rozwiązania na które żadne inne narzędzia bezpośrednio nie pozwalają. dzięki temu możliwe jest tworzenie aplikacji w taki sposób, by bazowym źródłem danych był… kod źródłowy (co daje całkiem pokaźne możliwości jak się postarać).

przestrzenie nazw: nie wnikając w szczegóły – przestrzenie nazw są dostępne w PHP już od dłuższego czasu.

w zasadzie dzisiejsze PHP (5.3 / 5.4) nie odstaje od konkurencyjnych języków a sądząc po zastosowaniu przez gigantów (google, facebook, yahoo), bardzo dużych graczy (choćby allegro) można śmiało powiedzieć, że ma sens… szkoda, że w szkołach – miejscu, gdzie uczy się przyszłych twórców aplikacji traktuje się w taki sposób. poza tym – skoro ktoś zaczął próbować, ruszył właśnie PHP (jest darmowe, publicznie dostępne, dla początkujących jest nawet sporo manuali czy wręcz tzw. frameworków) – i chce robić to co lubi (programować) – dlaczego szkoła wyśmiewa takiego człowieka? w praktyce C++ czy inne dużo “niższe” języki znacząco utrudniają nam życie… restrykcje dotyczące pilnowania tego co się zapisało w pamięci, brak zwalniania tej pamięci jak się samemu o to nie zadba… tworząc coś do sieci, tworząc aplikacje na poziomie “pomysłu” – jest to drastycznie uciążliwe. owszem – zgadzam się, że kod powinien być docelowo zupełny, opisany testami, udokmuentowany, przewidujący tak dużo sytuajci jak tylko się da (najlepiej wszytkie) ale to na poziomie np. tworzenia idei spowalnia proces. PHP dzięki temu, że nie wymaga kompilacji pozwala na podmiany w locie jedynie elementów dostępnych dla milionów ludzi aplikacji.

W praktyce jeżeli używasz PHP – rób to. używaj. korzystaj. to, że zatwardziały spec na pozycji dającej mu ciepłą posadę z niezłą pensją krzyknie “php jest do dupy”, czy też nauczyciel który nie sprawdził się w realnych projektach i dziesiątki lat w kółko uczy nie zauważając iż czasy i technologie się zmieniają krzyknie “php jest bee” – nie znaczy, że tak jest. Jednak postaraj sie przy tym zachować racjonalny poziom profesjonalizmu : obiektowość i pewne wymagania (testowanie, automatyzacja, dokumentacja,  hermetyzacja, projekt kodu itp itd) są często upierdliwe – ale ważne i potrzebne dla… leniwych (tak jest : patrząc długoterminowo – czyli tak, jak projektując aplikację powinno się spojrzeć przewidujmy sytuację “przez pół roku nie dotknę tego kodu…” : wtedy trafny komentarz, przejrzyste obiekty, dobry test będzie nieocenionym elementem aplikacji.). okay w momencie realizacji kodu będzie to trwało conajmniej połowę czasu dłużej. ale kod będzie sprawny (bardziej niż przy szerokich testach) i stabilny. pomijanie właśnie tych elementów w PHP powoduje że ma taką słabą renomę.To jest pewna wada php : zadne C++, Java itp nie dopuści by twój kod z pomylonymi typami, złym przetworzeniem aplikacji, czy nawet błędem skłądniowym nie dopuści tego do kompilacji. php niestety pozwala podmienić plik nawet z błedem składni i jeżeli go nie przetestowałeś – taki błąd ujawni się tylko czasem, w określonym przypadku (kiedy ten plik zostanie “uruchomiony”). w ten sposób błędy trudno wykrywać. testy przed tym cię uchronią (przynajmniej te, któ¶e napisane są sprytnie).

Dodam jeszcze, iż pisanie testów niekoniecznie wymaga znajomości phpUnit czy innych masakrycznych rozwiązań (choć np. xdebug polecam ;) ). wystarczy byś zrobił test który sprawdzi po twojemu czy kod wykonał to czego się spodziewałeś. to załatwi sprawę.

W każdym razie – Używajmy PHP, nie dajmy się “super specom i najmądrzejszym profesorom” ! ;)