<?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>BBProject.net &#187; wskaźnik</title>
	<atom:link href="http://www.bbproject.net/tag/wskaznik/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bbproject.net</link>
	<description>Programowanie, webmastering, informatyka</description>
	<lastBuildDate>Mon, 26 Jul 2010 08:03:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Referencja w pętli foreach &#8211; bug który nie jest bugiem</title>
		<link>http://www.bbproject.net/2010/02/referencja-w-petli-foreach-bug-ktory-nie-jest-bugiem/</link>
		<comments>http://www.bbproject.net/2010/02/referencja-w-petli-foreach-bug-ktory-nie-jest-bugiem/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 11:30:44 +0000</pubDate>
		<dc:creator>M@ster</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[foreach]]></category>
		<category><![CDATA[pętla]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[referencja]]></category>
		<category><![CDATA[wskaźnik]]></category>

		<guid isPermaLink="false">http://www.bbproject.net/?p=133</guid>
		<description><![CDATA[Weźmy pod lupę prostą pętle foreach w PHP, która zamienia we wszystkich elementach tablicy litery na duże: $words = array('system', 'baza', 'telefon'); foreach ($words as &#38;$item) { $item = strtoupper($item); } Jak widać, kolejne elementy tablicy pobierane są po przez referencję, tj. tworzony jest wskaźnik na konkretny element a nie jego kopia w pamięci. Dlatego [...]]]></description>
			<content:encoded><![CDATA[<p>Weźmy pod lupę prostą pętle <a href="http://pl.php.net/manual/en/control-structures.foreach.php"><em>foreach</em></a> w PHP, która zamienia we wszystkich elementach tablicy litery na duże:</p>
<pre class="brush: php">$words = array('system', 'baza', 'telefon');
foreach ($words as &amp;$item)
{
  $item = strtoupper($item);
}</pre>
<p>Jak widać, kolejne elementy tablicy pobierane są po przez referencję, tj. tworzony jest wskaźnik na konkretny element a nie jego kopia w pamięci. Dlatego też, zmieniając w pętli zawartość zmiennej <em>$item</em> modyfikujemy pierwotną tablicę. W czym zatem tkwi problem?</p>
<p><span id="more-133"></span>Po wykonaniu powyższego kodu tablica <em>$words</em> wygląda następująco (<em>var_dump($words)</em>):</p>
<pre class="brush: plain">array(3) {
  [0]=&gt;
  string(4) "SYSTEM"
  [1]=&gt;
  string(4) "BAZA"
  [2]=&gt;
  &amp;string(6) "TELEFON"
}</pre>
<p>Wszystko wygląda na pierwszy rzut oka tak jak oczekiwaliśmy. Spróbujmy zatem wyświetlić teraz wszystkie elementy:</p>
<pre class="brush: php">foreach ($words as $item)
{
  echo $item.' ';
}</pre>
<p>&#8230;w rezultacie otrzymujemy:</p>
<pre class="brush: plain">SYSTEM BAZA BAZA</pre>
<p>Zdziwieni? Dzieje się tak dlatego, iż po pierwszej pętli zmienna <em>$item</em>, która jest wskaźnikiem, wciąż wskazuje na ost. element tablicy. W kolejnym przejściu, mimo iż nie użyliśmy już referencji, to zmienna <em>$item</em> wciąż jest typu wskaźnikowego i następuje wówczas wyciągnięcie aktualnego elementu w pętli <em>foreach</em> i przechowywanie go w ost. komórce tablicy którą analizujemy (zamiast w osobnej zmiennej). Z tej przyczyny, w końcowym kroku, ost. komórka zawiera wartość z kroku poprzedniego &#8211; stąd powtórzone słowo „BAZA”. Oryginalna tablica <em>$words</em> również posiada zmodyfikowaną wartość, co nie powinno mieć miejsca.</p>
<p>Aby uniknąć takich sytuacji możemy zastosować kilka rozwiązań. Pierwsze i chyba najlepsze, zwalniać zmienną iteracyjną po skończonej pętli jeśli używaliśmy referencji:</p>
<pre class="brush: php">$words = array('system', 'baza', 'telefon');
foreach ($words as &amp;$item)
{
  $item = strtoupper($item);
}
unset($item);</pre>
<p>Drugie wyjście, użyć innej zmiennej (o innej nazwie) w ew. kolejnej pętli <img src='http://www.bbproject.net/wp-includes/images/smilies/icon_wink.png' alt=';)' class='wp-smiley' /> . I na koniec, rozwiązanie na siłę:</p>
<pre class="brush: php">$words = array('system', 'baza', 'telefon');
foreach ($words as $key =&gt; $item)
{
  $words[$key] = strtoupper($item);
}</pre>
<p>&#8230;aczkolwiek jeśli używamy referencji to z reguły z powodu z którego nie możemy użyć w/w konstrukcji.</p>
<p>To zachowanie, mimo iż poprawne z punktu widzenia języka PHP, jest częstą przyczyną zgryzów u osób które nie zetknęły się nigdy z tym problemem. Często też jest to uważane za <a href="http://bugs.php.net/bug.php?id=29992">błąd</a> samego parsera, który de facto nim nie jest.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bbproject.net/2010/02/referencja-w-petli-foreach-bug-ktory-nie-jest-bugiem/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
