<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Blog o PHP</title>
	<atom:link href="http://blogophp.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogophp.com</link>
	<description>i tematyce pokrewnej</description>
	<pubDate>Sun, 22 Aug 2010 16:02:27 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>chain of responsibility</title>
		<link>http://blogophp.com/2010/08/22/chain-of-responsibility/</link>
		<comments>http://blogophp.com/2010/08/22/chain-of-responsibility/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 16:02:27 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[wzorce projektowe]]></category>

		<category><![CDATA[polecenie]]></category>

		<category><![CDATA[wzorzec]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=52</guid>
		<description><![CDATA[Łańcuch odpowiedzialności to wzorzec projektowy, który znajduje zastosowanie w sytuacji, gdy konkretne żądanie może zostać obsłużone przez różne obiekty. Tworzą one uporządkowaną strukturę przypominającą swoją budową łańcuch. Jeśli jeden z nich nie jest w stanie prawidłowo zająć się request&#8217;em, to przekazuje jego obsługę dalej, do kolejnego handler&#8217;a. Na końcu zazwyczaj umieszczane jest działanie domyślne. Cały [...]]]></description>
			<content:encoded><![CDATA[<p>Łańcuch odpowiedzialności to wzorzec projektowy, który znajduje zastosowanie w sytuacji, gdy konkretne żądanie może zostać obsłużone przez różne obiekty. Tworzą one uporządkowaną strukturę przypominającą swoją budową łańcuch. Jeśli jeden z nich nie jest w stanie prawidłowo zająć się request&#8217;em, to przekazuje jego obsługę dalej, do kolejnego handler&#8217;a. <span id="more-52"></span>Na końcu zazwyczaj umieszczane jest działanie domyślne. Cały proces zobrazowano na poniższym rysunku:</p>
<p style="text-align:center;"><a href="http://blogophp.com/download/chain.PNG" title="chain" target="_blank"><img src="http://blogophp.com/download/chain.PNG"  style="width:460px" alt="chain" /></a></p>
<p>Gdzie:</p>
<ul>
<li><strong>request</strong> - żądanie</li>
<li><strong>A,B,C</strong> - obiekty tworzące łańcuch</li>
<li><strong>Default</strong> - obiekt odpowiadający za zachowanie domyślne, stąd też znajduje się na końcu</li>
</ul>
<p>Zatem żądanie może zakończyć swoją &#8220;wędrówkę&#8221; już na obiekcie A, ale równie dobrze może dotrzeć do samego końca hierarchii. </p>
<p>Gdybyśmy mieli odnieść się do sytuacji wziętej z życia, to znakomitym przykładem wydaje się być obieg pisma pomiędzy wydziałami dużej organizacji. Po zapoznaniu się z dokumentem konkretna filia podejmuje decyzję o jego rozpatrzeniu lub o przekazaniu do innego oddziału. Koniec końców dokument trafi na odpowiednie biurko.</p>
<h3>prosty przykład praktyczny</h3>
<p>Przyjmijmy założenie, iż w zależności od typu zmiennej będącej żądaniem, jego obsługa będzie delegowana do dedykowanego obiektu. Na początku potrzebny nam jest abstrakcyjny zarys dla klas stanowiących elementy łańcucha:</p>
<pre class="brush: php;">
abstract class Handler {

	protected $nextHandler = NULL;

	// zajmuje sie obsluga requesta
	abstract public function Request ($request);

	// setter dla kolejnego handler'a
	public function setNextHandler(Handler $h) {

		$this->nextHandler = $h;

	}

}
</pre>
<p>Teraz ich definicja:</p>
<pre class="brush: php;">
// obsluga dla zmiennej typu boolean
class Boolean extends Handler {

	public function Request ($request) {

		if (is_bool($request))
			return "BOOL";
		else
			if ($this->nextHandler instanceof Handler)
				return $this->nextHandler->Request($request);

	}

}

// obsluga dla zmiennej typu numeric
class Numeric extends Handler {

	public function Request ($request) {

		if (is_numeric($request))
			return "NUMERIC";
		else
			if ($this->nextHandler instanceof Handler)
				return $this->nextHandler->Request($request);

	}

}

// obsluga dla zmiennej typu string
class String extends Handler {

	public function Request ($request) {

		if (is_string($request))
			return "STRING";
		else
			if ($this->nextHandler instanceof Handler)
				return $this->nextHandler->Request($request);

	}

}

// obsluga zachowania domyslnego - na koncu lancucha
class DefaultHandler extends Handler {

	public function Request ($request) {

		return "DON'T KNOW";

	}

}
</pre>
<p>Na koniec klient:</p>
<pre class="brush: php;">
// klient
class Client {

	public function request ($request) {

		// tworzymy instancje elementow lancucha
		$string = new String();
		$numeric = new Numeric();
		$boolean = new Boolean();
		$default = new DefaultHandler();

		// ustawiamy kolejnosc elementow w lancuchu
		// string > numeric > boolean > default
		$string->setNextHandler($numeric);
		$numeric->setNextHandler($boolean);
		$boolean->setNextHandler($default);
		return $string->Request($request);

	}

}

// przykladowe uzycie
$client = new Client();
var_dump($client->request(array(1)));
</pre>
<p>Wśród zalet chain of responsibility należy wymienić możliwość dowolnego formowania przebiegu obsługi request&#8217;a. W dowolnej chwili można utworzyć nowe elementy lub usunąć istniejące. Zachęcam do głębszego zapoznania się z tym wzorcem projektowym.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/08/22/chain-of-responsibility/feed/</wfw:commentRss>
		</item>
		<item>
		<title>profiling</title>
		<link>http://blogophp.com/2010/07/11/profiling/</link>
		<comments>http://blogophp.com/2010/07/11/profiling/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 13:28:34 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=51</guid>
		<description><![CDATA[Z zagadnieniem profilowania kodu, każdy programista spotyka się prędzej czy później. Przychodzi bowiem taki moment, w którym okazuje się, iż napisany przez nas komponent działa zbyt wolno, skutecznie obniżając wydajność całej aplikacji. Z pomocą dla programistów PHP przychodzą liczne narzędzia. Wybrany z nich (Xdebug), postaram się w sposób przystępny i zrozumiały zaprezentować w niniejszym wpisie. [...]]]></description>
			<content:encoded><![CDATA[<p>Z zagadnieniem profilowania kodu, każdy programista spotyka się prędzej czy później. Przychodzi bowiem taki moment, w którym okazuje się, iż napisany przez nas komponent działa zbyt wolno, skutecznie obniżając wydajność całej aplikacji.<span id="more-51"></span> Z pomocą dla programistów PHP przychodzą liczne narzędzia. Wybrany z nich (Xdebug), postaram się w sposób przystępny i zrozumiały zaprezentować w niniejszym wpisie. Zacznijmy jednak od teorii.</p>
<h3>prawo amdahla</h3>
<p>Na początku mamy skrypt, który działa zbyt wolno. Po dokonaniu szczegółowej analizy okazuje się że:</p>
<ul>
<li><strong>80 %</strong> czasu jego wykonywania zajmuje &#8220;proces autoryzacji&#8221;</li>
<li><strong>10 %</strong> czasu jego wykonywania zajmuje &#8220;logowanie zdarzeń&#8221;</li>
<li><strong>10 %</strong> czasu jego wykonywania zajmują &#8220;operacje arytmetyczne&#8221;</li>
</ul>
<p>Który fragment należy poddać optymalizacji, aby uzyskać maksymalny wzrost wydajności? Na to pytanie udziela nam odpowiedzi prawo Amdahla. Choć wykorzystywane głównie w obliczeniach równoległych, to i dla operacji sekwencyjnych przedstawia algorytm postępowania. Dzięki zastosowaniu kilku prostych wzorów, możemy łatwo określić, jakie działania przyniosą najlepsze rezultaty. Poniżej ukazuję najważniejszy z nich (im wyższy wynik, tym lepsza optymalizacja):</p>
<p style="text-align:center;"><img src="http://blogophp.com/download/amdahla.PNG" style="text-align:center;" alt="wzor" /></p>
<p>Gdzie:</p>
<ul>
<li><strong>p</strong> - fragment kodu przyspieszony p-razy</li>
<li><strong>f</strong> - czas wykonywania fragmentu kodu (nieulegającego poprawkom) przed podjęciem jakichkolwiek działań (f należy do przedziału obustronnie otwartego (0,1) )</li>
</ul>
<p>Warto sprawdzić powyższy wzór w praktyce. Hipotetycznie przyjmijmy więc, że dla skryptu o którym była mowa na początku tego wpisu, mamy następujące możliwości poprawy jego wydajności.</p>
<ul>
<li>1. <strong>proces autoryzacji</strong> (80%) może przebiegać dwa razy szybciej</li>
<li>2. <strong>operacje arytmetyczne</strong> (10%) mogą być wykonywane 100 razy szybciej</li>
</ul>
<p>Choć stukrotny wzrost może robić duże wrażenie, to po podstawieniu danych do formuły i wykonaniu niezbędnych obliczeń wszystko staje się jasne:</p>
<ul>
<li><strong>rozwiązanie pierwsze</strong> ~ <strong>1,6</strong> (p=2, f=1-0.8, f=0.2)</li>
<li><strong>rozwiązanie drugie</strong> ~ <strong>1,1</strong>(p=100, f=1-0.1, f=0.9)</li>
</ul>
<p>Wybór jest oczywisty - optymalizacja procesu autoryzacji. Czasami podejmowanie decyzji jest trudniejsze, gdyż do wzrostu szybkości dochodzi jeszcze jeden czynnik - nakład pracy. Warto o nim pamiętać, przed dokonaniem ostatecznego wyboru.</p>
<h3>xdebug</h3>
<p>Profilery najczęściej prezentują dane w dwóch postaciach: tabelarycznej lub / i graficznej. Xdebug pozwala przeanalizować skrypty z wykorzystaniem drugiej formy. Po pomyślnej instalacji potrzebna jest jego szybka konfiguracja (dla zainteresowanych pełna dokumentacja znajduje się <a href="http://xdebug.org/docs/profiler" title="tutaj">TUTAJ</a>).</p>
<p>
<div class="codesnip-container" >
<em>php.ini</em><br />
xdebug.profiler_enable=On<br />
xdebug.profiler_output_dir=&#8221;C:\Users\moje_konto\Desktop&#8221;</div>
</p>
<p>Pierwsza dyrektywa aktywuje opcję profilera. Druga określa katalog, gdzie wyniki jego pracy mają być zapisywane. Aby je odczytać w zależności od posiadanego systemu operacyjnego potrzebujemy odpowiedni program. Dla Linux&#8217;a jest to <a href="http://kcachegrind.sourceforge.net/cgi-bin/show.cgi" title="">Kcachegrind</a> (oferuje szerszą gamę funkcjonalności w stosunku do swojego okienkowego konkurenta), a dla Windows&#8217;a <a href="http://kcachegrind.sourceforge.net/cgi-bin/show.cgi" title="">WinCachegrind</a>. Format tworzonych przez xdebug&#8217;a logów przedstawia się następująco: <em>cachegrind.out.xx</em>, gdzie <em>xx</em> to id procesu. Oczywiście nazewnictwo można zmienić, poprzez odpowiednie ustawienie opcji <em>xdebug.profiler_output_name</em>.</p>
<p>Zbytnio nie zwlekając przejdźmy od teorii do praktyki. Poniżej zamieszczam prosty przykład, którego wykonywanie rozłożymy na czynniki pierwsze z użyciem WinCachegrind&#8217;a.</p>
<pre class="brush: php;">
function a () {

	$m = 0;
	for ($i=0;$i<1000;++$i)
		$m += 1;

}

function b () {

	$m = 0;
	for ($i=0;$i<10000;$i++)
		$m += 1;

}

a();
b();
</pre>
<p>Po otwarciu wygenerowanego przez profiler pliku (czyli na dobrą sprawę po uruchomieniu skryptu) naszym oczom ukaże się następujący widok:</p>
<p style="text-align:center;"><a href="http://blogophp.com/download/win.PNG" title="" target="_blank"><img src="http://blogophp.com/download/win.PNG" style="width:400px;border: 2px solid #25ADE9;padding 3px;" alt="" /></a></p>
<p>Jak na dłoni widać ilości oraz czasy wywołań poszczególnych funkcji, dając nam spore źródło wiedzy niezbędnej do przeprowadzenia efektywnej optymalizacji skryptu.</p>
<p>Proszę traktować ten wpis jako wstęp do zagadnienia jakim jest profilowanie kodu. Osoby zainteresowane pogłębieniem wiedzy w tym zakresie, odsyłam do zapoznania się z takim narzędziem jak <a href="http://mirror.facebook.net/facebook/xhprof/doc.html" title="XHProf">XHProf</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/07/11/profiling/feed/</wfw:commentRss>
		</item>
		<item>
		<title>template method</title>
		<link>http://blogophp.com/2010/06/03/template-method/</link>
		<comments>http://blogophp.com/2010/06/03/template-method/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 10:13:58 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[apache]]></category>

		<category><![CDATA[php]]></category>

		<category><![CDATA[wzorce projektowe]]></category>

		<category><![CDATA[projektowe]]></category>

		<category><![CDATA[wzorce]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=50</guid>
		<description><![CDATA[Metoda szablonowa to design pattern należący do grupy wzorców operacyjnych. Zgodnie z nazwą jego przeznaczeniem jest zdefiniowanie metody, która ściśle określa kolejne etapy pewnego algorytmu postępowania. Łańcuch ten stanowi szablon, który nie może ulegać modyfikacjom. Jednakże jego poszczególne kroki mogą być implementowane przez klasy podrzędne. Korzystanie z tego wzorca pozwala zatem uchronić nas przez redundancją [...]]]></description>
			<content:encoded><![CDATA[<p>Metoda szablonowa to design pattern należący do grupy wzorców operacyjnych. Zgodnie z nazwą jego przeznaczeniem jest zdefiniowanie metody, która ściśle określa kolejne etapy pewnego algorytmu postępowania. Łańcuch ten stanowi szablon, który nie może ulegać modyfikacjom.<span id="more-50"></span> Jednakże jego poszczególne kroki mogą być implementowane przez klasy podrzędne. Korzystanie z tego wzorca pozwala zatem uchronić nas przez redundancją kodu. Zasada &#8220;Don&#8217;t repeat yourself&#8221; zostaje zachowana, a ewentualne zmiany w samym algorytmie przeprowadzamy w jednym miejscu.</p>
<h3>metoda szablonowa z życia wzięta</h3>
<p>Jeśli po tym krótkim wstępie nadal nie masz pojęcia czym jest i do czego służy metoda szablonowa, to za chwilę wszystko stanie się jasne i zrozumiałe. Weźmy pod lupę pieczenie ciasta. Niezależnie od jego rodzaju możemy wyodrębnić pewne etapy, które zazwyczaj nie ulegają zmianie i są wykonywane w określonej kolejności:</p>
<ul>
<li>proces gromadzenia niezbędnych składników</li>
<li>proces przygotowania ciasta</li>
<li>proces pieczenia</li>
</ul>
<p>Dopiero dla konkretnych  ciast, każdy z tych kroków wygląda inaczej. Tymczasem szablon nie ulega żadnym przekształceniom.</p>
<h3>przykład</h3>
<p>A teraz przykład praktyczny. Poniżej znajduje się klasa bazowa implementująca omawiany przeze mnie wzorzec. Zachęcam do zapoznania się z jego kodem i naniesionymi komentarzami.</p>
<pre class="brush: php;">
// klasa zawierajaca metode szablonowa
abstract class TemplateMethod {

	// ta czesc algorytmu jest stala
	private function StartIt () {

		echo __METHOD__,'';

	}

	// ponizsza czesc algorytmu implementuja klasy podrzedne

	protected abstract function DoSomething () ;

	protected abstract function EndIt ();

	// metoda szablonowa jest niezmienna

	public final function Template () {

		$this->StartIt();
		$this->DoSomething();
		$this->EndIt();

	}

}
</pre>
<p>Czas na klasę dziedzicząca po <em>TemplateMethod</em>:</p>
<pre class="brush: php;">
class Something extends TemplateMethod {

	protected function DoSomething () {

		echo __METHOD__,'';

	}

	protected function EndIt () {

		echo __METHOD__,'';

	}

}
</pre>
<p>Na koniec zobaczmy, czy wszystko funkcjonuje w sposób prawidłowy:</p>
<pre class="brush: php;">
$obj = new Something ();
$obj->Template();
</pre>
<p>Na wyjściu otrzymujemy:</p>
<div class="codesnip-container" >
TemplateMethod::StartIt<br />
Something::DoSomething<br />
Something::EndIt</div>
</p>
<p>Mam nadzieje, iż w tym krótkim wpisie udało mi się zachęcić Was do używania tego lub w  ogóle  wzorców projektowych. Osoby zainteresowane odsyłam do zapoznania się z &#8220;bratem&#8221; template method - <strong>strategią</strong>, o której miałem już okazję napisać parę słów <a href="http://blogophp.com/2008/12/02/strategy/" title="strategia">TUTAJ</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/06/03/template-method/feed/</wfw:commentRss>
		</item>
		<item>
		<title>unit tests</title>
		<link>http://blogophp.com/2010/05/01/unit-tests/</link>
		<comments>http://blogophp.com/2010/05/01/unit-tests/#comments</comments>
		<pubDate>Sat, 01 May 2010 14:01:57 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[asercja]]></category>

		<category><![CDATA[jednostkowe]]></category>

		<category><![CDATA[testy]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=49</guid>
		<description><![CDATA[Tworząc różnego rodzaju komponenty, najczęściej w formie klas dążymy do tego, aby implementowane rozwiązania zachowywały się poprawnie w każdej, możliwej do zaistnienia sytuacji. Doskonałym narzędziem na drodze ku stworzeniu bardziej niezawodnego kodu, są testy jednostkowe (unit tests).
testy jednostkowe
Unit tests umożliwiają przeprowadzenie weryfikacji poprawnego funkcjonowania konkretnych klas, ich metod lub funkcji - zatem przynależą do grupy [...]]]></description>
			<content:encoded><![CDATA[<p>Tworząc różnego rodzaju komponenty, najczęściej w formie klas dążymy do tego, aby implementowane rozwiązania zachowywały się poprawnie w każdej, możliwej do zaistnienia sytuacji. Doskonałym narzędziem na drodze ku stworzeniu bardziej niezawodnego kodu, są testy jednostkowe (unit tests).<span id="more-49"></span></p>
<h3>testy jednostkowe</h3>
<p>Unit tests umożliwiają przeprowadzenie weryfikacji poprawnego funkcjonowania konkretnych klas, ich metod lub funkcji - zatem przynależą do grupy testów białej skrzynki (white box). W metodyce programowania zwinnego (agile software development) są one doskonałą metodą dokumentacji poszczególnych modułów aplikacji.<br />Programiści piszą testy jednostkowe równolegle z komponentem dla którego są przeznaczone. Choć takie podejście wydłuża czas pracy, to  w ostatecznym rozrachunku przynosi sporo korzyści. Moduły są bowiem mniej błędogenne, a ich działanie cechuje się większą niezawodnością. Poprzez wprowadzoną automatyzację oszczędzamy godziny, które poświęcilibyśmy na przeprowadzanie testów ręcznie i nanoszenie ewentualnych poprawek.</p>
<h3>narzędzia do testów</h3>
<p>Dla programistów PHP istnieją na rynku gotowe rozwiązania. Wśród nich pozwolę sobie wymienić <a href="http://www.phpunit.de/" title="PHPUnit">PHPUnit</a> oraz <a href="http://www.simpletest.org/" title="SimpleTest">SimpleTest</a>. Oczywiście nic nie stoi na przeszkodzie, by samemu spróbować stworzyć własny komponent do przeprowadzania testów. Potrzebna jest tylko odrobina czasu i chęci, oraz zaznajomienie się z pojęciem asercji, o której miałem już okazję napisać parę słów <a href="http://blogophp.com/2009/07/27/asercja/" title="asercja">TUTAJ</a>. Omawiane przeze mnie zagadnienie postaram się wyjaśnić z wykorzystaniem biblioteki <em>SimpleTest</em>.</p>
<h3>simpletest</h3>
<p>Klasa testowa - <em>Maths</em> będzie bardzo prosta. Jej jedyna metoda, zwróci <em>TRUE</em>, jeżeli iloraz dwóch liczb jest większy od zera. W przeciwnym wypadku - <em>FALSE</em>. Spójrzmy więc na jej deklarację.</p>
<pre class="brush: php;">
class Maths {

	public function IsPositive ($first,$second) {

		if (($first/$second)>0)
			return true;

	}

}
</pre>
<p>Jako, że test piszemy równocześnie, zatem zobaczmy jak może wyglądać:</p>
<pre class="brush: php;">
// klasa testujaca dziedziczy po UnitTestCase
class TestMaths extends UnitTestCase {

	// wolana przed wykonaniem testow
	public function setUp() {

		$this->maths = new Maths();

	}

	// wolana po zakonczeniu wszytskich testow
	public function tearDown () {

		unset($this->maths);

	}

	// metoda testowa, gdyz zawiera prefiks test
	public function testIsPositive () {

		for ($i=0;$i<100;$i++)
			// sprawdzamy czy metoda klasy Maths
			// zwraca zawsze jakas wartosc
			$this->assertnotNull(
				$this->maths->IsPositive(rand(-10,10),rand(-10,10))
			);

	}

}
</pre>
<p>Powyższa klasa musi dziedziczyć po <em>UnitTestCase</em>. Metoda <em>setUp()</em> jest wywoływana przed wykonaniem jakichkolwiek testów (czyli wszystkich metod które zaczynają się przedrostkiem <em>test</em>), a <em>tearDown()</em> po ich zakończeniu. Brakuje nam uruchomienia przedstawionego kodu.</p>
<pre class="brush: php;">
require_once(dirname(__FILE__) . '/simpletest/autorun.php');

require_once 'Maths.php';
require_once 'TestMaths.php';
// tworzymy nowa grupe testow
$test = new GroupTest('Moje testy');
// dodajemy testowanie naszej klasy
$test->addTestCase(new TestMaths());
// uruchamiamy test
$test->run(new HtmlReporter());
</pre>
<p>Na wyjściu otrzymujemy:</p>
<p style="text-align:center;"><a href="http://blogophp.com/download/error.PNG" title="error" target="_blank"><img src="http://blogophp.com/download/error_small.PNG" alt="error" style="border: 1px solid #25ADE9"/></a></p>
<p>Zapomnieliśmy o fakcie, iż nie wolno dzielić przez zero, oraz o zwracaniu wartości <em>FALSE</em> jeśli iloraz jest mniejszy lub równy zero. Wprowadzamy więc poprawki.</p>
<pre class="brush: php;">
class Maths {

	public function IsPositive ($first,$second) {

		if ($second===0)
			return 0;
		if (($first/$second)>0)
			return true;
		else
			return false;

	}

}
</pre>
<p>Ponowne uruchomienie testu daje wyczekiwany rezultat. Wszystko funkcjonuje poprawnie.</p>
<p style="text-align:center;"><a href="http://blogophp.com/download/success.PNG" title="error" target="_blank"><img src="http://blogophp.com/download/success_small.PNG" alt="error"  style="border: 1px solid #25ADE9" /></a></p>
<p>Na koniec prezentuję opis najważniejszych metod klasy <em>UnitTestCase</em>, bez znajomości których ciężko wyobrazić sobie efektywne pisanie unit tests:</p>
<ul>
<li><em><strong>assertTrue($a)</strong></em> - <em>$a</em> musi być prawdą (np. 1,true,12,&#8217;a')</li>
<li><em><strong>assertFalse($a)</strong></em> - <em>$a</em> musi być fałszem (np. 0,false,&#8221;)</li>
<li><em><strong>assertNull($a)</strong></em> - <em>$a</em> musi być NULL&#8217;em</li>
<li><em><strong>assertNotNull($a)</strong></em> - <em>$a</em> nie może być NULL&#8217;em</li>
<li><em><strong>assertEqual($a,$b)</strong></em> - <em>$a</em> i <em>$b</em> muszą być sobie równe, lecz nie koniecznie tego samego typu</li>
</ul>
<p>To tylko krótki wstęp możliwości oferowanych przez <em>SimpleTest</em>. Zainteresowanych odsyłam do dokumentacji, którą znajdziecie <a href="http://www.simpletest.org/en/overview.html" title="tutaj">TUTAJ</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/05/01/unit-tests/feed/</wfw:commentRss>
		</item>
		<item>
		<title>late static bindings</title>
		<link>http://blogophp.com/2010/03/28/late-static-bindings/</link>
		<comments>http://blogophp.com/2010/03/28/late-static-bindings/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 16:33:53 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=48</guid>
		<description><![CDATA[Wraz z wydaniem PHP 5.3 możemy w swoich aplikacjach korzystać z nowej funkcjonalności udostępnionej od tej wersji. Mowa o late static bindings, których zasadę działania najłatwiej będzie przedstawić, w oparciu o praktyczne przykłady ich użycia. Jednak zanim do tego dojdziemy - krótkie wprowadzenie.
parent i self
Są to dwa słowa kluczowe dzięki którym w sposób prosty, łatwy [...]]]></description>
			<content:encoded><![CDATA[<p>Wraz z wydaniem <strong>PHP 5.3</strong> możemy w swoich aplikacjach korzystać z nowej funkcjonalności udostępnionej od tej wersji. Mowa o <strong>late static bindings</strong>, których zasadę działania najłatwiej będzie przedstawić, w oparciu o praktyczne przykłady ich użycia. Jednak zanim do tego dojdziemy - krótkie wprowadzenie.<span id="more-48"></span></p>
<h3>parent i self</h3>
<p>Są to dwa słowa kluczowe dzięki którym w sposób prosty, łatwy i przyjemny jesteśmy w stanie odwoływać się do stałych, właściwości statycznych oraz metod - klasy rodzica (<em>parent</em>) lub samej siebie (<em>self</em>). Oczywiście z zachowaniem wszystkich zasad dziedziczenia. Spójrzmy na poniższe dwa skrypty, ilustrujące <em>parent</em> i <em>self</em> w akcji. Prosiłbym o zwrócenie uwagi na komentarze, które zawierają szczegółowe objaśniania.</p>
<h3>przykład pierwszy - self</h3>
<pre class="brush: php;">
class A {

	protected function Test () {

		echo __CLASS__;

	}

}

class B extends A {

	public function Call() {
		// jako ze jestesmy w klasie B,
		// slowo kluczowe self bedzie
		// odnosilo sie wlasnie do niej
		self::Test();
		// zapis rownoznaczny powyzszemu
		// aczkowiek w przypadku zmiany
		// nazwy klasy wymuszajacy na nas
		// dodatkowa ingerencje w strukture kodu:
		// B::Test();
	}

	public function Test () {

		echo __CLASS__;

	}

}

$obj = new B();
$obj->Call();
</pre>
<p>Na wyjściu otrzymamy:</p>
<div class="codesnip-container" >B</div>
</p>
<h3>przykład drugi - parent</h3>
<pre class="brush: php;">
class A {

	protected function Test () {

		echo __CLASS__;

	}

}

class B extends A {

	public function Call() {
		// jako ze jestesmy w klasie B,
		// slowo kluczowe parent bedzie
		// sie odnosilo do klasy rodzica - A
		parent::Test();
		// zapis rownoznaczny powyzszemu
		// aczkowiek w przypadku zmiany
		// nazwy klasy rodzica wymuszajacy na nas
		// dodatkowa ingerencje w strukture kodu:
		// A::Test();
	}

	public function Test () {

		echo __CLASS__;
	}

}

$obj = new B();
$obj->Call();
</pre>
<p>Na wyjściu otrzymamy:</p>
<div class="codesnip-container" >A</div>
</p>
<h3>late static bindings</h3>
<p>Opóźnione statyczne wiązania wprowadzają dodatkowe słowo kluczowe <em>static</em>,  uzupełniając tym samym spektrum możliwości oferowanych przez wyżej opisane: <em>parent</em> i <em>self</em>. <em>Static</em> bowiem, odwołuje się do klasy biorąc pod uwagę kontekst w jakim nastąpiło żądanie. Prześledźmy to na przykładzie:</p>
<pre class="brush: php;">
class A {

	protected static function Test () {

		echo __CLASS__;

	}

	public function Call() {
		// slowo kluczowe static bedzie
		// sie odnosilo do klasy z kontekstu ktorej
		// zastapilo zadanie
		static::Test();

	}

}

class B extends A {

	protected static function Test () {

		echo __CLASS__;

	}

}

// metoda Call wywola metode klasy B, gdyz w jej kontekscie nastapilo zadanie
B::Call();

// metoda Call wywola metode klasy A, gdyz w jej kontekscie nastapilo zadanie
A::Call();
</pre>
<p>Na wyjściu otrzymamy:</p>
<div class="codesnip-container" >BA</div>
</p>
<p>Osoby zainteresowane poszerzeniem wiedzy na temat <strong>late static bindings</strong> polecam zapoznanie się z dokumentacją <a href="http://www.php.net/manual/en/language.oop5.late-static-bindings.php" title="tutaj">TUTAJ</a>. Tym samym był to mój ostatni post na temat nowości w <strong>PHP 5.3</strong>. Przyszedł więc czas na małe podsumowanie najważniejszych zmian i nowości wniesionych z tym wydaniem, w formie krótkiej listy:</p>
<ul>
<li><strong>funkcje anonimowe</strong> - dodatkowe informacje <a href="http://blogophp.com/2009/10/31/funkcje-anonimowe/" title="tutaj">TUTAJ</a></li>
<li><strong>przestrzenie nazw</strong> - dodatkowe informacje <a href="http://blogophp.com/2010/01/17/namespaces/" title="tutaj">TUTAJ</a></li>
<li><strong>nowdoc</strong> - dodatkowe informacje <a href="http://blogophp.com/2010/03/13/nowdoc/" title="tutaj">TUTAJ</a></li>
<li><strong>late static bindings</strong></li>
<li><strong>metody magiczne <em>__callStatic()</em> i <em>__invoke()</em></strong> - dodatkowe informacje <a href="http://blogophp.com/2008/11/17/funkcje-magiczne/" title="tutaj">TUTAJ</a></li>
<li><strong>możliwość definiowania stałych przy użyciu słowa kluczowego <em>const</em></strong> - dodatkowe informacje <a href="http://www.php.net/manual/en/language.constants.syntax.php" title="tutaj">TUTAJ</a></li>
<li><strong>instrukcja goto</strong> - dodatkowe informacje <a href="http://www.php.net/manual/en/control-structures.goto.php" title="tutaj">TUTAJ</a></li>
</ul>
<p>Więcej informacji szukaj u źródła - w dokumentacji PHP.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/03/28/late-static-bindings/feed/</wfw:commentRss>
		</item>
		<item>
		<title>nowdoc</title>
		<link>http://blogophp.com/2010/03/13/nowdoc/</link>
		<comments>http://blogophp.com/2010/03/13/nowdoc/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 13:37:25 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[string]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=47</guid>
		<description><![CDATA[Ciągi znaków są nieodłącznym elementem tworzonych przy użyciu PHP skryptów. Język ten udostępnia kilka metod deklaracji tego typu danych. W wersji 5.3 dodano nową - nowdoc. W tym krótkim wpisie pokażę jak z niej korzystać.
Stringi
Zatem istnieją cztery sposoby tworzenia ciągów znaków:

pojedynczy cudzysłów (łańcuchy nieprzetwarzane)
cudzysłów (łańcuchy przetwarzane)
heredoc
nowdoc

Heredoc i nowdoc
Korzystając ze składni heredoc deklarowane łańcuchy są przetwarzane. [...]]]></description>
			<content:encoded><![CDATA[<p>Ciągi znaków są nieodłącznym elementem tworzonych przy użyciu PHP skryptów. Język ten udostępnia kilka metod deklaracji tego typu danych. W wersji <strong>5.3</strong> dodano nową - <strong>nowdoc</strong>. W tym krótkim wpisie pokażę jak z niej korzystać.<span id="more-47"></span></p>
<h3>Stringi</h3>
<p>Zatem istnieją cztery sposoby tworzenia ciągów znaków:</p>
<ul>
<li>pojedynczy cudzysłów (łańcuchy nieprzetwarzane)</li>
<li>cudzysłów (łańcuchy przetwarzane)</li>
<li>heredoc</li>
<li>nowdoc</li>
</ul>
<h3>Heredoc i nowdoc</h3>
<p>Korzystając ze składni <strong>heredoc</strong> deklarowane łańcuchy są przetwarzane. Spójrzmy na poniższy przykład:</p>
<pre class="brush: php;">
$a = 1;
// deklaracje przy uzyciu cudzyslowia
// dodano w PHP 5.3
// mozna go spokojnie pominac
echo <<<"HER"
$a
HER;
</pre>
<p>Na wyjściu otrzymamy:</p>
<div class="codesnip-container" >1</div>
</p>
<p>Natomiast <strong>nowdoc</strong> nie oferuje takiej możliwości - zachowując się analogicznie jak pojedynczy cudzysłów:</p>
<pre class="brush: php;">
$a = 1;

echo <<<'HER'
$a
HER;
</pre>
<p>Wypisze:</p>
<div class="codesnip-container" >$a</div>
</p>
<p>Od <strong>PHP 5.3</strong> obie metody mogą być używane do deklaracji zmiennych statycznych oraz stałych i właściwości klas. Popatrzmy:</p>
<pre class="brush: php;">
class Heredoc {

	const A = <<<"HER"
Test
HER;

	public $m = <<<"HER"
Test
HER;

}

class Nowdoc {

	const A = <<<'HER'
Test
HER;

	public $m = <<<'HER'
Test
HER;

}
</pre>
<p>I na koniec jeszcze jeden przykład:</p>
<pre class="brush: php;">
function heredoc () {

	static $a = <<<"HER"
1
HER;

	return $a++;

}

function nowdoc () {

	static $a = <<<'HER'
1
HER;

	return $a++;

}
</pre>
<p>I to tyle w temacie stringów.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/03/13/nowdoc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>intercepting filter</title>
		<link>http://blogophp.com/2010/02/14/intercepting-filter/</link>
		<comments>http://blogophp.com/2010/02/14/intercepting-filter/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 19:46:58 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[wzorce projektowe]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=46</guid>
		<description><![CDATA[Intercepting filter to wzorzec projektowy, który znajduje zastosowanie w aplikacjach wymagających wielokrotnego wykonywania tych samych czynności. Za przykład może posłużyć sytuacja, w której skrypt na samym początku musi uzyskać połączenie z bazą danych, a na końcu je zamknąć. Innymi często powtarzającymi się działaniami są operacje związane z autoryzacją, transakcjami, logowaniem zdarzeń, itd. Sposób implementacji intercepting [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Intercepting filter</strong> to wzorzec projektowy, który znajduje zastosowanie w aplikacjach wymagających wielokrotnego wykonywania tych samych czynności. Za przykład może posłużyć sytuacja, w której skrypt na samym początku musi uzyskać połączenie z bazą danych, a na końcu je zamknąć. Innymi często powtarzającymi się działaniami są operacje związane z autoryzacją, transakcjami, logowaniem zdarzeń, itd.<span id="more-46"></span> Sposób implementacji <em>intercepting filter</em> zależy w dużej mierze od naszych indywidualnych wymagań. Nie pozostaje nam więc nic innego, jak przejść do praktyki.</p>
<h3>przykład pierwszy</h3>
<p>Poniżej prezentuję prostą klasę <em>ImplementAction</em>, która korzysta z omawianego przeze mnie wzorca (klasa abstrakcyjna <em>Action</em>). Popatrzmy na jej kod:</p>
<pre class="brush: php;">
abstract class Action {

	abstract public function BeforeAction();

	abstract public function AfterAction();

	public function __construct () {
		$this->BeforeAction ();
	}

	public function __destruct() {
		$this->AfterAction ();
	}

}

class ImplementAction extends Action {

	public function BeforeAction() {
		echo __METHOD__;
	}

	public function AfterAction() {
		echo __METHOD__;
	}

	public function A () {
		echo __METHOD__;
	}

	public function B () {
		echo __METHOD__;
	}

}

$obj = new ImplementAction();
$obj->A();
$obj->b();
</pre>
<p>Na wyjściu otrzymamy:</p>
<div class="codesnip-container" >
ImplementAction::BeforeAction<br />
ImplementAction::A<br />
ImplementAction::B<br />
ImplementAction::AfterAction</div>
</p>
<p>Jak widać przy tworzeniu obiektu wywoływana jest metoda <em>BeforeAction()</em>, a w destruktorze <em>AfterAction()</em>. Oczywiście powyższy kod ma swoje wady i zalety. Zależą one jednak od wymogów tworzonego oprogramowania, zatem coś co dla jednych może być dużym plusem, dla innych staje się rozwiązaniem nie do przyjęcia. Najwyższy czas na przyjrzenie się bardziej zaawansowanemu modelowi użycia <em>Intercepting Filter</em>, dzięki któremu zwiększymy jego elastyczność i możliwości.</p>
<h3>przykład drugi</h3>
<pre  class="brush: php;">
// iterfejs dla filtrow
interface InterceptingFilter {

	public function doBefore();
	public function doAfter();

}

// klasa filtra
class FirstFilter implements InterceptingFilter {

	public function doBefore() {

		echo __METHOD__;

	}

	public function doAfter() {

		echo __METHOD__;

	}

}
// klasa filtra
class SecondFilter implements InterceptingFilter {

	public function doBefore() {

		echo __METHOD__;

	}

	public function doAfter() {

		echo __METHOD__;

	}

}
// klasa filtra
class AnotherFilter implements InterceptingFilter {

	public function doBefore() {

		echo __METHOD__;

	}

	public function doAfter() {

		echo __METHOD__;

	}

}
// abstrakcyjna klasa zajmujaca sie odpowiednim wywolywaniem
// filtrow
abstract class UseInterceptingFilter {

	private $filters = array();

	private function doBeforeActions() {

		foreach ($this->filters as $do)
			$do->doBefore();

	}

	private function doAfterActions() {

		foreach ($this->filters as $do)
			$do->doAfter();

	}

	public function __construct (array $filters = array()) {

		$this->filters = $filters;

		$this->doBeforeActions();

	}

	public function __destruct () {
		$this->doAfterActions();
	}

}

// klasa korzystajaca z filtrow
class Example extends UseInterceptingFilter {

	public function A() {

		echo __METHOD__;

	}

	public function B() {

		echo __METHOD__;

	}

}

// tworzymy przykladowe filtry
$filter1 = new FirstFilter();
$filter2 = new SecondFilter();
$filter3 = new AnotherFilter();

// filtry przekazywane w konstruktorze
$obj = new Example(array($filter1,$filter2,$filter3));
$obj->A();
$obj->B();
</pre>
<p>Na wyjściu dostajemy:</p>
<div class="codesnip-container" >
FirstFilter::doBefore<br />
SecondFilter::doBefore<br />
AnotherFilter::doBefore<br />
Example::A<br />
Example::B<br />
FirstFilter::doAfter<br />
SecondFilter::doAfter<br />
AnotherFilter::doAfter</div>
</p>
<p>Aby dodać nowy filtr wystarczy napisać klasę implementującą interfejs <em>InterceptingFilter</em>. Natomiast klasy z nich korzystające dziedziczą po <em>UseInterceptingFilter</em> , a ów filtry są przekazywane jako tablica w konstruktorze.</p>
<p>Zachęcam więc do własnych eksperymentów, które doprowadzą do rozwiązań w pełni dostosowanych do stawianych przez Was wymagań.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/02/14/intercepting-filter/feed/</wfw:commentRss>
		</item>
		<item>
		<title>namespaces</title>
		<link>http://blogophp.com/2010/01/17/namespaces/</link>
		<comments>http://blogophp.com/2010/01/17/namespaces/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 10:53:59 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[namespaces]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=45</guid>
		<description><![CDATA[Przestrzenie nazw, czyli jedna z najbardziej oczekiwanych funkcjonalności, została udostępniona dla programistów wraz z wydaniem PHP 5.3. Namespaces pozwalają na grupowanie klas, funkcji i stałych poprzez nadawanie im unikalnych nazw, które są następnie wykorzystywane w procesie odwoływania się do tak uporządkowanych struktur kodu. Nabiera to ogromnego znaczenia na przykład w pracy grupowej. Może się bowiem [...]]]></description>
			<content:encoded><![CDATA[<p>Przestrzenie nazw, czyli jedna z najbardziej oczekiwanych funkcjonalności, została udostępniona dla programistów wraz z wydaniem <strong>PHP 5.3</strong>. Namespaces pozwalają na grupowanie klas, funkcji i stałych poprzez nadawanie im unikalnych nazw, które są następnie wykorzystywane w procesie odwoływania się do tak uporządkowanych struktur kodu.<span id="more-45"></span> Nabiera to ogromnego znaczenia na przykład w pracy grupowej. Może się bowiem zdarzyć sytuacja, w której dwóch niezależnie pracujących informatyków, napisze klasy które będą miały tę samą nazwę. Idealnym rozwiązaniem okazują się przestrzenie nazw właśnie.</p>
<h3>praktyka</h3>
<p>W PHP namespaces można tworzyć na dwa sposoby i oba zostały zaprezentowane poniżej:</p>
<pre class="brush: php;">
namespace A;

function ShowMsg() {

	echo __FUNCTION__;

}
</pre>
<p>Albo tak:</p>
<pre class="brush: php;">
namespace A {

function ShowMsg() {

	echo __FUNCTION__;

}

}
</pre>
<p>Jak widać na powyższych przykładach, przestrzeń konstruuje się z użyciem słowa kluczowego <em>namespace</em>, po czym określana jest jej nazwę (w tym wypadku <em>A</em>). Należy pamiętać, aby<strong> deklaracja ta znajdowała się na początku skryptu</strong> (przed nią może wystąpić tylko  <em>declare</em>). Dozwolone jest też tworzenie kilku przestrzeni w jednym pliku, aczkolwiek rozwiązanie to nie jest zalecane:</p>
<pre class="brush: php;">
namespace A ;

function ShowMsg() {

	echo __FUNCTION__;

}

namespace B ;

function ShowMsg() {

	echo __FUNCTION__;

}
</pre>
<p>Można również organizować pewnego rodzaju hierarchię, formując poziomy (sub-namespaces):</p>
<pre class="brush: php;">
namespace Main\First ;

function ShowMsg() {

	echo __FUNCTION__;

}

namespace Main\First\One ;

function ShowMsg() {

	echo __FUNCTION__;

}

namespace Main\First\Two ;

function ShowMsg() {

	echo __FUNCTION__;

}
</pre>
<p>Zapewne zastanawiacie się jak wywoływać klasy, funkcje i stałe z różnych przestrzeni. Przełączanie się między nimi przypomina proces poruszania się po strukturze katalogów. Występuje tutaj pojęcie ścieżek względnych i bezwzględnych. Najprościej będzie to zrozumieć analizując prosty kod, zamieszczony poniżej: </p>
<pre class="brush: php;">
// przestrzen A\First
namespace A\First {

	function ShowMsg () {
		// specjalna stala predefiniowana zawiera
		// przestrzen w ktorym sie znajduje struktura
		echo __NAMESPACE__;

	}
}

// przestrzen A\Second
namespace A\Second {

	function ShowMsg () {

		echo __NAMESPACE__;

	}
}

// przestrzen A
namespace A {

	// sciezki bezwzgledne
	\A\First\ShowMsg();
	\A\Second\ShowMsg();

	// sciezki wzgledne (wzgledem obecnej przestrzeni)
	First\ShowMSg();
	Second\ShowMSg();

	// jeszcze jeden sposob namespace to odwolanie
	// do aktualnej przestrzeni
	namespace\First\ShowMsg();
	namespace\Second\ShowMsg();

	// wywolywanie globalnych funkcji, klas i stalych
	echo \count(array(1,2,3));

}

// przestrzen "globalna"
namespace {

}
</pre>
<p>Oczywiście nie opisałem wszystkich możliwości namespaces w PHP. Zainteresowanych odsyłam <a href="http://www.php.net/manual/en/language.namespaces.php" title="tutaj">TUTAJ</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/01/17/namespaces/feed/</wfw:commentRss>
		</item>
		<item>
		<title>introspekcja</title>
		<link>http://blogophp.com/2010/01/03/introspekcja/</link>
		<comments>http://blogophp.com/2010/01/03/introspekcja/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 13:30:44 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[introspekcja]]></category>

		<category><![CDATA[reflection]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=44</guid>
		<description><![CDATA[Introspekcja to pojęcie oznaczające zdolność aplikacji do zarządzania własnym kodem. Pozwala zatem pobierać informacje na temat klas,interfejsów i funkcji w trakcie działania programu. Termin ten jest utożsamiany z mechanizmem refleksji. W zależności od języka programowania, oba pojęcia mogą się subtelnie różnić. Z reguły mechanizm odbić (reflection) rozszerza introspekcję, oferując znacznie większe spektrum możliwości (dostarczając bardziej [...]]]></description>
			<content:encoded><![CDATA[<p>Introspekcja to pojęcie oznaczające zdolność aplikacji do zarządzania własnym kodem. Pozwala zatem pobierać informacje na temat klas,interfejsów i funkcji w trakcie działania programu. Termin ten jest utożsamiany z mechanizmem refleksji.<span id="more-44"></span> W zależności od języka programowania, oba pojęcia mogą się subtelnie różnić. Z reguły mechanizm odbić (reflection) rozszerza introspekcję, oferując znacznie większe spektrum możliwości (dostarczając bardziej szczegółowych informacji, czasami dając szansę na zmianę semantyki, czy też zachowania metod, funkcji itp.). Refleksja stanowi doskonałe narzędzie inżynierii odwrotnej i jest jedną z technik programowania generycznego.</p>
<h3>Introspekcja w PHP</h3>
<p>Po krótkim wstępie teoretycznym przechodzimy do praktycznego przykładu, wykorzystującego introspekcję. Na początku przykładowa klasa pełniąca rolę królika doświadczalnego.</p>
<pre class="brush: php;">
class Rabbit {

	public $name;

	public function PrintClassName () {

		echo __CLASS__;

	}

	public function PrintRabbitName () {

		echo $this->name;

	}

}
</pre>
<p> Pobierzmy podstawowe informacje o tej klasie. Sposób pierwszy - na podstawie nazwy klasy:</p>
<pre class="brush: php;">
var_dump (class_exists('Rabbit'));
var_dump (get_class_methods('Rabbit'));
var_dump (method_exists('Rabbit','PrintRabbitName'));
var_dump (property_exists('Rabbit','name'));
</pre>
<p>Sposób drugi - korzystając z instancji klasy:</p>
<pre class="brush: php;">
$obj = new Rabbit();
var_dump (get_class_methods($obj));
var_dump (method_exists($obj,'PrintRabbitName'));
var_dump (property_exists($obj,'name'));
</pre>
<p>Omówmy użyte powyżej funkcje:</p>
<ul>
<li><strong>class_exists(</strong><em>string</em><strong> $name)</strong> - zwraca <em>bool</em> informując czy klasa została zdefiniowana czy też nie. <strong>UWAGA!</strong> Funkcja posiada opcjonalny parametr, o którym można przeczytać w dokumentacji.</li>
<li><strong>get_class_methods(</strong><em>mixed</em><strong> $class)</strong> - zwraca <em>array</em> zawierającą wszystkie metody klasy przekazanej w parametrze (instancja lub jej nazwa). Jeśli wystąpił błąd funkcja zwróci <em>NULL</em>.</li>
<li><strong>method_exists(</strong><em>mixed</em><strong> $class, </strong><em>string</em><strong> $method)</strong> - zwraca <em>bool</em> informując czy istnieje metoda <em>$method</em> dla klasy przekazanej w parametrze <em>$class</em> (instancja lub jej nazwa).</li>
<li><strong>property_exists(</strong><em>mixed</em><strong> $class, </strong><em>string</em><strong> $property)</strong> - zwraca <em>bool</em> informując czy istnieje właściwość <em>$property</em> dla klasy przekazanej w parametrze <em>$class</em> (instancja lub jej nazwa).</li>
</ul>
<p>Oczywiście to tylko wybrane funkcje. Zainteresowanych zapraszam <a href="http://www.php.net/manual/en/ref.classobj.php" title="tutaj">TUTAJ</a>. Źródło przykładu zamieszczonego w tym poście znajdziecie <a href="http://blogophp.com/download/introspection.rar" title="przykład">TUTAJ</a>. O refleksji pisałem już trochę <a href="http://blogophp.com/2009/02/22/wstep-do-mechanizmu-refleksji-w-php/" title="tutaj">TUTAJ</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2010/01/03/introspekcja/feed/</wfw:commentRss>
		</item>
		<item>
		<title>stan</title>
		<link>http://blogophp.com/2009/11/22/stan/</link>
		<comments>http://blogophp.com/2009/11/22/stan/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 19:00:24 +0000</pubDate>
		<dc:creator>Ralf</dc:creator>
		
		<category><![CDATA[php]]></category>

		<category><![CDATA[wzorce projektowe]]></category>

		<category><![CDATA[wzorzec]]></category>

		<guid isPermaLink="false">http://blogophp.com/?p=42</guid>
		<description><![CDATA[Stan to kolejny wzorzec projektowy, z którym chciałbym Was zapoznać. W dużym stopniu wykazuje on podobieństwo do innego wzorca, którego miałem już okazję opisywać - strategii. Stan posługuje się kompozycją obiektów, implementujących ten sam interfejs, przez co pozwala na swobodne zmiany sposobu wykonania tych samych czynności w zależności od potrzeb (a konkretniej stanu obiektu). Cały [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Stan</strong> to kolejny wzorzec projektowy, z którym chciałbym Was zapoznać. W dużym stopniu wykazuje on podobieństwo do innego wzorca, którego miałem już okazję opisywać - strategii. Stan posługuje się kompozycją obiektów, implementujących ten sam interfejs, przez co pozwala na swobodne zmiany sposobu wykonania tych samych czynności w zależności od potrzeb (a konkretniej stanu obiektu).<span id="more-42"></span> Cały proces jest poddany hermetyzacji, zatem używając klasy wykorzystującej ów wzorzec zmiany delegacji są przed nami ukrywane. Choć może się to wydawać troszkę niezrozumiałe, zapraszam do zapoznania się z poniższym przykładem.</p>
<h3>stan w praktyce</h3>
<p>Przyjmijmy następujące założenie. Chcemy uzależnić wywoływanie kolejnych metod na obiekcie, na podstawie typu zmiennej (integer,boolean,itp.) wcześniej do niego przekazanej. Zatem chciałbym, aby do &#8220;obsługi&#8221; integer&#8217;a,boolean&#8217;a został delegowany odpowiedni, dedykowany obiekt. Spójrzmy na poniższy przykład:</p>
<pre class="brush: php;">
interface Stan {

	public function CheckIt ($value);
	public function WriteMessage ();

}
</pre>
<p>Powyżej znajduje się interfejs dla klas (ich implementacja znajduje się poniżej), które będą obsługiwać poszczególne typy zmiennych. Metoda <em>CheckIt($value)</em> sprawdza typ przekazanego parametru a metoda <em>WriteMessage()</em> wypisze go na wyjściu.</p>
<pre class="brush: php;">
class NoStan implements Stan {

	private $stan;

	public function __construct (UseStan $usestan) { 

		$this->stan = $usestan;

	}

	public function CheckIt ($value) {

		if (is_int($value))
			$this->stan->ChangeStan($this->stan->GetIntegerStan());
		elseif (is_bool($value))
			$this->stan->ChangeStan($this->stan->GetBooleanStan());
		elseif (is_string($value))
			$this->stan->ChangeStan($this->stan->GetStringStan());
	}

	public function WriteMessage () {

		echo 'Nie wywolano metody CheckIt()!';

	}

}

class IntegerStan implements Stan {

	private $stan;

	public function __construct (UseStan $usestan) { 

		$this->stan = $usestan;

	}

	public function CheckIt ($value) {

		echo 'Metoda CheckIt() byla juz wolana!';
	}

	public function WriteMessage () {

		$this->stan->ChangeStan($this->stan->GetNoStan());
		echo 'INTEGER';

	}

}

class StringStan implements Stan {

	private $stan;

	public function __construct (UseStan $usestan) { 

		$this->stan = $usestan;

	}

	public function CheckIt ($value) {

		echo 'Metoda CheckIt() byla juz wolana!';
	}

	public function WriteMessage () {

		$this->stan->ChangeStan($this->stan->GetNoStan());
		echo 'STRING';

	}

}

class BooleanStan implements Stan {

	private $stan;

	public function __construct (UseStan $usestan) { 

		$this->stan = $usestan;

	}

	public function CheckIt ($value) {

		echo 'Metoda CheckIt() byla juz wolana!';
	}

	public function WriteMessage () {

		$this->stan->ChangeStan($this->stan->GetNoStan());
		echo 'BOOLEAN';

	}

}
</pre>
<p>Jak widać każdy typ danych ma swoją klasę (string - <em>StringStan</em>, itd.). Wyjątek stanowi <em>NoStan</em>, której zadaniem jest określenie typu zmiennej <em>$value</em> przekazanej w metodzie <em>CheckIt($value)</em>,a następnie wydelegowanie do dalszej obsługi metod interfejsu <em>Stan</em> instancji odpowiedniej klasy(<em>StringStan</em>,<em>BooleanStan</em>,itd.). Może zastanawiać do czego służy i czym jest prywatna właściwość <em>$stan</em> klasy <em>UseStan</em>. Zatem spójrzmy na jej implementację: </p>
<pre class="brush: php;">
class UseStan {

	private $nostan;
	private $integerstan;
	private $stringstan;
	private $booleanstan;

	private $stan;

	public function __construct () {
                // przekazywanie w parametrze obiektu klasy UseStan ($this)
                // pozwoli na swobodna zmiane delegacji przez klasy stanow
                // z uzyciem setter'a stanu i getterow wszystkich stanow
		$this->nostan = new Nostan($this);
		$this->integerstan = new IntegerStan($this);
		$this->stringstan = new StringStan($this);
		$this->booleanstan = new BooleanStan($this);
                // na poczatku nie wiemy jaki typ zmiennej bedzie przekazany, zatem
                // inicjujemy wlasciwosc obiektem klasy NoStan
		$this->stan = $this->nostan;

	}

	//implementacja interfejsu obiektow - stanow

	public function CheckIt ($value) {

		$this->stan->CheckIt($value);

	}

	public function WriteMessage () {

		$this->stan->WriteMessage();

	}

	// metoda delegujaca nowy obiekt stanu do pracy

	public function ChangeStan (Stan $newstan) {

		$this->stan = $newstan;

	}

	// gettery stanów

	public function GetNoStan () {

		return $this->nostan;

	}

	public function GetIntegerStan () {

		return $this->integerstan;

	}

	public function GetStringStan () {

		return $this->stringstan;

	}

	public function GetBooleanStan () {

		return $this->booleanstan;

	}
}
</pre>
<p>Obiekty stanów używają instancji klasy <em>UseStan</em> która je posiada, do zmiany delegacji (stąd gettery wszystkich stanów i setter <em>ChangeStan($nowystan)</em>). Na koniec użycie:</p>
<pre class="brush: php;">
$obj = new UseStan();
// W zaleznosci od typu parametru, zostanie wydelegowana instancja
// odpowiednej klasy do dalszej obslugi metod interfejsu Stan.
$obj->CheckIt(true); 

// Stad tez metoda WriteMessage wywolana zostanie na obiekcie klasy
// BooleanStan a nie zadnym innym.
$obj->WriteMessage();
</pre>
<p>Powyższy przykład jest prosty i ma na celu zrozumienie wzorca <strong>Stan</strong>. Mam nadzieje, iż w jakimś stopniu Wam w tym pomogłem. Kod przykładu znajduje się <a href="http://blogophp.com/download/stan.rar" title="tutaj">TUTAJ</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogophp.com/2009/11/22/stan/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
