<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Athlan • Piotr Pelczar • blog programisty &#187; PHP</title>
	<atom:link href="http://athlan.pl/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://athlan.pl</link>
	<description>Napisać kod zrozumiały dla komputera potrafi byle głupek. Dobrzy programiści tworzą kod zrozumiały dla człowieka...</description>
	<lastBuildDate>Tue, 14 Feb 2012 14:33:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Chmura tagów Tagcloud w PHP</title>
		<link>http://athlan.pl/chmura-tagow-tagcloud-php/</link>
		<comments>http://athlan.pl/chmura-tagow-tagcloud-php/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 19:12:21 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[tagcloud]]></category>
		<category><![CDATA[tagi]]></category>
		<category><![CDATA[tags]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=439</guid>
		<description><![CDATA[Ostatnio byłem zobligowany napisać nową klasę tagów do mojego projektu Sypacz.pl, która de facto zachowała stare API, lecz rozszerzyła swoje funkcjonalności, więc w kodzie projektu nie było wielu zmian. Wena spowodowała to, że zacząłem pisać kod od zera. Cały problem polega na tym, aby napisać na tyle elastyczną klasę tagów, która przyjmie nam zestaw danych, [...]]]></description>
			<content:encoded><![CDATA[<p>Ostatnio byłem zobligowany napisać nową klasę tagów do mojego projektu <a href="http://sypacz.pl">Sypacz.pl</a>, która de facto zachowała stare API, lecz rozszerzyła swoje funkcjonalności, więc w kodzie projektu nie było wielu zmian. Wena spowodowała to, że zacząłem pisać kod od zera.</p>
<p>Cały problem polega na tym, aby napisać na tyle elastyczną klasę tagów, która przyjmie nam zestaw danych, a następnie zaprezentować ją w formie chmury, czym zaopiekuje się arkusz stylów CSS:</p>
<p><code>Nazwa tagu =&gt; Ilość występowań</code></p>
<p>Parę osób mnie pytało, jak wyciągnąć takie informacje z bazy danych:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">SELECT tag_name<span style="color: #339933;">,</span> <span style="color: #990000;">COUNT</span><span style="color: #009900;">&#40;</span>tag_name<span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">AS</span> tag_times FROM tags GROUP BY tag_name ORDER BY tag_times LIMIT <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">50</span></pre></div></div>

<p style="border: 2px solid red; padding: 15px;"><strong><span style="color: #ff0000;">Uwaga!</span></strong> Zaprezentowane wyżej zapytanie jest przykładowe, nieoptymalne, a jedynie służące do testowania chmur tagów na małych, testowych bazach danych. <strong>Optymalna implementacja struktur tagów w bazie danych</strong> dla większych projektów <strong>została opisana we <a href="/mysql-tags/">wpisie MySQL tags</a></strong>.</p>
<p>Wykorzystałem obiekt <a href="http://athlan.pl/code/Attribute.Class">Vframe_Attribute</a>, aby ustandaryzować komponent względem pozostałych w moim frameworku. Jeżeli ktoś nie chce używać obiektu Attribute, może w prosty sposób przekształcić klasę tagów, otrzymując ten sam efekt, deklarując tylko atrybut chroniony <code>protected $_aAttributes = array();</code>. Temat chmury tagów wydaje mi się na tyle trywialny, że nie ma się co nad nim zbyt wiele rozwodzić, zamieszczę tylko klasę i opiszę krótko w przykładach jej możliwości.</p>
<ul>
<li><a href="http://athlan.pl/code/Tagcloud.Class">Vframe_Tagcloud</a> &#8211; klasa tagów,</li>
<li><a href="http://athlan.pl/code/Attribute.Class"> Vframe_Attribute</a> &#8211; pomocnicza klasa atrybutów dla stosu $_aAttributes, dziedziczenie można usunąć i zadeklarować atrybut samemu.</li>
</ul>
<p>Aby stworzyć nowy obiekt tagów, po prostu wywołujemy konstruktor:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$oCloud</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Vframe_Tagcloud<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Konstruktor nie przyjmuje żadnych argumentów, wiec możemy od razu przejść do podawania obiektowi tagów. W tym miejscu warto nadmienić, że każdy znak jest rozróżniany (ze względów elastycznych), więc jeżeli chcesz, aby Nazwatagu oraz nazwatagu były rozpoznawane jako jeden klucz, wypadałoby użyć funkcji <a href="http://php.net/strtolower">strtolower</a> lub <a href="http://php.net/mb_strtolower">mb_strtolower</a> (dla Multibyte Strings):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aDataTags</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$iKey</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$aRow</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000088;">$oCloud</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>add<span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$aRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag_times'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Najistotniejszą częścią klasy jest sposób renderowania chmury, które może działać w dwóch trybach:</p>
<ul>
<li><strong>Tryb prosty</strong> zwraca nam nazwę tagu oraz jego wagę po przeliczeniu w formie liczby.</li>
<li><strong>Tryb zaawansowany</strong> zwraca nam nazwę tagu oraz tablicę z danymi:
<ul>
<li><code>level</code> &#8211; waga tagu po przeliczeniu,</li>
<li><code>count</code> &#8211; ilość występowań, taka jaką podaliśmy,</li>
<li><code>count_percentage</code> &#8211; informacja, w jakiej procentowej części ilości występowań znajduje się tag, przyjmując za 100% tag, który występuje najczęściej.</li>
</ul>
</li>
</ul>
<p>Aby w prosty sposób wyrenderować chmurę tagów, używamy poniższego przykładu:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$aDataTagsRender</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oCloud</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>render<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Najczęściej używa się trybu prostego. Oba tryby są dalej rozbudowane, bowiem <strong>mamy możliwość zdefiniowania zakresu i dokładności wag tagów</strong>. <span style="text-decoration: underline;">Domyślnie wagi tagów zawierają się pomiędzy 1, a 10</span>. Możemy na przykład przyjąć, że najmniejszą wagą jest liczba 3, największą 5, a precyzja wag tagów to 2 miejsca po przecinku:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$aDataTagsRender</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oCloud</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>render<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>W celu uniknięcia precyzji po przecinku (chcemy otrzymać liczby całkowite), ustawimy precyzję na 0.</p>
<p>Aby wywołać tryb zaawansowany, musimy podać 4 argument dla metody <code>render()</code> i ustawić go na <code>true</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$aDataTagsRender</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oCloud</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>render<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Warto w tym miejscu nadmienić, że tagi mogą nie być posortowane alfabetycznie (co ma miejsce podczas tworzenia chmury tagów). Wystarczy wywołać funkcję <code>ksort</code> (key sort).</p>
<p>Finalny przykład używania klasy tagów, celem wywołania klas CSS level_X, gdzie X to liczba całkowita z zakresu od 1 do 10, resztę robi CSS (kolorowanie, nakładanie rozmiaru):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aDataTags</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000088;">$oCloud</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Vframe_Tagcloud<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aDataTags</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$iKey</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$aRow</span><span style="color: #009900;">&#41;</span>
  <span style="color: #000088;">$oCloud</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>add<span style="color: #009900;">&#40;</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag_name'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$aRow</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tag_times'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$aDataTags</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$oCloud</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>render<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">ksort</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aDataTags</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$aDataTags</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$sTag</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #000088;">$iTag</span><span style="color: #009900;">&#41;</span>
  <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;a class=&quot;level_'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$iTag</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot; href=&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt<span style="color: #339933;">;</span>route<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tag'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sTag</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;&gt;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$sTag</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;/a&gt;'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/chmura-tagow-tagcloud-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MVC &#8211; Model</title>
		<link>http://athlan.pl/mvc-model/</link>
		<comments>http://athlan.pl/mvc-model/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 15:21:19 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[batabae]]></category>
		<category><![CDATA[baza danych]]></category>
		<category><![CDATA[dane]]></category>
		<category><![CDATA[last.fm]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[wzorce projektowe]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=258</guid>
		<description><![CDATA[Powstało masę artykułów na temat MVC, temat staje się naprawdę oklepany. Postanowiłem zebrać wszystkie informacje w jedno miejsce i streścić je w jednym artykule uzupełniając go o informacje, które nabyłem z własnego doświadczenia oraz zwracając uwagę na najistotniejsze informacje. Czym jest model Model to jedna z warstw wzorca projektowego MVC, który odpowiada logikę biznesową, czyli [...]]]></description>
			<content:encoded><![CDATA[<p>Powstało <a href="http://phpedia.pl/wiki/MVC">masę artykułów</a> na temat <strong>MVC</strong>, temat staje się naprawdę <em>oklepany</em>. Postanowiłem zebrać wszystkie informacje w jedno miejsce i streścić je w jednym artykule uzupełniając go o informacje, które nabyłem z własnego doświadczenia oraz zwracając uwagę na najistotniejsze informacje.</p>
<p><strong>Czym jest model</strong></p>
<p><strong>Model </strong>to jedna z warstw wzorca projektowego <strong>MVC</strong>, który odpowiada logikę biznesową, czyli pozyskiwanie oraz modelowanie danych pozyskanych ze źródła danych. Na samym wstępie brzmi to bardzo abstrakcyjnie. W myśl architektury MVC, <span style="text-decoration: underline;">dostęp</span> do modelu <span style="text-decoration: underline;">powinien mieć tylko kontroler</span>, a w żadnym wypadku widok. Dodatkowo model musi pobrać i modelować dane w taki sposób, <span style="text-decoration: underline;">aby można było go ewentualnie wymienić bez jakiejkolwiek ingerencji w kontroler</span>, a co za tym idzie – widok. Niezależnie od tego, z jakiego źródła informacji korzysta (pliki tekstowe, bazy danych, pliki XML)  kontroler powinien otrzymać maksymalnie zbliżone dane podczas wymiany źródła informacji.</p>
<p style="text-align: center;"><a href="http://athlan.pl/wp-content/uploads/mvc-model.png"><img class="aligncenter size-medium wp-image-259" style="border: 0pt none;" title="mvc-model" src="http://athlan.pl/wp-content/uploads/mvc-model-265x300.png" alt="mvc-model" width="265" height="300" /></a></p>
<p><strong>Model != baza danych</strong></p>
<p>Często spotykam się z definicją modelu jako źródłem połączenia i wykonywania zapytań do serwera bazy danych. Otóż nie jest to prawdą. Według ideologii MVC model powinien być jedynie pośrednikiem między warstwą aplikacji przeznaczoną do połączenia do bazy danych, wykonywania zapytań itp., a kontrolerem. Dodatkowo powinien pomóc kontrolerowi w zbudowaniu zapytania do źródła informacji (pobranie danych na podstawie kryteriów), zmodelować je i zwrócić. Dlaczego model nie jest połączeniem do bazy danych? Jeżeli model potraktujemy jako pośrednika między kontrolerem a źródłem danych, ma on prawo wybrać dowolny sposób uzyskania żądanych informacji. Wcale nie oznacza to, że model musi używać baz danych, ale może użyć plików XML lub API udostępniane przez konkretny serwis (np. YouTube)</p>
<p><strong>Wymienialność modeli i modelowanie danych</strong></p>
<p>Modelowanie informacji jest to dostosowanie ich do użytku przez kontroler. Zazwyczaj jest to przekazywanie informacji w postaci tablic, wartości logicznych, liczb i ciągów znaków. Przykładem może być pobieranie informacji z bazy danych. Kontroler de facto nie wie skąd są pobierane dane, wie to tylko model, otrzymuje suche informacje. Jak rozumieć modelowanie danych przy projektowaniu aplikacji? Wyobraźmy sobie sytuację, że zmieniamy źródło informacji z bazy danych na pliki XML. W tym przypadku kontroler <span style="text-decoration: underline;">powinien otrzymać rekordy danych jako tablica o tych samych kluczach i tych samych typach danych</span>, jak miało to miejsce przy używaniu bazy danych. <span style="text-decoration: underline;">Wymiana modelu odbywa się bez ingerowania w kontroler</span>.</p>
<p><strong>Przykłady modeli</strong></p>
<p>Najpopularniejszym sposobem pozyskania informacji jest połączenie do bazy danych i pobieranie (reprezentowanie) ich na różnoraki sposób. Doskonale wyjaśnia to tekst znajdujący się w wikipedii:</p>
<p style="padding-left: 30px;">Frameworki MVC do operacji na bazach danych używają modeli i mapowania relacyjno-obiektowego, <a class="mw-redirect" title="ORM" href="http://pl.wikipedia.org/wiki/ORM">ORM</a> (ang. <em>object-relationship mapping</em>) &#8211; w Railsach jest to ActiveRecord, w Catalyscie np. DBIx::Class, a framework <a title="Spring Framework" href="http://pl.wikipedia.org/wiki/Spring_Framework">Spring</a> w Javie używa Hibernate. Zwykle jest też możliwe użycie baz danych przez bezpośrednie zapytania <a title="SQL" href="http://pl.wikipedia.org/wiki/SQL">SQL</a>. Użycie modeli upraszcza typowe operacje &#8211; wyświetlanie ze stronicowaniem, edycję danych, a także uniezależnia od konkretnego typu bazy danych.</p>
<p>Posiadam przykład od siebie. Źródłem danych jest API serwisu Last.fm:</p>
<ul>
<li><a href="http://athlan.pl/code/ModelLastfmApi">Model</a> informacji o utworze.</li>
<li><a href="http://athlan.pl/code/ModelLastfmApiAbstract">Klasa abstrakcyjna modelu</a> opartego o API Last.fm (oparty na klasie bazowej modelu frameworka).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/mvc-model/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Wzorzec projektowy Registry w PHP</title>
		<link>http://athlan.pl/wzorzec-registry-php/</link>
		<comments>http://athlan.pl/wzorzec-registry-php/#comments</comments>
		<pubDate>Sat, 17 Jan 2009 22:22:54 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[registry]]></category>
		<category><![CDATA[wzorce projektowe]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=195</guid>
		<description><![CDATA[Registry to wzorzec projektowy, który ma za zadanie przechowywać i udostępniać dane w obrębie aplikacji. Implementacja wzorca zastępuje globalny zasięg wartości zarejestrowanych w przestrzeni klasy. Różnicą globalnego zasięgu zmiennych oraz wartości ujętych w Registry jest to, że można je ściśle kontrolować (dostęp w aplikacji itd.). W tej publikacji przedstawię jedną z najprostszego wykorzystania wzorca Registry. [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Registry</strong> to <a href="http://phpedia.pl/wiki/Wzorce_projektowe">wzorzec projektowy</a>, który ma za zadanie przechowywać i udostępniać dane w obrębie aplikacji. Implementacja wzorca zastępuje globalny zasięg wartości zarejestrowanych w przestrzeni klasy. Różnicą globalnego zasięgu zmiennych oraz wartości ujętych w Registry jest to, że można je ściśle kontrolować (dostęp w aplikacji itd.). W tej publikacji przedstawię jedną z najprostszego wykorzystania wzorca Registry.</p>
<p>Głównym założeniem Registry jest globalny zasięg (pomijając już zabezpieczenia dostępowe, którymi się nie zajmujemy). Język PHP od wersji 5 obsługuje statyczne <em>static</em> wywołania metod klas, czyniąc tym samym ich globalny zasięg wraz z połączeniem ze słowem kluczowym <em>public</em>. Dla wygody &#8211; nie trzeba tworzyć instancji klasy, więc wywołanie jest bardzo proste i nie zajmuje dużo miejsca w naszym kodzie.</p>
<p>Podstawowymi funkcjonalnościami Registry będzie:</p>
<ul>
<li>dodawanie i usuwanie,</li>
<li>pobieranie</li>
</ul>
<p>&#8230;zmiennych z rejestru. Pojęcie <em>zmienna</em> jest bardzo względne. Przechowywać w rejestrze możemy praktycznie wszystkie typy zmiennych dostępnych w PHP, włączając w to typ <em><a href="http://pl.php.net/manual/pl/resource.php">resource</a> (zasoby)</em>. Registry to nic innego, jak przechowywanie zmiennych w przestrzeni jednej klasy, więc nie mamy wobec tego żadnych ograniczeń.</p>
<ul>
<li><a href="http://athlan.pl/code/RegistrySimple">Przykładowy kod najprostszej implementacji wzorca Registry</a>.</li>
<li><a href="http://athlan.pl/code/RegistrySimpleUsage">Użycie powyższej klasy <em>RegistrySimple</em></a>.</li>
</ul>
<p>Zajmiemy się teraz bardziej rozbudowanym przykładem wzorca. Wykonamy następujące operacje:</p>
<ol>
<li>Nowa klasa <em>RegistryAdvenced</em> będzie dziedziczyła z <em>RegistrySimple</em> na potrzeby metody <em>Registry()</em>.</li>
<li>Zaimplementujemy interfejsy:
<ul>
<li><a href="http://pl.php.net/manual/pl/class.iterator.php">Iterator</a></li>
<li><a href="http://pl.php.net/manual/pl/class.arrayaccess.php">ArrayAccess</a> (na potrzeby poruszania się po instancji jak po tablicy)</li>
<li><a href="http://pl.php.net/manual/pl/class.countable.php">Countable</a> (aby łatwo otrzymać liczbę przechowywanych danych)</li>
<li><a href="http://pl.php.net/manual/pl/class.serializable.php">Serializable</a> (żeby można było <a href="http://pl.php.net/manual/pl/function.serialize.php">zaserializować</a> i <a href="http://pl.php.net/manual/pl/function.unserialize.php">odserializować</a> instancję obiektu)</li>
</ul>
</li>
<li>Dodamy prywatny konstruktor, skorzystamy ze wzorca <a href="http://phpedia.pl/wiki/Singleton">Singleton</a>.</li>
</ol>
<p><a href="http://athlan.pl/code/RegistryExtended">Gotowy kod klasy <em>RegistryAdvenced</em></a>.</p>
<p>Interpretacja i rozwijanie swojego wzorca Registry jest szeroka, można na przykład zastosowac przestrzenie rejestrów, tj. tworzyć wiele rejestrów na podstawie ich instancji. Ile programistów, tyle pomysłów, ale zasada działania nie zmienia się. Zainteresowanych zapraszam do manuala, jak problem został rozwiązany w <a href="http://framework.zend.com/manual/en/zend.registry.html">Zend_Registry</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/wzorzec-registry-php/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Paginacja (stronicowanie) w PHP</title>
		<link>http://athlan.pl/paginacja-php-stronicowanie/</link>
		<comments>http://athlan.pl/paginacja-php-stronicowanie/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 18:03:37 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[mysql limit]]></category>
		<category><![CDATA[pager]]></category>
		<category><![CDATA[paginacja]]></category>
		<category><![CDATA[stronicowanie]]></category>
		<category><![CDATA[strony]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=177</guid>
		<description><![CDATA[Zaczynając swoją przygodę z PHP nie miałem pojęcia jak wykonać paginację newsów, która załamywałaby łańcuchy liczb w momencie, w których chce. Na dzień dzisiejszy postanowiłem napisać swój nowy pager, gdyż ten, który dotychczas używałem przez ostatnie 2 lata nie odpowiadał mi pod trzema względami: nagromadzenie metod, tj. setLimit(), getLimit(), zamiast pojedynczego limit(), brak możliwości ustawienia [...]]]></description>
			<content:encoded><![CDATA[<p>Zaczynając swoją przygodę z PHP nie miałem pojęcia jak wykonać paginację newsów, która załamywałaby łańcuchy liczb w momencie, w których chce. Na dzień dzisiejszy postanowiłem napisać swój nowy pager, gdyż ten, który dotychczas używałem przez ostatnie 2 lata nie odpowiadał mi pod trzema względami:</p>
<ul>
<li>nagromadzenie metod, tj. setLimit(), getLimit(), zamiast pojedynczego limit(),</li>
<li>brak możliwości ustawienia załamywania się łańcucha (domyślnie były to 2 liczby):<br />
<code>1, 2 ... 6, 7, 8 ...  12, 13</code>.</li>
<li>brak możliwości definiowania limitu, ilości elementów oraz aktualnie przeglądanej strony w jednej metodzie, najchętniej w samym konstruktorze.</li>
</ul>
<p>Ostatnio potrzebowałem zwiększyć limit liczb &#8220;z przodu&#8221; i &#8220;tyłu&#8221; oraz &#8220;w środku&#8221;:<br />
<code>1, 2, 3 ... 5, 6, 7, 8, 9 ...  11, 12, 13</code></p>
<p>Dla tych, którzy ciągle szukają komponentu obsługującego paginację prezentuję <a href="http://athlan.pl/code/Vframe_Pagination">Vframe_Pagination</a>.</p>
<p>Implementacja od strony kontrolera (metoda krótka):</p>
<p><code>$oPager = new Vframe_Pagination($iItemsCount, $iLimit, $iCurrentPage);</code></p>
<p>Metoda długa:</p>
<p><code>$oPager = new Vframe_Pagination();<br />
$oPager-&gt;limit($iLimit);<br />
$oPager-&gt;items($iItemsCount);<br />
$oPager-&gt;page($iPage);</code></p>
<p>Metody limit, items oraz page zwracają liczby odpowiadające ich nazwą niezależnie od tego, czy została podana nowa wartość w argumencie, czy nie, co jest absolutnie wygodnym (dla mnie) rozwiązaniem.</p>
<p>Aby wyświetlić oczekiwane rekordy, wykorzystujemy pagera:</p>
<p><code>$aData = $oModel-&gt;GetList($iUser, $oPager-&gt;start(), $oPager-&gt;limit());</code></p>
<p>Lub bezpośrednio w zapytaniu do bazy dancyh:</p>
<p><code>$sSql = "SELECT news_id FROM news LIMIT " . $oPager-&gt;start() . ", " . $oPager-&gt;limit();</code></p>
<p>Od strony widoku, prezentacja pagincaji prezentuje się w bardzo prosty sposób:</p>
<p>&lt;?php echo $oPager-&gt;Render(true); ?&gt;</p>
<p>Metoda render przyjmuje kolejno:</p>
<ol>
<li><em>$mMode</em> (mixed: bool, null, string), jeżeli true, paginacja jest zwracana w formacie HTML. Jeżeli null, numerki stron podane w formie array&#8217;a zamiast linków HTML. Jeżeli string, zostaje zwracana wartość po renderowaniu pagera, np. element startujący przedział mnożony po limicie: $oPager-&gt;Render(&#8216;start&#8217;);. Ten sam efekt powoduje metoda $oPager-&gt;start();</li>
<li><em>$iDrawCutLimit</em> (int) ilość numerków na początku i końcu łańcucha paginacji.</li>
<li><em>$iDrawCutLimitCenter</em> (int) ilość numerków &#8220;w środku&#8221; obok aktualnie przeglądanej strony.</li>
<li><em>$bNavigation</em> (bool) linki &#8220;poprzednia&#8221; i &#8220;następna&#8221; strona znajdujące się na początku i końcu łańcucha.</li>
</ol>
<p>Możemy sami ostylować linki generowane przez pager. Wystarczy że w widoku dodamy swój apperance:</p>
<p><code>$this-&gt;oPager-&gt;PatternPage('&lt;a href="?[$]"&gt;[$]&lt;/a&gt;');<br />
$this-&gt;oPager-&gt;PatternPageCurrent('&lt;strong&gt;[$]&lt;/strong&gt;');<br />
$this-&gt;oPager-&gt;PatternPageNavigation('&lt;a href="?[$]" rel="nofollow"&gt;[$$]&lt;/a&gt;', array('&amp;laquo; poprzednia', 'następna &amp;raquo;'));<br />
$this-&gt;oPager-&gt;PatternSeparator('&lt;span&gt;...&lt;/span&gt;');</code></p>
<p>Końcowy efekt, możemy nie wyświetlać pagera, gdy jest tylko jedna strona elementów:</p>
<p><code>&lt;?php if($this-&gt;oPager-&gt;Render('pages') &gt; 1) {<br />
// wyswietl pager...<br />
} ?&gt;</code></p>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/paginacja-php-stronicowanie/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Podtrzymanie sesji</title>
		<link>http://athlan.pl/podtrzymanie-sesji/</link>
		<comments>http://athlan.pl/podtrzymanie-sesji/#comments</comments>
		<pubDate>Fri, 26 Dec 2008 19:35:39 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Przemyślenia]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[Usablity]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[sesje]]></category>
		<category><![CDATA[sessions]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=159</guid>
		<description><![CDATA[Dla niektórych wygasanie sesji jest zabezpieczeniem (banki, etc.). Realizując jeden z projektów oczekiwałem od systemu tego, aby użytkownik nigdy nie gubił sesji, gdy ma otwarte okno w przeglądarce. Dlaczego? Może dodaje posta, być może uzupełnia dość obszerny tekst na stronie. Gdy klika zapisz, przerzuca go do strony logowania, a cały tekst zniknął za sprawą tego, [...]]]></description>
			<content:encoded><![CDATA[<p>Dla niektórych wygasanie sesji jest zabezpieczeniem (banki, etc.). Realizując jeden z projektów oczekiwałem od systemu tego, aby użytkownik nigdy nie gubił sesji, gdy ma otwarte okno w przeglądarce. Dlaczego? Może dodaje posta, być może uzupełnia dość obszerny tekst na stronie. Gdy klika <em>zapisz</em>, przerzuca go do strony logowania, a cały tekst zniknął za sprawą tego, że jego przeglądarka nie zapisuje wartości pól formularza. Skąd to znamy.</p>
<p><strong>Jak użytkownik gubi sesję?</strong></p>
<ol>
<li>Jego ciastko wygasa, więc serwer nie może go zidentyfikować z sesją.</li>
<li>Po jakimś czasie, choćby odtworzył ciastko, plik sesji znika z naszego serwera (<a href="http://pl.php.net/manual/pl/session.configuration.php#ini.session.gc-divisor">garbage collection</a>).</li>
</ol>
<p><strong>Rozwiązania:</strong></p>
<ol>
<li>Wydłużenie czasu wygasania ciastka i sesji.</li>
<li>Odświeżenie strony w interwale mniejszym, niż wynosi czas wygasania sesji i ciastka.</li>
</ol>
<p>Rozmyślając nad podtrzymaniem sesji, próbowałem znaleźć wszystkie metody oraz wybrać najlepszą. Wszystkie sprowadzają się do &#8220;odświeżenia&#8221; strony lub jej fragmentu tak, aby nasz silnik wykonał tylko potrzebne session_start(); czyli podtrzymanie aktywności sesji. Jest kilka mniej lub bardziej zadowalających sposobów:</p>
<ol>
<li><strong>Odświeżenie całej strony.</strong><br />
To może spowodować, że dane wprowadzane przez użytkownika w formularzu zostaną utracone. Ponad to, jeżeli użytkownik czyta newsy, denerwującym może być fakt, że lista nagle zostanie przescrollowana do góry (prócz opery).</li>
<li><strong>Wysłanie requestu ajax w tle.</strong><br />
Minusem jest to, że trzeba używać biblioteki ajax lub pisać dodatkowy kod javascriptu. Jeżeli ktoś na stronie używa jakiegoś ajaxa &#8211; co za różnica. Poza tym same plusy.</li>
<li><strong>Odświeżanie ukrytej ramki</strong> iframe lub elementu frameset.<br />
Minusów usablity prawie brak. Brak potrzeby instalacji javascriptów i ajaxa. Odświeżacz powinien wysłać nagłówek <em>Refresh</em> lub odpowiedni metatag.</li>
</ol>
<p>Sposób 3 wydaje mi się najlepszy. Można go ulepszyć w ten sposób, aby ramka nie wysyłała żądania zaraz po załadowaniu strony. Powodowałoby to podwójne requesty do serwera.</p>
<ul>
<li><a href="http://athlan.pl/code/PingIframe">Przykład z ukrytym iframe</a>.</li>
<li><a href="http://athlan.pl/code/PingAdvajax">Przykład z Advajax</a>.</li>
<li>plik <code>ping.php</code> wygląda wówczas następująco: <span style="color: #999999; font-size: 9px;">aplikacje nie używające frameworków ingerujących w standardowe działanie sesji</span><br />
<code>session_start(); header('Refresh: 60');</code></li>
</ul>
<p><span style="font-size: 9px">Zapewne znajdą się osoby, które powiedzą: a co z użytkownikami, którzy mają wyłączone ramki, lub ich przeglądarki w ogóle ich nie obsługują. Zapytam wówczas: a co z użytkownikami, którzy nie akceptują cisteczek (wówczas sesje nie są dla nich użyteczne, chyba, że użyjemy przesłyki jej identyfikatora w adresie url). Dopytam również: a co z użytkownikami, którzy mają wyłączony Javascript? Patologiczne przepadki się po prostu pomija ;)</span></p>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/podtrzymanie-sesji/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Hashowanie haseł z solą</title>
		<link>http://athlan.pl/hashowanie-hasel-z-sola/</link>
		<comments>http://athlan.pl/hashowanie-hasel-z-sola/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 18:50:26 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[sha1]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=150</guid>
		<description><![CDATA[Przeglądając forum.php.pl często widziałem, jak użytkownicy przechowują hasła w swoich bazach danych. Najczęściej używają funkcji hashujących md5, sha1 i sha2. Wszystko wygląda bardzo dobrze, hasła są przechowywanie bezpiecznie. No właśnie&#8230; na ile bezpiecznie. Nie będę tutaj rozwodził się nad zabezpieczeniem baz danych, w których owa baza haseł się znajduje, ale nad samym zahashowanym ciągu. Wszyscy [...]]]></description>
			<content:encoded><![CDATA[<p>Przeglądając forum.php.pl często widziałem, jak użytkownicy przechowują hasła w swoich bazach danych. Najczęściej używają funkcji hashujących <code>md5</code>, <code>sha1</code> i <code>sha2</code>. Wszystko wygląda bardzo dobrze, hasła są przechowywanie bezpiecznie. No właśnie&#8230; na ile bezpiecznie.</p>
<p>Nie będę tutaj rozwodził się nad zabezpieczeniem baz danych, w których owa baza haseł się znajduje, ale nad samym zahashowanym ciągu. Wszyscy doskonale wiemy, że istnieją bazy md5 (sha1, sha2 również).</p>
<p><em>Przezorny zawsze ubezpieczony.</em> Wiadomo, że nigdy nic nie wiadomo.</p>
<p>Pokażę, jak dodatkowo zabezpieczyć nasze hasła. Będą przechowywane w tej samej bazie danych, używając tych samych metod hashowania, a jednak szansa na &#8220;złamanie&#8221; hasła (wyszukania w bazie) będzie niemożliwa. Posłużymy się ciągiem znaków zwanym przez programistów <em>solą </em>(<em>salt</em>). Przykład implementacji możemy znaleźć w forum IPB, natomiast phpBB pozbawione jest tego <span style="text-decoration: line-through;">fjuczuru</span> ficzera. Cała sprawa sprowadza się do wygenerowania dowolnego kawałka ciągu znaków i doklejenia go do hasła. Sól potrzebna nam będzie również przy porównaniu hasła, więc trzeba ją zapisać w bazie danych obok hasła.</p>
<p>Poniżej zamieszczam przykładową klasę, która obsługuje solenie haseł. Doklejanie soli może być napisane w dowolny sposób, zależy to od Waszej wyobraźni. Ja dodatkowo dodałem element &#8220;losowy&#8221; w postaci doklejenia do soli wyniku działania funkcji microtime().</p>
<ul>
<li><a href="http://athlan.pl/code/PassSalt">Klasa, która soli hasła.</a></li>
<li><a href="http://athlan.pl/code/PassSaltExample">Przykład</a> &#8211; zapisywanie hasła do bazy danych oraz sprawdzanie go przy logowaniu.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/hashowanie-hasel-z-sola/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
