<?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>WebProgramming - wszystko o serwisach internetowych</title>
	<atom:link href="http://www.webprogramming.pl/feed/" rel="self" type="application/rss+xml" />
	<link>http://webprogramming.pl</link>
	<description>O serwisach internetowych.</description>
	<pubDate>Sat, 20 Jun 2009 12:13:10 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>[php] Operacje na napisach (string) i ich wydajność (krótka historia)</title>
		<link>http://webprogramming.pl/2009/php-operacje-na-napisach-string-i-ich-wydajnosc/</link>
		<comments>http://webprogramming.pl/2009/php-operacje-na-napisach-string-i-ich-wydajnosc/#comments</comments>
		<pubDate>Sat, 20 Jun 2009 12:10:11 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Ciekawostki]]></category>

		<category><![CDATA[Język PHP]]></category>

		<category><![CDATA[Wydajność]]></category>

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=124</guid>
		<description><![CDATA[Od dawna zastanawiałem się, czy operacje na napisach są kosztowne (pamięciowo i/lub obliczeniowo)? W językach typu Java, C# spotykamy specjalną klasą typu StringBuilder, która jest zalecanym sposobem tworzenia napisów (jest optymalną wersją &#8220;zwykłych&#8221; napisów - optymalną pod względem wykonywania operacji na nich). W przypadku języka PHP takiej klasy nie posiadamy - istnieje tylko prosta zwykła [...]]]></description>
			<content:encoded><![CDATA[<p>Od dawna zastanawiałem się, czy operacje na napisach są kosztowne (pamięciowo i/lub obliczeniowo)? W językach typu Java, C# spotykamy specjalną klasą typu StringBuilder, która jest zalecanym sposobem tworzenia napisów (jest optymalną wersją &#8220;zwykłych&#8221; napisów - optymalną pod względem wykonywania operacji na nich). W przypadku języka PHP takiej klasy nie posiadamy - istnieje tylko prosta zwykła konkatenacja.</p>
<p><span id="more-124"></span></p>
<p>Przeprowadzałem proste badanie i okazuje się, iż konkatenacja nie alokuje więcej pamięci niż stworzenie całego napisu ad hoc, wpływa jednak nieznacznie na czas wykonania takiej operacji (jest to związane z niszczeniem i tworzeniem nowego napisu):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"> <span class="co1">// Długi napis stworzony ad hoc</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$str</span> &nbsp;= <span class="st0">&#8216;Długi napis, bardzo długi napis, zajmujący kilka tysięcy znaków &#8230;.&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Ten sam napis podzielony na części i &quot;łączony&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$str</span> &nbsp;= <span class="st0">&#8216;Długi napis, bardzo długi napis, &#8216;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$str</span> .= <span class="st0">&#8216;zajmujący kilka tysięcy znaków &#8230;.&#8217;</span>;</div>
</li>
</ol>
</div>
<p>W oby powyższych przypadkach zajętość pamięci jest taka sama, natomiast czas tworzenia napisu różni się o ok 14-17% na korzyść napisu stworzonego w jednym przepisaniu (bez konkatenacji). Nie jest to jednak duża różnica biorąc pod uwagę, iż tworzenie stringa o długości ponad 4 tys znaków zajmuje ok 0.000026 s.</p>
<p>Test był przeprowadzony na dwóch maszynach (laptopie i dzierżawionym serwerze, oba działały pod kontrolą PHP 5.2.6).</p>
<p>Z ciekawostek wartych uwagi jest fakt, iż przypisanie napisu do innej zmiennej nie oznacza alokacji dodatkowej pamięci, jak w tym przypadku:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$str</span> = <span class="st0">&#8216;Długi napis, bardzo długi napis, zajmujący kilka tysięcy znaków &#8230;.&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$tmp</span> = <span class="re0">$str</span>;</div>
</li>
</ol>
</div>
<p>Pod warunkiem jednak, iż nowo powstały napis nie zostanie zmodyfikowany:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$str</span> &nbsp;= <span class="st0">&#8216;Długi napis, bardzo długi napis, zajmujący kilka tysięcy znaków &#8230;.&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$tmp</span> &nbsp;= <span class="re0">$str</span>; <span class="co1">// Brak alokacji pamięci dla zmiennej $tmp</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$tmp</span> .= <span class="st0">&#8221;</span>; &nbsp; <span class="co1">// Alokowanie pamięci</span></div>
</li>
</ol>
</div>
<p>Innymi słowy niejawnie zmienna jest podstawiona przez &#8220;pseudo-referencje&#8221;  - jeżeli jednak nowo stworzony string się zmieni tworzone jest nowe miejsce w pamięci. Dzieje się tak również w przypadku przekazywania argumentów do funkcji/metody.</p>
<p>Aby zwolnić pamięć zajmowaną przez dany napis wystarczy zrobić jeden z dwóch sposobów:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// Pierwszy sposób - czyści zmienną</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$str</span> = <span class="kw2">null</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Drugi sposób - bardziej koszerny - likwiduje zmienną</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$str</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/php-operacje-na-napisach-string-i-ich-wydajnosc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[smarty] Ciekawe wykorzystanie modyfikatora.</title>
		<link>http://webprogramming.pl/2009/smarty-ciekawe-wykorzystanie-modyfikatora/</link>
		<comments>http://webprogramming.pl/2009/smarty-ciekawe-wykorzystanie-modyfikatora/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 22:24:50 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Ciekawostki]]></category>

		<category><![CDATA[Język PHP]]></category>

		<category><![CDATA[Serwisy internetowe]]></category>

		<guid isPermaLink="false">http://webprogramming.pl/?p=121</guid>
		<description><![CDATA[Przyszedł czas na ciekawostkę, a dokładnie na nietypowe (wg mnie) wykorzystanie modyfikatorów biblioteki Smarty. Wyobraźmy sobie, że mamy bibliotekę do obsługi formularzy (wraz z walidacją pól), która dla każdego pola przechowuje informacje o tym, czy jest ono poprawne, czy też nie - informacja ta bardzo by się przydała w warstwie widoku, tylko jak ją &#8220;przekazać&#8221;. [...]]]></description>
			<content:encoded><![CDATA[<p>Przyszedł czas na ciekawostkę, a dokładnie na nietypowe (wg mnie) wykorzystanie modyfikatorów biblioteki <a title="Biblioteka Smarty - system szablonów dla PHP." href="http://www.smarty.net/" target="_blank">Smarty</a>. Wyobraźmy sobie, że mamy bibliotekę do obsługi formularzy (wraz z walidacją pól), która dla każdego pola przechowuje informacje o tym, czy jest ono poprawne, czy też nie - informacja ta bardzo by się przydała w warstwie widoku, tylko jak ją &#8220;przekazać&#8221;. Pierwsza myśl jaka przyszłaby mi do głowy to stworzenie <em>funkcji</em> (wtyczki typu &#8216;template function&#8217;) Smarty, która realizowałoby tą funkcjonalność, na przykład:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> smarty_function_hasError<span class="br0">&#40;</span><span class="re0">$params</span>, &amp;<span class="re0">$smarty</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$hasError</span> = <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#91;</span><span class="st0">&#8216;field&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// Sprawdź, czy pole $params['field'] ma błędy</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="re0">$hasError</span> = Form::<span class="me2">getFieldError</span><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#91;</span><span class="st0">&#8216;field&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">return</span> <span class="re0">$hasError</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><span id="more-121"></span>Problem jest gdy chcemy sprawdzić w warunku &#8216;if&#8217;, czy dane pole posiada błąd. W tym przypadku najczęściej tworzy się możliwość zapisywania wyniku danej funkcji do zmiennej Smarty, w stylu:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// &#8230;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// } (linia #6)</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span><span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#91;</span><span class="st0">&#8216;assign&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$smarty</span>-&gt;<span class="me1">assign</span><span class="br0">&#40;</span><span class="re0">$params</span><span class="br0">&#91;</span><span class="st0">&#8216;assign&#8217;</span><span class="br0">&#93;</span>, <span class="re0">$hasError</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="kw1">return</span> <span class="st0">&#8221;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// return $hasError; (linia #7)</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// &#8230;</span></div>
</li>
</ol>
</div>
<p>W szablonie Smarty wykorzystanie tej wtyczki wygląda następująco:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">{hasError field=&quot;lastname&quot; assign=&quot;lastnameErr&quot;}
</div>
</li>
<li class="li1">
<div class="de1">{if $lastnameErr} &#8230; {/if}</div>
</li>
</ol>
</div>
<p>Niestety jest to mało przyjemne w użyciu&#8230; jest jednak inne wyjście - stworzenie prostego modyfikatora w postaci:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> smarty_modifier_hasError<span class="br0">&#40;</span><span class="re0">$field</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> Form::<span class="me2">getFieldError</span><span class="br0">&#40;</span><span class="re0">$field</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Wówczas wykorzystanie jest dużo prostsze i łatwiejsze:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">{if &quot;lastname&quot;|hasError} &#8230; {/if}</div>
</li>
</ol>
</div>
<p>Mimo, iż sam zapis wydaje się dość dziwny - w końcu modyfikatory powstały głównie do &#8220;filtrowania&#8221; zmiennych, a nie interpretowanie bezpośrednio napisów - to w/w sposób wydaje się idealny do tej sytuacji.</p>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/smarty-ciekawe-wykorzystanie-modyfikatora/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[ant&#124;eclipse] Kopiowanie plików na konta FTP.</title>
		<link>http://webprogramming.pl/2009/ant-eclipse-kopiowanie-plikow-na-konta-ftp/</link>
		<comments>http://webprogramming.pl/2009/ant-eclipse-kopiowanie-plikow-na-konta-ftp/#comments</comments>
		<pubDate>Thu, 28 May 2009 20:29:14 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Dział IT]]></category>

		<category><![CDATA[Oprogramowanie i narzędzia]]></category>

		<category><![CDATA[Serwisy internetowe]]></category>

		<guid isPermaLink="false">http://webprogramming.pl/?p=118</guid>
		<description><![CDATA[Tworząc serwis najczęściej pracujemy na lokalnym serwerze www/mysql - dzięki czemu dużo szybciej możemy zobaczyć rezultat naszej pracy (w 99% przypadków wystarczy odświeżyć stronę ;)). Wcześniej, czy później jednak musimy wrzucić wynik naszej ciężkej pracy na serwer FTP (np klienta) - jeżeli to jest po raz pierwszy to nie ma większego problemu - uruchamiamy klienta [...]]]></description>
			<content:encoded><![CDATA[<p>Tworząc serwis najczęściej pracujemy na lokalnym serwerze www/mysql - dzięki czemu dużo szybciej możemy zobaczyć rezultat naszej pracy (w 99% przypadków wystarczy odświeżyć stronę ;)). Wcześniej, czy później jednak musimy wrzucić wynik naszej ciężkej pracy na serwer FTP (np klienta) - jeżeli to jest po raz pierwszy to nie ma większego problemu - uruchamiamy klienta FTP i kopiujemy pliki. Problem jednak zaczyna się, gdy musimy wdrażać kolejne poprawki. Jak sobie z tym poradzić?</p>
<p><span id="more-118"></span></p>
<p>Teoretycznie możemy zrobić tak jak za pierwszym razem - za pomocą klienta FTP wrzucamy cały serwis albo wrzucamy tylko te pliki, które zmieniliśmy. Żadne z tych rozwiązań nie jest wg mnie satysfakcjonujące, ponieważ oba są dość uciążliwe. W pierwszym przypadku kopiowanie całego serwisu jest powolne (przy nawet najdrobniejsze zmianie byśmy musieli wrzucać cały serwis/cały katalog), w drugim natomiast z jednej strony bardzo łatwo pominąć jakiś plik (jest bardzo błednogenne) a z drugiej strony musimy pamiętać (albo ręcznie sprawdzać) jakie pliki zmienialiśmy.</p>
<p>Idealnym rozwiązaniem byłoby &#8220;coś&#8221;, co pamięta kiedy ostatnio wrzucałem pliki na serwer FTP i przy następnej aktualizacji kopiował tylko te najnowsze. W moim przypadku tym &#8220;czymś&#8221; jest skrypt biblioteki <a title="Biblioteka Ant - skrypty pod Eclipse." href="http://ant.apache.org/" target="_blank">Ant</a>, biblioteki (zaimplementowanej w języku Java) umożliwiającej tworzenie skryptów w plikach XML realizujących pewne określone zadania (coś w stylu makefile). Więcej informacji na jej temat można przeczytać na stronie producenta <a title="Biblioteka Ant - manual do biblioteki." href="http://ant.apache.org/manual/index.html" target="_blank">Apache Ant</a>.</p>
<p>Przykładowy skrypt wygląda mniej więcej tak (plik o nazwie build.xml):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;utf-8&quot;</span><span class="re2">?&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;project</span> <span class="re0">name</span>=<span class="st0">&quot;NazwaProjektu&quot;</span> <span class="re0">basedir</span>=<span class="st0">&quot;.&quot;</span> <span class="re0">default</span>=<span class="st0">&quot;ftp&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Zadanie kopiujące pliki zmieniane od ostatniego kopiowania &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sc3"><span class="re1">&lt;target</span> <span class="re0">name</span>=<span class="st0">&quot;ftp&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Załaduj plik zawierający datę ostatniego aktualizacji konta FTP &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;loadproperties</span> <span class="re0">srcFile</span>=<span class="st0">&quot;timestamp.dat&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Wyświetl tą datę (informacyjnie) &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;echo</span> <span class="re0">message</span>=<span class="st0">&quot;${timestamp}&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Skopiuj pliki na konto FTP &#8211;&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;ftp</span> <span class="re0">password</span>=<span class="st0">&quot;&#8230;&quot;</span> <span class="re0">server</span>=<span class="st0">&quot;&#8230;&quot;</span> <span class="re0">userid</span>=<span class="st0">&quot;&#8230;&quot;</span> <span class="re0">remotedir</span>=<span class="st0">&quot;/&quot;</span> <span class="re0">binary</span>=<span class="st0">&quot;no&quot;</span> <span class="re0">passive</span>=<span class="st0">&quot;yes&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Wybierz tylko wybrane katalogi oraz pliki &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;fileset</span> <span class="re0">dir</span>=<span class="st0">&quot;.&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Z katalogu application pobierz tylko pliki php &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;application/**/*.php&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Z katalogu www pobierz wszystkie pliki (również w podkatalogach) &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;include</span> <span class="re0">name</span>=<span class="st0">&quot;www/**/*.*&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Ale tylko te które zostały zmienione po odpowiedniej dacie &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;date</span> <span class="re0">datetime</span>=<span class="st0">&quot;${timestamp}&quot;</span> <span class="re0">when</span>=<span class="st0">&quot;after&quot;</span> <span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/fileset<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/ftp<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="coMULTI">&lt;!&#8211; Zapisz aktualny czas &#8211;&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;propertyfile</span> <span class="re0">file</span>=<span class="st0">&quot;timestamp.dat&quot;</span> <span class="re0">comment</span>=<span class="st0">&quot;Upload timestamp&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;entry</span> <span class="re0">key</span>=<span class="st0">&quot;timestamp&quot;</span> <span class="re0">type</span>=<span class="st0">&quot;date&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;now&quot;</span> <span class="re0">pattern</span>=<span class="st0">&quot;MM/dd/yyyy hh:mm aa&quot;</span><span class="re2">/&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/propertyfile<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="sc3"><span class="re1">&lt;/target<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/project<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Jak widać w/w skrypt jest dość czytelny i prosty w związku z czym nie będę się nad nim rozwodzić <img src='http://webprogramming.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> Idea jest natomiast następująca: pobierz datę ostatniej aktualizacji (linia #6), pobierz pliki (tylko z odpowiednich katalogów) zmieniane od ostatniej aktualizacji (linie #12-19), skopiuj na serwer FTP (linia #10), zapisz aktualną datę jako czas ostatniej aktualizacji (linia #22-24).</p>
<p>Jeszcze lepszym rozwiązaniem byłby kopiowanie plików bezpośrednio z serwera SVN (zakładając, że korzystacie z niego) - niestety nie każdy może sobie na takie rozwiązanie pozwolić, więc trzeba sobie radzić inaczej.</p>
<p>PS. Zalecam korzystanie z platformy <a title="Platforma Eclipse - obsługuję bibliotekę Ant." href="http://www.eclipse.org/pdt/" target="_blank">Eclipse PDT</a>, która ma wbudowaną obsługę skryptów Ant <img src='http://webprogramming.pl/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/ant-eclipse-kopiowanie-plikow-na-konta-ftp/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[php&#124;zend] Nowa biblioteka dla plików CSV (wersja 0.96)</title>
		<link>http://webprogramming.pl/2009/phpzend-nowa-biblioteka-dla-plikow-csv-wersja-096/</link>
		<comments>http://webprogramming.pl/2009/phpzend-nowa-biblioteka-dla-plikow-csv-wersja-096/#comments</comments>
		<pubDate>Sun, 17 May 2009 12:09:16 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język PHP]]></category>

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

		<category><![CDATA[Zend Framework]]></category>

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

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=115</guid>
		<description><![CDATA[Przyszedł czas na dojrzalszą wersję znanej już Wam biblioteki obsługującej pliki CSV (Fasic_Csv). Dojrzewając pozbyła się kilku błędów i niedoskonałości oraz uzyskała nowe ciekawe funkcjonalności (przyznam się że trochę jej w tym pomogłem).
Przykład użycia biblioteki Fasic CSV (wraz z nowymi funkcjonalnościami):



// Pobierz plik CSV


// &#160;nazwa pliku, załaduj cały plik, rozpoznaj automatycznie separator


$file = new Fasic_Csv&#40;&#8216;1.csv&#8217;, [...]]]></description>
			<content:encoded><![CDATA[<p>Przyszedł czas na dojrzalszą wersję znanej już Wam biblioteki obsługującej pliki CSV (<em>Fasic_Csv</em>). Dojrzewając pozbyła się kilku błędów i niedoskonałości oraz uzyskała nowe ciekawe funkcjonalności (przyznam się że trochę jej w tym pomogłem).</p>
<p>Przykład użycia biblioteki <em>Fasic CSV</em> (wraz z nowymi funkcjonalnościami):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// Pobierz plik CSV</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// &nbsp;nazwa pliku, załaduj cały plik, rozpoznaj automatycznie separator</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$file</span> = <span class="kw2">new</span> Fasic_Csv<span class="br0">&#40;</span><span class="st0">&#8216;1.csv&#8217;</span>, <span class="kw2">true</span>, <span class="kw2">true</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Zmień kodowanie, plik jest w kodowaniu UTF-8 natomiast my chcemy ISO</span></div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$file</span>-&gt;<span class="me1">setEncoding</span><span class="br0">&#40;</span><span class="st0">&#8216;UTF-8&#8242;</span>, <span class="st0">&#8216;ISO-8859-2&#8242;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Ustaw mapowanie dla obiektów</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// &nbsp;nazwa_pola =&gt; ['numer_kolumny:typ_danych' | 'funkcja anonimowa']</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$file</span>-&gt;<span class="me1">setMapping</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&#8216;price&#8217;</span> =&gt; <span class="st0">&#8216;2:round2&#8242;</span>,</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="st0">&#8216;name&#8217;</span> &nbsp;=&gt; <a href="http://www.php.net/create_function"><span class="kw3">create_function</span></a><span class="br0">&#40;</span><span class="st0">&#8216;$cells&#8217;</span>, <span class="st0">&#8216;return strtolower($cells[0]);&#8217;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Pobierz 3 linie (nie zwiększając wskaźnika), linie liczone są od 0</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$line</span> = <span class="re0">$file</span>-&gt;<span class="me1">line</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Stwórz obiekt na podstawie wcześniej zdefiniowanego mapowania</span></div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$obj</span> &nbsp;= <span class="re0">$line</span>-&gt;<span class="me1">asObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Dla linii: &quot;Nazwa Produktu;nieuzywana kolumna;13.008&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Wyświetli: &quot;stdClass Object ([price] =&gt; 13.01 [name] =&gt; &#8216;nazwa produktu&#8217;)&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span><span class="re0">$obj</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p><span id="more-115"></span></p>
<p>Oto lista zmian:</p>
<ol>
<li>[new] Obsługa kodowania, możliwość określania wejściowego i wyjściowego kodowania dla pliku (domyślne UTF-8) W przypadku gdy te kodowania są różne system konwertuję dane do formatu wyjściowego za pomocą iconv.</li>
<li>[change] Format mapowania dla obiektu - metoda <em>setMapping</em> klasy <em>Fasic_Csv</em><br />
(aktualny format to &#8216;nazwa_pola&#8217; =&gt; &#8216;numer_kolumny:typ&#8217;)</li>
<li>[change] Możliwość określania funkcji anonimowej dla mapowania<br />
(np. &#8216;name&#8217; =&gt; create_function(&#8217;$cells&#8217;, &#8216;return strtoupper($cells[2]);&#8217;)</li>
<li>[new] Możliwość dodania nowych komórek do linii (metoda <em>addMoreCells</em> klasy <em>Fasic_Csv_Line</em>)</li>
<li>[new] Proste, ale automatyczne rozpoznawanie separatora dla komórek (między &#8216;;&#8217; a &#8216;,&#8217;)</li>
<li>[change] W metodzie <em>cell</em> (klasa <em>Fasic_Csv_Line</em>) można podać ujemny numer kolumny (wówczas pobierana jest komórka liczona od końca)</li>
</ol>
<p>W aktualnej wersji nadal nie jest zaimplementowana opcja <em>preLoaded = false</em>, która umożliwiałaby wczytywanie pliku CSV linia po linii (a nie jak jest teraz załadowanie całego pliku do pamięci) - opcja ta zostanie zaprezentowana w wersji 1.0 biblioteki.</p>
<p>Uwaga: mam nadzieje, że oczywiste jest, iż w/w bibliotekę można używać nie tylko w aplikacjach opartych na <strong>Zend Framework</strong> - równie dobrze można z niej korzystać w jakiejkolwiek innych aplikacjach webowych napisanych w <strong>języku PHP</strong>.</p>
<p>Biblioteka Fasic_Csv:</p>
<ul>
<li>Źródła: <a title="Fasic_Csv - biblioteka obsługi plików CSV w Zend Framework" href="http://webprogramming.pl/downloads/Fasic_Csv-0.96.zip">http://webprogramming.pl/downloads/Fasic_Csv-0.96.zip</a></li>
<li>Wersja: 0.96</li>
<li>Data edycji: 12 maj 2009</li>
<li>Instalacja: skopiować do katalogu Fasic, który jest w ścieżce poszukiwań skryptów PHP (w tym samym katalogu, w którym jest katalog Zend),</li>
<li>Zależności: korzysta z bioblioteki Fasic_Forcetype</li>
<li>Aktualizacja: w przypadku aktualizacji do nowej wersji wystarczy nadpisać wcześniej istniejące pliki (należy również zapoznać się ze zmianami, wersja 0.96 nie jest całkowicie kompatybilna z wersją 0.9)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/phpzend-nowa-biblioteka-dla-plikow-csv-wersja-096/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[usability] Uwaga na Ajax (przykłady w jQuery).</title>
		<link>http://webprogramming.pl/2009/usability-uwaga-na-ajax-przyklady-w-jquery/</link>
		<comments>http://webprogramming.pl/2009/usability-uwaga-na-ajax-przyklady-w-jquery/#comments</comments>
		<pubDate>Sat, 09 May 2009 21:43:52 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język JavaScript]]></category>

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

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=106</guid>
		<description><![CDATA[Odkąd Ajax stał się tak popularny coraz więcej osób zauważa również jego wady (niestety taki jest koszt popularności ;)). Głównymi zarzutami (ale nie jedynymi) w jego kierunku to:

Zaburzenie standardowej interakcji z użytkownikiem.
Niepoprawne działanie przycisku Wstecz/Back w przeglądarce.

Zamiast rozczulać się nad nimi, zastanówmy się jak można sobie z nimi poradzić - tak abyśmy mogli tworzyć aplikacje [...]]]></description>
			<content:encoded><![CDATA[<p>Odkąd Ajax stał się tak popularny coraz więcej osób zauważa również jego wady (niestety taki jest koszt popularności ;)). Głównymi zarzutami (ale nie jedynymi) w jego kierunku to:</p>
<ol>
<li>Zaburzenie standardowej interakcji z użytkownikiem.</li>
<li>Niepoprawne działanie przycisku Wstecz/Back w przeglądarce.</li>
</ol>
<p><span id="more-106"></span>Zamiast rozczulać się nad nimi, zastanówmy się jak można sobie z nimi poradzić - tak abyśmy mogli tworzyć aplikacje internetowe podążające za nowościami (korzystające z nowych trendów jakim niewątpliwie jest Ajax), a jednocześnie nie zaburzające standardowych przyzwyczajeń użytkownika. Oto podpowiedzi jak temu zaradzić w przypadku korzystania z <a title="jQuery - biblioteka JavaScript." href="http://jquery.com/" target="_blank">jQuery</a>:</p>
<ol>
<li><em>Zaburzenie standardowej interakcji z użytkownikiem.</em><br />
Głównym zarzutem w tej kategorii jest brak wyświetlania informacji użytkownikowi, że coś się dzieje. W przypadku zwykłych żądań przeglądarka &#8220;mówiła&#8221;, czy dana strona jest ładowana czy też nie. W przypadku zapytań Ajax sami musimy o to zadbać. W dobrym tonie jest też blokowanie linku/przycisku (który aktywuje żądanie Ajax) tak, aby użytkownik nie mógł drugi raz wykonać tej samej akcji (zmniejszy to obciążenie naszego serwera) - z obserwacji moich wynika, że ludzie lubią klikać w nieskończoność na link mając nadzieje, że dzięki temu strona się szybciej załaduje..<br />
Ważne jest, aby zawsze wyświetlać użytkownikowi odpowiednią informację, iż żądanie jest właśnie obsługiwane (standardowym sposobem jest wyświetlanie kręcącego się kółeczka) - w jQuery można to uczynić na przykład tak:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="coMULTI">/*** Metody globalne, dla wszystkich żądań Ajax&#8217;owych ***/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Wyświetl &#8216;div&#8217; o id &#8216;loading&#8217; na początku zapytania Ajax</span></div>
</li>
<li class="li1">
<div class="de1">$<span class="br0">&#40;</span><span class="st0">&quot;#loading&quot;</span><span class="br0">&#41;</span>.<span class="me1">ajaxStart</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;$<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Schowaj &#8216;div&#8217; o id &#8216;loading&#8217; po zakończeniu zapytania Ajax</span></div>
</li>
<li class="li1">
<div class="de1">$<span class="br0">&#40;</span><span class="st0">&quot;#loading&quot;</span><span class="br0">&#41;</span>.<span class="me1">ajaxStop</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;$<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">hide</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/*** Metody lokalne, tylko dla aktualnego żądania Ajax&#8217;owego ***/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Wyświetl &#8216;div&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">$<span class="br0">&#40;</span><span class="st0">&#8216;#loading&#8217;</span><span class="br0">&#41;</span>.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">$.<span class="me1">ajax</span><span class="br0">&#40;</span><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;complete: <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// Schowaj &#8216;div&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">&#8216;#loading&#8217;</span><span class="br0">&#41;</span>.<span class="me1">hide</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
</li>
<li><em>Niepoprawne działanie przycisku Wstecz/Back w przeglądarce.</em><br />
W tym przypadku wystarczy zainstalować jedną z wtyczek do jQuery, która eliminuje ten problem. Wśród bibliotek, które mogą być w tym pomocne znajdują się między innymi: <a title="jQuery History - biblioteka do obsługi historii dla Ajax." href="http://www.mikage.to/jquery/jquery_history.html" target="_blank">jQuery History</a> lub <a title="jQuery History Remote - biblioteka do obsługi historii dla Ajax." href="http://stilbuero.de/jquery/history/" target="_blank">jQuery History/Remote</a>. W przypadku biblioteki jQuery History wykorzystanie jej jest bardzo proste (bazując na przykładzie na stronie głównej projektu):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// Funkcja pobierająca treść na podstawie hasha, wykonywana:</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// 1. po wykonaniu $.historyInit();</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// 2. po wykonaniu $.historyLoad();</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// 3. po naciśnięciu przycisku &quot;Wstecz&quot;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">function</span> pageload<span class="br0">&#40;</span>hash<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Hash nie zawiera znaku &#8216;#&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Div o id &#8216;content&#8217; przechowuje treść strony</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">if</span><span class="br0">&#40;</span>hash<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// Pobierz stronę</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">&quot;#content&quot;</span><span class="br0">&#41;</span>.<span class="me1">load</span><span class="br0">&#40;</span>hash + <span class="st0">&quot;.html&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// Brak strony do pobrania</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">&quot;#content&quot;</span><span class="br0">&#41;</span>.<span class="me1">empty</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">$<span class="br0">&#40;</span>document<span class="br0">&#41;</span>.<span class="me1">ready</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Zainicjuj wtyczkę.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// &nbsp;W parametrze przekazujemy funkcję, która realizuje pobieranie treści</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;$.<span class="me1">historyInit</span><span class="br0">&#40;</span>pageload<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Zainicjuj zdarzenia załadowania strony</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;$<span class="br0">&#40;</span><span class="st0">&quot;a[@rel='history']&quot;</span><span class="br0">&#41;</span>.<span class="me1">click</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="co1">// Hash określa która stronę mam pobrać</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw2">var</span> hash = <span class="kw1">this</span>.<span class="me1">href</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="re0">/^.<span class="me1">*</span>#/</span>, <span class="st0">&#8221;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="co1">// Załaduj stronę - wykonuje metodę pageload.</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; $.<span class="me1">historyLoad</span><span class="br0">&#40;</span>hash<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Łącząc powyższe rozwiązania z naszą aplikacją możemy uzyskać bardzo funkcjonalną i użyteczną (ang. <em>usability</em>) aplikację internetową, jednocześnie nie irytując użytkownika ;).</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/usability-uwaga-na-ajax-przyklady-w-jquery/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[php&#124;zend] Biblioteka obsługi plików CSV - przykład.</title>
		<link>http://webprogramming.pl/2009/php-zend-biblioteka-obslugi-plikow-csv-przyklad/</link>
		<comments>http://webprogramming.pl/2009/php-zend-biblioteka-obslugi-plikow-csv-przyklad/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 22:31:30 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język PHP]]></category>

		<category><![CDATA[Serwisy internetowe]]></category>

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

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=114</guid>
		<description><![CDATA[Ponad dwa miesiące temu (ale ten czas leci&#8230;) przedstawiłem Wam propozycję klasy ułatwiającą pracę z plikami CSV - obiecałem wówczas, iż przedstawię bardziej zaawansowany przykład jej wykorzystania. Dotrzymuje więc obietnicy ;).
Przypomnę, iż poprzednio zaprezentowałem ogólne możliwości biblioteki Fasic_Csv, które między innymi skupiały się na:

pobraniu następnej (lub dowolnie wybranej) linii z pliku CSV w postaci napisu [...]]]></description>
			<content:encoded><![CDATA[<p>Ponad dwa miesiące temu (ale ten czas leci&#8230;) przedstawiłem Wam propozycję klasy <a title="Klasa obsługi plików CSV w PHP/Zend." href="http://webprogramming.pl/2009/php-biblioteka-obslugi-plikow-csv/" target="_self">ułatwiającą pracę z plikami CSV</a> - obiecałem wówczas, iż przedstawię bardziej zaawansowany przykład jej wykorzystania. Dotrzymuje więc obietnicy ;).</p>
<p>Przypomnę, iż poprzednio zaprezentowałem ogólne możliwości biblioteki <code>Fasic_Csv</code>, które między innymi skupiały się na:</p>
<ul>
<li>pobraniu następnej (lub dowolnie wybranej) linii z pliku CSV w postaci napisu oraz tablicy komórek</li>
<li>pobraniu wybranej komórki, dla której można było określać jej typ (patrz biblioteka <code>Fasic_Forcetype</code>)</li>
</ul>
<p><span id="more-114"></span></p>
<p>Powyższe funkcjonalności są dość oczywiste&#8230; jednak omawiana biblioteka potrafi coś więcej&#8230;a mianowicie pobranie linii w postaci obiektu. Jak do tego się zabrać?</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// Plik plikcsv.csv:</span></div>
</li>
<li class="li1">
<div class="de1"><span class="nu0">1</span>,Szymon</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Otwórz plik, cały plik zostanie wczytany do pamięci</span></div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$file</span> = <span class="kw2">new</span> Fasic_Csv<span class="br0">&#40;</span>‘plikcsv.csv’<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Ustaw mapowanie dla danych (nazwa pola obiektu - numer kolumny),</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// &nbsp;określając co najmniej nazwę pola i numer kolumny</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$file</span>-&gt;<span class="me1">setMapping</span><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// &#8216;numer kolumny w pliku CSV&#8217; =&gt; &#8216;nazwa pola w obiekcie&#8217;:'wymagany typ pola&#8217;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="co1">// &nbsp; &#8216;typ pola&#8217; jest opcjonalny, przyjmuje takie wartości jak Fasic_Forcetype</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="nu0">1</span> =&gt; <span class="st0">&#8216;id:int&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="nu0">2</span> =&gt; <span class="st0">&#8216;name&#8217;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Dla każdego kolejnego wiersza</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">while</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$line</span> = <span class="re0">$file</span>-&gt;<span class="me1">line</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> !== <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Pobierz linie w formacie tablicy, czyli po staremu&#8230;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$arr</span> = <span class="re0">$line</span>-&gt;<span class="me1">asArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Pobierz linie w formacie obiektu (klasy stdClass) na podstawie mapowania</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$obj</span> = <span class="re0">$line</span>-&gt;<span class="me1">asObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="co1">// Wówczas dla linii numer 0</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// &nbsp;$arr[0] == 1, $arr[1] == &#8216;Szymon&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// &nbsp;$obj-&gt;id == 1, $obj-&gt;name == &#8216;Szymon&#8217;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// W przypadku gdy podane są typy pól obiektu (wartości po &#8216;:&#8217;) wykonanie</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$ok</span> &nbsp;= <span class="re0">$line</span>-&gt;<span class="me1">isValid</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="co1">// zwraca true, jeżeli ma wartości poprawne, false w przeciwnym przypadku</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Jak widać na powyższym przykładzie korzystanie z wersji &#8220;obiektowej&#8221; pobranej linii pliku CSV jest bardziej przejrzyste i ładniejsze. Dodatkowo umożliwia definiowanie typów dla wybranych pól.</p>
<p>Opcja ta okazuję się bardzo przydatna również w przypadku, gdy chcemy pobrać takie same dane z różnych plików (które są zapisane w różnych formatach, czyli np w jednym id jest na pozycji 2 a w drugim na pozycji 9). Wówczas definiujemy dwie różne mapy i w linii #7 rozpoznajemy, którą z nich wykorzystać. Dalsza część naszego skryptu będzie wyglądała identycznie dla każdego pliku.</p>
<p>Powyższy przykład opierał się na bibliotece <code>Fasic_Csv</code> w wersji 0.9, którą można pobrać <a title="Download biblioteki CSV dla PHP/Zend," href="http://webprogramming.pl/downloads/Fasic_Csv-0.9.zip" target="_self">tutaj</a>. Jednak już niebawem pojawi się następna wersja (poprawione błędy i kilka nowych funkcjonalności).</p>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/php-zend-biblioteka-obslugi-plikow-csv-przyklad/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[php] Jaki kierunek język PHP powinien obrać?</title>
		<link>http://webprogramming.pl/2009/php-jaki-kierunek-powinien-obrac/</link>
		<comments>http://webprogramming.pl/2009/php-jaki-kierunek-powinien-obrac/#comments</comments>
		<pubDate>Fri, 10 Apr 2009 18:00:36 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język PHP]]></category>

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

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

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=107</guid>
		<description><![CDATA[Do największych bolączek programistów PHP (moim zdaniem) do tej pory można było zaliczyć:

Niezgodność nazw funkcji, mało spójne API.
Brak oficjalnego frameworka.
Wydajność aplikacji.

Czy coś się zmieniło? Postanowiłem przeanalizować aktualną sytuację w ramach w/w punktów  


Niezgodność nazw funkcji (np. strpos, str_replace), mało spójne API (kolejność parametrów w funkcjach operujących na napisach).
Niestety dopóki autorzy interpretatora będą chcieli zachować [...]]]></description>
			<content:encoded><![CDATA[<p>Do największych bolączek programistów PHP (moim zdaniem) do tej pory można było zaliczyć:</p>
<ol>
<li>Niezgodność nazw funkcji, mało spójne API.</li>
<li>Brak oficjalnego frameworka.</li>
<li>Wydajność aplikacji.</li>
</ol>
<p>Czy coś się zmieniło? Postanowiłem przeanalizować aktualną sytuację w ramach w/w punktów <img src='http://webprogramming.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><span id="more-107"></span></p>
<ol>
<li>Niezgodność nazw funkcji (np. strpos, str_replace), mało spójne API (kolejność parametrów w funkcjach operujących na napisach).<br />
Niestety dopóki autorzy interpretatora będą chcieli zachować zgodność z poprzednimi wersjami PHP dopóty ten problem nie zniknie. Według mnie przyszedł czas na odświeżenie podstawowych funkcji i metod i ujednolicenie wszystkiego, nawet kosztem kompatybilności. W szczególnym przypadku można stworzyć nowe, spójne funkcje/metody nie rezygnując ze starych (oznaczając je jednocześnie jako <em>deprected</em>).</li>
<li>Brak oficjalnego frameworka.<br />
W ciągu kilku ostatnich lat powstało dużo frameworków dla PHP (CakePHP, PRADO, phpMVC itp.) jednak wszystkie były tworzone przez programistów &#8220;na własną rękę&#8221; - cześć z nich natomiast było przeszczepieniem znanego frameworka w określonej technologii (np. Java) do środowiska PHP (np. phpMVC było inspirowane frameworkiem Struts) - niestety nie zawsze udanym. Całe szczęście firma, która najbardziej jest związana z PHP (czyli Zend) przebudziła się ze śpiączki i stworzyła bardzo ciekawy system Zend Framework (o świetnej dokumentacji i bardzo fajnej budowie). Jest to według mnie bardzo jasne światełko w tunelu, do którego śmiało można podążać.</li>
<li>Wydajność aplikacji.<br />
Bardzo często mówi się o wydajności aplikacji napisanych w PHP, niestety w porównaniu z niektórymi językami wydajność może okazać się trochę mniejsza (głównie ze względu na fakt, iż język Java, Python są kompilowane do kodu pośredniego). Jednak dzięki akceleratorom takim jak &#8220;Zend Optimalizer&#8221;, &#8220;eAccelerator&#8221;, czy też &#8220;Alternative PHP Cache&#8221; wydajność ta drastycznie wzrasta, w związku z czym różnice wydajności również drastycznie maleją. Co ciekawsze ostatni z wymienionych ma być dostępny domyślnie wraz z PHP 6&#8230; pytanie tylko kiedy ona będzie oficjalnie wydana.</li>
</ol>
<p>Jak widać póki co tylko punkt pierwszy nie jest &#8220;ruszony&#8221;, w związku z czym pozostaje nam albo korzystanie z dostępnych funkcji (korzystając z pomocy Eclipse można się nawet do nich przyzwyczaić ;)) albo opakowanie ich w bardziej przystępny (na przykład obiektowy) sposób.</p>
<p>Nie ulega jednak wątpliwości, iż do walki ruszyły dwa dość ciekawe języki (mam tutaj na myśli oczywiście Python ze swoim Django oraz Ruby wraz z Ruby on Rails) w związku z czym PHP musi coraz bardziej walczyć jeżeli nie chce stracić swoich zwolenników.</p>
<p>PS. Czy pominąłem coś, co powinno się znaleźć na tej liście?</p>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/php-jaki-kierunek-powinien-obrac/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programista Zend Framework - poziomy wtajemniczenia.</title>
		<link>http://webprogramming.pl/2009/programista-zend-framework-poziomy-wtajemniczenia/</link>
		<comments>http://webprogramming.pl/2009/programista-zend-framework-poziomy-wtajemniczenia/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 22:33:22 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język PHP]]></category>

		<category><![CDATA[Serwisy internetowe]]></category>

		<category><![CDATA[Zend Framework]]></category>

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=113</guid>
		<description><![CDATA[System Zend Framework stał się ostatnimi czasy bardzo popularny, w związku z czym jego znajomość jest bardzo mile widziana wśród pracodawców (czasami wręcz wymagana)&#8230; zastanawia mnie jednak co się kryje pod pojęciem &#8220;umiejętność ZF&#8221;.
Osoby, które chociaż trochę liznęły systemu Zend Framework wiedzą, iż serwisy oparte na ZF mogą być stworzone na 1001 sposobów (co w [...]]]></description>
			<content:encoded><![CDATA[<p>System Zend Framework stał się ostatnimi czasy bardzo popularny, w związku z czym jego znajomość jest bardzo mile widziana wśród pracodawców (czasami wręcz wymagana)&#8230; zastanawia mnie jednak co się kryje pod pojęciem &#8220;umiejętność ZF&#8221;.<br />
Osoby, które chociaż trochę liznęły systemu Zend Framework wiedzą, iż serwisy oparte na ZF mogą być stworzone na 1001 sposobów (co w tym przypadku jest dużym plusem), przy czym każdy z nich będzie inny.. jedynie co może być stałe to zbiór podstawowych klas, takich jak Zend_Controller_Front,  Zend_Controller_Action, itp&#8230;</p>
<p><span id="more-113"></span>Dumając trochę nad tym wyloniła mi się odpowiedź w postaci 3 poziomów wtajemniczenia:</p>
<p><strong>Poziom 1- użytkowy</strong></p>
<p>Do tej grupy należą osoby, które potrafią korzystać z systemu (opartego na ZF), pod warunkiem, że jest on skonfigurowany, jego struktura jest określona, a jego zadaniem jest głównie tworzyć nowe funkcjonalności. Takie osoby wiedzą mniej więcej jak działa Zend Framework na zewnątrz (nie tyka się jego wnętrzności) oraz znają zasady w nim obowiązujące.</p>
<p><strong>Poziom 2 - programistyczny</strong></p>
<p>Osoby, które oprócz wiedzy z poziomu 1 potrafią również poprawiać mniejsze błędy w istniejącym systemie i łatać dziury. Orientują się jak funkcjonuje system, jaki jest przepływ żądania, gdzie i co się znajduje itp. Znając konkretny problem potrafią również znaleźć do niego ładne rozwiązanie oraz zaimplementować je.</p>
<p><strong>Poziom 3 - projektowy</strong></p>
<p>Do ostatniego poziomu natomiast należą osoby, których dodatkowo cechuje duża wiedza, doświadczenie i umiejętność projektowania, dokonywania zmian koncepcyjnych systemu itp. Osoby te znają bardzo dobrze koncepcje wzorców projektowych, dobrych praktyk programistycznych (w szczególności w systemie ZF). Potrafią zaprojektować i przygotować gotowe środowisko programistyczne oparte na systemie Zend Framework zgodne z oczekiwaniami zleceniodawcy.</p>
<p>Oczywiste jest, iż podział jest dość płynny i w niektórych przypadkach ciężko by było zakwalifikować daną osobę do którejś z w/w poziomów. A Ty do której grupy należysz?</p>
<p><em>Uwaga:</em> podobny opis poziomów można by zdefiniować prawdopodobnie dla wszystkich systemów, czy też frameworków (nie koniecznie musi być nim ZF).</p>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/programista-zend-framework-poziomy-wtajemniczenia/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[php&#124;zend] Biblioteka obsługi plików CSV.</title>
		<link>http://webprogramming.pl/2009/php-biblioteka-obslugi-plikow-csv/</link>
		<comments>http://webprogramming.pl/2009/php-biblioteka-obslugi-plikow-csv/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 00:24:18 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język PHP]]></category>

		<category><![CDATA[Oprogramowanie i narzędzia]]></category>

		<category><![CDATA[Serwisy internetowe]]></category>

		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://webprogramming.pl/?p=97</guid>
		<description><![CDATA[Już ładne kilkanaście miesięcy temu pracowałem nad projektem, w którym ważną częścią był import plików CSV (zapis z plików Excel). Przyznaje się bez bicia, iż wówczas zrobiłem to dość &#8220;nieładnie&#8221; - pomieszałem logikę importu z samym parsowaniem pliku i walidacją. Postanowiłem, więc że napiszę taki parser jeszcze raz - tym razem wg zasad naszego rzemiosła [...]]]></description>
			<content:encoded><![CDATA[<p>Już ładne kilkanaście miesięcy temu pracowałem nad projektem, w którym ważną częścią był import plików CSV (zapis z plików Excel). Przyznaje się bez bicia, iż wówczas zrobiłem to dość &#8220;nieładnie&#8221; - pomieszałem logikę importu z samym parsowaniem pliku i walidacją. Postanowiłem, więc że napiszę taki parser jeszcze raz - tym razem wg zasad naszego rzemiosła (standardowo bazuję na języku PHP i systemie Zend Framework).<br />
<span id="more-97"></span><br />
Funkcjonalności tworzonej biblioteki bazowały na tych, które były potrzebne w/w projekcie plus kilka innych udogodnień, ostatecznie lista założeń jest następująca:</p>
<ol>
<li>dogodne pobieranie całych linii/komórek</li>
<li>sprawdzanie poprawności formatu wybranych komórek oraz ich filtrowanie (wymuszanie typu)</li>
<li>pomijanie nagłówków jeżeli jest taka potrzeba</li>
</ol>
<p>Proste wykorzystanie biblioteki:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">// Otwórz plik, plik zostanie wczytany do pamięci</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$file</span> = <span class="kw2">new</span> Fasic_Csv<span class="br0">&#40;</span>‘plikcsv.csv’<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Dla każdego kolejnego wiersza</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">while</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re0">$line</span> = <span class="re0">$file</span>-&gt;<span class="me1">line</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> !== <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="co1">// Pobierz drugą komórkę (komórki liczone są od zera, podobnie jak linie)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$line</span>-&gt;<span class="me1">ceil</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Pobierz pierwszą komórkę i wymuś typ (konwersja)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$line</span>-&gt;<span class="me1">ceil</span><span class="br0">&#40;</span><span class="nu0">0</span>, ‘float’<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Pobierz pierwszą komórkę i sprawdź typ (w przypadku niepoprawnego typu</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="co1">//  wyrzuca wyjątek Fasic_Csv_Exception)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$line</span>-&gt;<span class="me1">ceil</span><span class="br0">&#40;</span><span class="nu0">0</span>, ‘float’, ‘float’<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// Dodatkowo możemy pobrać całą linie w formacie..</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// … napisu (oryginalny format z pliku)</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="re0">$line</span>-&gt;<span class="me1">asString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="co1">// … tablicy</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$line</span>-&gt;<span class="me1">asArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Skocz do 11tego wiersza:</span></div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$file</span>-&gt;<span class="me1">goto</span><span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Wówczas instrukcja:</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$file</span>-&gt;<span class="me1">line</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//  zwraca wiersz 11 i zwiększa wskaźnik (następne wywołanie tej metody</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//   zwróci wiersz 12sty).</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// Pobierz następną linie, wg aktualnej pozycji, nie zwiększając wskaźnika</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// W pierwszym obiegu pętli aktualny wskaźnik ma wartość 0, natomiast</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//  poniższa instrukcja zwraca wiersz 1 (dzięki temu możemy wykonać &quot;look up&quot;).</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$file</span>-&gt;<span class="me1">line</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>W przypadku metody ceil(), wartości drugiego i trzeciego parametru są takie same. Wartości typów wykorzystywane w tej bibliotece opierają się na bibliotece <code>Fasic_Forcetype</code>, o której wspomniałem już <a title="Fasic_ForceType - biblioteka dla Zend Framework." href="http://webprogramming.pl/2009/phpzend-prosta-klasa-do-konwertowaniasprawdzania-typu/">wcześniej</a>.</p>
<p>Powyższy przykład przedstawia najprostsze wykorzystanie biblioteki <code>Fasic_Csv</code>, w najbliższym czasie przedstawię inny sposób wykorzystania jej. Póki co zapraszam do analizy kodu ;).</p>
<p>Biblioteka Fasic_Csv:</p>
<ul>
<li>Źródła: <a title="Fasic_Csv - biblioteka obsługi plików CSV w Zend Framework" href="http://webprogramming.pl/downloads/Fasic_Csv-0.9.zip">http://webprogramming.pl/downloads/Fasic_Csv-0.9.zip</a></li>
<li>Wersja: 0.9</li>
<li>Data edycji: 10 luty 2009</li>
<li>Instalacja: skopiować do katalogu Fasic, który jest w ścieżce poszukiwań skryptów PHP (w tym samym katalogu, w którym jest katalog Zend)</li>
<li>Zależności: korzysta z bioblioteki Fasic_Forcetype</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/php-biblioteka-obslugi-plikow-csv/feed/</wfw:commentRss>
		</item>
		<item>
		<title>[usability&#124;javascript] Zabawy JavaScript&#8217;owo-Ajax&#8217;owe.</title>
		<link>http://webprogramming.pl/2009/usability-javascript-zabawy-javascriptowo-ajaxowe/</link>
		<comments>http://webprogramming.pl/2009/usability-javascript-zabawy-javascriptowo-ajaxowe/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 17:10:03 +0000</pubDate>
		<dc:creator>Szymon Szczepaniak</dc:creator>
		
		<category><![CDATA[Język JavaScript]]></category>

		<category><![CDATA[Serwisy internetowe]]></category>

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

		<guid isPermaLink="false">http://webprogramming.pl/?p=105</guid>
		<description><![CDATA[Aby urozmaicić look &#38; feel strony coraz częściej wykorzystuje się możliwości jakie daje nam JavaScript &#38; Ajax&#8230; i bez wątpienia nie należy się tego wstydzić. Jest jednak jedno ale&#8230;Mianowicie często zapominamy o ważnej rzeczy  jak użyteczność tych nowych &#8220;bajerów&#8221;. Pod adresem Ajax&#8217;a zostało przedstawionych kilka zarzutów związanych z ogólnie pojętym &#8220;usability&#8221; - między innymi odnosiły [...]]]></description>
			<content:encoded><![CDATA[<p>Aby urozmaicić look &amp; feel strony coraz częściej wykorzystuje się możliwości jakie daje nam JavaScript &amp; Ajax&#8230; i bez wątpienia nie należy się tego wstydzić. Jest jednak jedno ale&#8230;Mianowicie często zapominamy o ważnej rzeczy  jak użyteczność tych nowych &#8220;bajerów&#8221;. Pod adresem Ajax&#8217;a zostało przedstawionych kilka zarzutów związanych z ogólnie pojętym &#8220;usability&#8221; - między innymi odnosiły się one do problemów z przyciskiem Back przeglądarki (takie same zarzuty były wysuwane w kierunku iframe). Jednak nie chciałem mówić o tych utartych i znanych wszystkim problemach.</p>
<p><span id="more-105"></span></p>
<p>W tym przypadku chciałem przedstawić konkretny przykład problemu użyteczności. Wyobraźmy sobie sytuacje, w której mamy główne menu w postaci (standardowe menu w panelach administracyjnych):<br />
<img src="http://webprogramming.pl/blog/usability-menu-w-panelu.jpg" alt="Ustability/javascript w panelach administratorskich" width="473" height="139" /></p>
<p>Projektanci zażyczyli sobie, aby obsługa tych zakładek była realizowana za pomocą Ajax (co zwiększa użyteczność panelu - strona będzie się szybciej ładowała), a programiści &#8220;na szybko&#8221; zrealizują to w taki oto sposób:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&lt;a onclick=&quot;loadPage(&#8217;adresy_strony.html&#8217;)&quot; href=&quot;#&quot;&gt;&lt;/a&gt;</div>
</li>
</ol>
</div>
<p>Innym słowy za pomocą JavaScript przechwytują kliknięcie na link i obsługują żądanie za pomocą JavaScript/Ajax. Wszytko ładnie wygląda.. dopóki użytkownik nie będzie chciał takiej zakładki otworzyć w nowym panelu (osobiście tak często robię) - wtedy zaczną się schody.</p>
<p>Strasznie mnie irytują strony/serwisy, które ograniczają moje standardowe (i optymalne dla mnie) zachowanie. Tym bardziej, że problem ten łatwo rozwiązać.</p>
<p>Przykładowe rozwiązanie problemu (sprawy techniczne, kod JavaScript).<br />
Dla kodu HTML w postaci:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;ul<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;li<span class="re2">&gt;</span></span></span> <span class="sc3"><span class="re1">&lt;a</span> <span class="re0">class</span>=<span class="st0">&quot;menuLink&quot;</span> <span class="re0">href</span>=<span class="st0">&quot;/adresy_strony.html&quot;</span><span class="re2">&gt;</span></span>Publikuj<span class="sc3"><span class="re1">&lt;/a<span class="re2">&gt;</span></span></span><span class="sc3"><span class="re1">&lt;/li<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/ul<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Wystarczy dodać następujący kod JavaScript, aby po kliknięciu strona załadowała się za pomocą Ajax, ale jednocześnie działała opcja &#8220;Otwórz w nowym oknie/panelu&#8221; .</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">$<span class="br0">&#40;</span>document<span class="br0">&#41;</span>.<span class="me1">ready</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;$<span class="br0">&#40;</span><span class="st0">&#8216;.menuLink&#8217;</span><span class="br0">&#41;</span>.<span class="me1">click</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; $.<span class="me1">get</span><span class="br0">&#40;</span>$<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">attr</span><span class="br0">&#40;</span><span class="st0">&#8216;href&#8217;</span><span class="br0">&#41;</span>, <span class="kw2">function</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$<span class="br0">&#40;</span><span class="st0">&#8216;#body&#8217;</span><span class="br0">&#41;</span>.<span class="me1">html</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>Dodatkowo musimy zapewnić po stronie serwera, aby obie opcje zostały odpowiednie obsłużone. Jak widać oba żądania są wysyłane pod ten sam adres URL z tym, że w przypadku żądania Ajax oczekujemy innego wyniku  - wówczas interesuje nas tylko sama zawartość strony (bez menu, nagłówków, stopek, itp).</p>
<p>Typ żądania można poznać za pomocą dodatkowego nagłówka jakie wysyła biblioteka jQuery (biblioteka Prototype też takowy wysyła) - wystarczy sprawdzić, czy istnieje nagłówek &#8216;X_REQUESTED_WITH&#8217; i czy posiada wartość &#8216;XMLHttpRequest&#8217; (w przypadku Zend Framework mamy dostępna metodę &#8216;isXmlHttpRequest&#8217; klasy &#8216;Zend_Controller_Request_Http&#8217;, która robi to za nas). Jeżeli żądanie jest wysłane za pomocą Ajax to wygeneruj tylko treść dla wybranej akcji, w przeciwnym przypadku wygeneruj cała stronę (opakowaną w odpowiedni układ).</p>
<p>Jak widać obsługa nie sprawia większych problemów, a zyskuje się na użyteczności.</p>
]]></content:encoded>
			<wfw:commentRss>http://webprogramming.pl/2009/usability-javascript-zabawy-javascriptowo-ajaxowe/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

