<?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>Rob Rosenbaum's Development Blog &#187; PHP</title>
	<atom:link href="http://robrosenbaum.com/tags/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://robrosenbaum.com</link>
	<description>PHP, Symfony, and Other Web Things</description>
	<lastBuildDate>Wed, 30 Jan 2008 02:38:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>HOWTO: Disable Session Timeout in Symfony</title>
		<link>http://robrosenbaum.com/php/howto-disable-session-timeout-in-symfony/</link>
		<comments>http://robrosenbaum.com/php/howto-disable-session-timeout-in-symfony/#comments</comments>
		<pubDate>Wed, 16 Jan 2008 20:10:07 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/php/howto-disable-session-timeout-in-symfony/</guid>
		<description><![CDATA[The problem: make symfony use PHP's default session behavior. Symfony session handling is based on timed sessions - you set a time after which the session will expire - but the default PHP behavior is to expire when the user closes the browser window. This is also the most commonly desired behavior for sessions. The [...]]]></description>
			<content:encoded><![CDATA[<p>The problem: make symfony use PHP's default session behavior. Symfony session handling is based on timed sessions - you set a time after which the session will expire - but the default PHP behavior is to expire when the user closes the browser window. This is also the most commonly desired behavior for sessions. The drawback of using a timed session is that it could expire while the user is still on the site. This is an issue in <a href="http://www.lecturetools.org/">LectureTools</a>, because students may sit for an hour or more without loading a new page, and they may even have logged in before class. You can solve this little problem easily if you are using symfony 1.1 (currently in beta). Just set the timeout to <code>false</code> in settings.yml:</p>
<pre class="YAML">
all:
  .settings:
    timeout:    false
</pre>

But if you are using the stable 1.0 branch of symfony, this will do just the opposite - it will make your sessions time out immediately! To make this work, we have to override <code>sfBasicSecurityUser</code>'s <code>initialize()</code> method. I will describe two ways to do this; one is a short hack, the other is longer and somewhat more proper.
<p class="leadingnoindent">Here's the short way:</p>
<pre class="PHP">
class myUser extends sfBasicSecurityUser
{
  public function initialize($context, $parameters = null)
  {
    if (sfConfig::get('sf_timeout') == 0) {
      // session will expire if window is open for a day
      sfConfig::set('sf_timeout', 86400);
    }

    return parent::initialize($context, $parameters);
  }
}
</pre>
This works because the <code>sf_timeout</code> setting is not used by any other class (at the moment), so changing it doesn't have any side effects. If you set your timeout to 0 or false, symfony will always think you have set the session timeout to 24 hours, but the session will actually expire when the user closes the browser window.
If you are not comfortable with "hacks" like the above, you could copy <code>the initialize()</code> method from <code>sfBasicSecurityUser</code>, change it in the appropriate place, and skip calling the parent constructor altogether. Unfortunately, <code>sfBasicSecurityUser</code> calls <em>its</em> parent constructor, so you have to rewrite them both:
<pre class="php">
class myUser extends sfBasicSecurityUser
{
  public function initialize($context, $parameters = null)
  {
    $this->context = $context;

    $this->parameterHolder = new sfParameterHolder();
    $this->parameterHolder->add($parameters);

    $this->attributeHolder = new sfParameterHolder(self::ATTRIBUTE_NAMESPACE);

    // read attributes from storage
    $attributes = $context->getStorage()->read(self::ATTRIBUTE_NAMESPACE);
    if (is_array($attributes))
    {
      foreach ($attributes as $namespace => $values)
      {
        $this->attributeHolder->add($values, $namespace);
      }
    }

    // set the user culture to sf_culture parameter if present in the request
    // otherwise
    //  - use the culture defined in the user session
    //  - use the default culture set in i18n.yml
    if (!($culture = $context->getRequest()->getParameter('sf_culture')))
    {
      if (null === ($culture = $context->getStorage()->read(self::CULTURE_NAMESPACE)))
      {
        $culture = sfConfig::get('sf_i18n_default_culture', 'en');
      }
    }

    $this->setCulture($culture);

    // read data from storage
    $storage = $this->getContext()->getStorage();

    $this->authenticated = $storage->read(self::AUTH_NAMESPACE);
    $this->credentials   = $storage->read(self::CREDENTIAL_NAMESPACE);
    $this->lastRequest   = $storage->read(self::LAST_REQUEST_NAMESPACE);

    if ($this->authenticated == null)
    {
      $this->authenticated = false;
      $this->credentials   = array();
    }
    else
    {
      // Automatic logout logged in user if no request within [sf_timeout] setting
      if (0 != sfConfig::get('sf_timeout') &#038;& null !== $this->lastRequest &#038;& (time() - $this->lastRequest) > sfConfig::get('sf_timeout'))
      {
        if (sfConfig::get('sf_logging_enabled'))
        {
          $this->getContext()->getLogger()->info('{sfUser} automatic user logout due to timeout');
        }
        $this->setTimedOut();
        $this->setAuthenticated(false);
      }
    }

    $this->lastRequest = time();

  }
}
</pre>

That should do it!]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/howto-disable-session-timeout-in-symfony/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>sfModelTestPlugin &#8211; Simple unit tests for any ORM!</title>
		<link>http://robrosenbaum.com/php/sfmodeltestplugin-simple-unit-tests-for-any-orm/</link>
		<comments>http://robrosenbaum.com/php/sfmodeltestplugin-simple-unit-tests-for-any-orm/#comments</comments>
		<pubDate>Wed, 14 Nov 2007 19:02:31 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/uncategorized/sfmodeltestplugin-simple-unit-tests-for-any-orm/</guid>
		<description><![CDATA[Easy unit testing with model objects and a test database with sfModelTest plugin. Propel, Doctrine, and Propel 1.3 are supported.]]></description>
			<content:encoded><![CDATA[<p>I have redone the <a href="http://trac.symfony-project.com/wiki/sfPropelTestPlugin">sfPropelTestPlugin</a>, and it is now <a href="http://trac.symfony-project.com/wiki/sfModelTestPlugin">sfModelTestPlugin</a>, with support for Doctrine and Propel 1.3! Also new - you can now specify the test data file/directory at runtime, allowing for more flexibility with your tests. I want to thank Anders Betnér and my readers for bug reports and patches!</p>]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/sfmodeltestplugin-simple-unit-tests-for-any-orm/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>New symfony plugin &#8211; sfPropelTestPlugin simplifies unit tests</title>
		<link>http://robrosenbaum.com/php/new-symfony-plugin-sfpropeltestplugin-simplifies-unit-tests/</link>
		<comments>http://robrosenbaum.com/php/new-symfony-plugin-sfpropeltestplugin-simplifies-unit-tests/#comments</comments>
		<pubDate>Thu, 13 Sep 2007 12:59:47 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/symfony/new-symfony-plugin-sfpropeltestplugin-simplifies-unit-tests/</guid>
		<description><![CDATA[Easy unit testing with Propel objects and a test database with sfPropelTestPlugin.]]></description>
			<content:encoded><![CDATA[<p>If you've ever tried to write a symfony unit test for a model class - or for any piece of code that interacts with the database - then you know what a headache it can be. <a href="http://trac.symfony-project.com/trac/wiki/sfPropelTestPlugin">sfPropelTestPlugin</a> to the rescue! This plugin loads all the necessary symfony components for database interaction, and goes a step further: test data is automatically reloaded to the test database at the beginning of each test case, so you don't have to worry about your tests interacting with each other. Here's an example of a unit test written with <a href="http://trac.symfony-project.com/trac/wiki/sfPropelTestPlugin">sfPropelTestPlugin</a>:</p>
<pre class="php">
class myUnitTest extends sfPropelTest
{
  public function setup()
  {
    $this->bob = UserPeer::retrieveByPK('bob');
  }

  public function teardown()
  {
    $this->diag('Test method complete!');
  }

  public function test_user()
  {
    $this->is($this->bob->getId(), 'bob', 'Bob exists!');

    $user = new User();
    $user->setFirstName('Joe');
    $user->setLastName('Smith');
    $user->setUsername('joe');
    $user->save();

    $joe = UserPeer::getBy(UserPeer::USERNAME, 'joe');
    $this->isa_ok($joe, 'User', 'Joe exists!');
  }

  public function test_dataDelete()
  {
    $this->is($this->bob->getId(), 'bob', 'Bob still exists!');

    $joe = UserPeer::getBy(UserPeer::USERNAME, 'joe');
    $this->ok(!$joe, 'Joe no longer exists.');
  }
}

$test = new myUnitTest();
$test->execute();
</pre>

<p class="leadingnoindent">If you've written tests in Ruby on Rails, the above should look familiar. If not, let's go through the code:</p>
<p>The first two lines are setup: The first line tells symfony what application to test - in this case, "myApp" - and the second line includes the code we need to test against the database. Next we define our "test case" - a class that extends <code class="php">sfPropelTest</code>, which is itself a child of <code class="php">lime_test</code>. Every method that begins with "test_" will be called in turn, with our test data being reloaded between each call. Also, the <code class="php">setup()</code> method, if defined, will be called immediately before each test method, and the <code class="php">teardown()</code> method, if defined, will be called immediately after. The last two lines create a new instance of our test suite, and call its <code class="php">execute()</code> method, which runs our tests.</p>
<p>There you have it - a quick and painless way to run unit tests in symfony. One less excuse for not writing them!</p>]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/new-symfony-plugin-sfpropeltestplugin-simplifies-unit-tests/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Improved Plugin for Model Validation: sfPropelValidatePlugin</title>
		<link>http://robrosenbaum.com/php/improved-plugin-for-model-validation-sfpropelvalidateplugin/</link>
		<comments>http://robrosenbaum.com/php/improved-plugin-for-model-validation-sfpropelvalidateplugin/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 01:08:37 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/symfony/improved-plugin-for-model-validation-sfpropelvalidateplugin/</guid>
		<description><![CDATA[Put your Symfony validation in the model, where it belongs, with sfPropelValidate plugin. New version is more efficient.]]></description>
			<content:encoded><![CDATA[<p>I have updated my plugin for doing <a href="http://trac.symfony-project.com/trac/wiki/sfPropelValidatePlugin">model-based validation in symfony</a>. The new plugin uses the Propel builders instead of behaviors, so it is now called <a href="http://trac.symfony-project.com/trac/wiki/sfPropelValidatePlugin">sfPropelValidatePlugin</a> instead of the former (unwieldy) name sfPropelValidateBehaviorPlugin. If you have not investigated the Propel builder classes, I suggest you give them a look. By overriding the default classes used to build your Propel object and peer classes, you can write your modifications directly into your model's base classes. This is a much cleaner and more readable solution than using Propel behaviors, and you avoid the performance hit that behaviors incur. </p>
<p>The default Propel builders can be found in the symfony source in these places:</p>
<pre class="filesystem">
symfony/addon/propel/builder/sfObjectBuilder.php
symfony/addon/propel/builder/sfPeerBuilder.php
</pre>
<p class="leadingnoindent">The classes these inherit from are buried. They can be found here:</p>
<pre class="filesystem">
symfony/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5ComplexObjectBuilder.php
symfony/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5ComplexPeerBuilder.php
</pre>
]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/improved-plugin-for-model-validation-sfpropelvalidateplugin/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Using Flash Upload with PHP &amp; symfony</title>
		<link>http://robrosenbaum.com/php/using-flash-upload-with-php-symfony/</link>
		<comments>http://robrosenbaum.com/php/using-flash-upload-with-php-symfony/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 22:50:09 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[Flash]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/flash/using-flash-upload-with-php-symfony/</guid>
		<description><![CDATA[Using Flash-based multi-file uploads with session cookies.]]></description>
			<content:encoded><![CDATA[<p>Through Flash's <a href="http://livedocs.adobe.com/flex/201/langref/flash/net/FileReference.html"><code class="ActionScript">FileReference</code></a> and <a href="http://livedocs.adobe.com/flex/201/langref/flash/net/FileReferenceList.html"><code class="ActionScript">FileReferenceList</code></a> classes, you  can create a powerful file uploader that allows the user to upload multiple files with a single form element. But beware: unless the user happens to be using IE, the <code class="ActionScript">upload</code> will use a new browser session to upload the files. This means that if you require that a user be authenticated before uploading something (and you better be), the upload won't work - the request will be forwarded to the login form, or to wherever your system forwards unauthorized requests. This is a maddening bug to track down, and there is nothing you can do to make Flash use the right session. The work around is to send the session cookie in the url and, on the server side, use that to override the new (and wrong) session cookie sent by Flash. Here's how that works in symfony, although much of the following is useful for other languages or frameworks:</p>
<p>First, we have to tell our Flash component what the cookie is, so it can roll it into the URL. One solution would be to pass the session cookie as an argument in <a href="http://www.permadi.com/tutorial/flashVars/">FlashVars</a>, but then the user's session cookie is sitting unencrypted in the HTML, leaving them vulnerable to <a href="http://shiflett.org/articles/cross-site-request-forgeries">cross-site request forgery</a>. Better to use javascript to fetch the cookie, and <em>then</em> put it in FlashVars. If you are using <a href="http://www.bobbyvandersluis.com/ufo/">ufo.js</a>, the first argument to <code class="javascript">UFO.create()</code> should look like this:</p>
<pre class="javascript">
{
  movie: '/flash/uploader.swf', 
  id: 'uploader',
  name: 'uploader',

  flashvars: 'cookie=' + document.cookie,

  // other options ...
}
</pre>
<p>Note that if you are dealing with multilple cookies, you will want to parse the output of <code class="javascript">document.cookie</code> and send only the desired cookie.</p>
<p class="leadingnoindent">Next, add the cookie to the URL in your ActionScript (this is for ActionScript 2.0):</p>
<pre class="ActionScript2">
var list:Array = myFileRefList.fileList;
var item:FileReference;
var url:String = _root.uploadURL + '?cookie=' + _root.cookie;

for (var i:Number = 0; i < list.length; i++) {
  item.upload (url);
}
</pre>
<p class="leadingnoindent">That does it for the client side. Now, we need to tell PHP to use our cookie instead of the one the browser sent. This does the trick:</p>
<pre class="PHP">
list($cookieName, $cookieValue) = str_split('=', $_GET['cookie']);

session_name($cookieName);
session_id($cookieValue);

session_start();
</pre>
<p>If you are using symfony, things are a little more complex. We need to call <code class="PHP">session_name()</code> and <code class="PHP">session_id()</code> <em>before</em> <code class="PHP">session_start()</code>; looking at the symfony source code, we find that <code class="PHP">session_start()</code> is called in <code class="PHP">sfSessionStorage::initialize()</code>. So a simple solution is to extend the sfSessionStorage class:</p>
<pre class="PHP">
class mySessionStorage extends sfSessionStorage
{
  public function initialize($context, $parameters = null)
  {
    if ( /* whatever the condition is when we want to do this */ ) {
      if ($cookie = $context->getRequest()->getParameter('cookie')) {
        $name = 'symfony';
        preg_match('/^' . $name.'=(.*)$/', $cookie, $asMatch);
        $value = $asMatch[1];

        session_name($name);
        session_id($value);
      }
    }

    parent::initialize($context, $parameters);
  }
}
</pre>
<p class="leadingnoindent">Finally, tell symfony to use the mySessionStorage class by editting factories.yml:</p>
<pre class="YAML">
all:
  storage:
    class: mySessionStorage
    param:
      session_name: symfony
</pre>
<p class="leadingnoindent">And you're done! Clear your cache, and try it out. An easy way to check if it's working is to add the following line to the end of index.php (or frontend.php):</p>
<pre class="PHP">file_put_contents('testSessionOverwrite.txt', sfContext::getInstance()->getRequest()->getActionName());</pre>
<p>Now try uploading a file. If the action name in testSessionOverwrite.txt is the action you're uploading to, you're golden. If instead it is the name of the action that authenticates users, you have a problem somewhere, and you get to have the enjoyable experience of debugging PHP without browser output. Remember to erase the debugging line from your front controller when you get everything working.</p>
<p>Next time, just make the users upload their damn files one-at-a-time...</p>
]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/using-flash-upload-with-php-symfony/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Comparing Strings in PHP &#8211; Mysteries of PHP, Part 2</title>
		<link>http://robrosenbaum.com/php/comparing-strings-in-php-mysteries-of-php-part-2/</link>
		<comments>http://robrosenbaum.com/php/comparing-strings-in-php-mysteries-of-php-part-2/#comments</comments>
		<pubDate>Wed, 04 Jul 2007 00:16:29 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/php/comparing-strings-in-php-mysteries-of-php-part-2/</guid>
		<description><![CDATA[Always use the identity operator, "===", to compare strings. "==" can get you into trouble.]]></description>
			<content:encoded><![CDATA[<p>Don't use the equality operator (<code class="php">==</code>) to compare strings - use the <code class="php">strcmp()</code> function, or the identity operator (<code class="php">===</code>). In fact, when comparing values in PHP, use the identity operator (<code class="php">===</code>) instead of the equality operator whenever possible. You may have heard that <code class="php">===</code> is faster, since it incurs no type conversions, but some people have argued that it hurts code clarity. According to this theory, you should only use the identity operator when you actually need the two variables to have the same type, as when checking <code class="php">strpos()</code> for the return value "<code class="php">false</code>". But the fact is that the identity operator is not only faster, it is also <em>clearer</em>. The identity operator says, "These two pieces of data are identical," whereas the equality operator says, "These two pieces of data, <em>or anything under the sun they could possibly be converted to</em>, are equal." Which seems like clearer code to you?
</p>
<p>
If you doubt the importance of this distinction - and I understand why you might - check out the following, rather shocking examples taken from the PHP manual:
<pre class="php">
if (            0 == 'my string'
  &#038;&            1 != 'my string'
  &#038;&       '+010' == '10.0'
  &#038;&   '  131e-2' == '001.3100' 
  &#038;& '000e002073' == '0e459239'
  &#038;&       '0xab' == 0253 
  &#038;&       '0xab' != '0253' 
  &#038;&       '0xab' == '171'
){
  echo 'WTF????';
}
</pre>
If you run the above code, you will see that all the above examples do indeed evaluate to <code class=php>true</code>. How can that be? It's because PHP checks every possible conversion of each argument, so it actually tries converting <em>both</em> strings to floats, and if those floats are equal, returns true. Those little e's are exponent markers, the x's indicate hexadecimal values, and a leading 0 marks an octal (unless it's in a string, apparently). As for why the numeral zero is equal to <strong>any</strong> string ... it beats the hell out of me.</p>
<p>In light of these facts, a developer should only ever use <code class="php">==</code> when type-conversion is <em>expected</em>, such as when comparing a form input to a numerical value. Furthermore, we should regard <code class="php">==</code> as expressing this expectation, since, by using the comparison operator, the developer has forced us to check for conversions. Thus, to keep your code clean and self-documenting, stop using <code class="php">==</code>. Use <code class="php">strcmp()</code> for strings; it's binary-safe, and expresses the type of your arguments without the need for comments. Use <code class="php">===</code> for everything else.</p>]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/comparing-strings-in-php-mysteries-of-php-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DOMNodeList Gotchas</title>
		<link>http://robrosenbaum.com/php/domnodelist-gotchas/</link>
		<comments>http://robrosenbaum.com/php/domnodelist-gotchas/#comments</comments>
		<pubDate>Wed, 13 Jun 2007 18:05:16 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/xml/domnodelist-gotchas/</guid>
		<description><![CDATA[Be wary - DomNodeLists behave strangely in loops the alter them.]]></description>
			<content:encoded><![CDATA[<h3>An Undocumented &#034;Feature&#034;</h3>
<p>Suppose we write the following code, whose simple purpose is to go through an XML document and replace every &#034;foo&#034; element with an empty &#034;bar&#034; element: 
<pre>
$dom = DOMDocument::loadXML('
  &lt;root&gt;
  &lt;foo&gt;This&lt;/foo&gt;
  &lt;foo /&gt;
  &lt;foo /&gt;
  &lt;/root&gt;'
);

$document = $dom-&gt;documentElement;
$foos = $document-&gt;getElementsByTagName('foo');

for ($i = 0; $i &lt; $foos-&gt;length; $i++) {
  $bar = $dom-&gt;createElement('bar');
  $document-&gt;replaceChild($bar, $foos-&gt;item($i));
}
</pre>
We are quite surprised when the script outputs:<pre class="xml">
&lt;root&gt;&lt;bar/&gt;&lt;foo/&gt;&lt;bar/&gt;&lt;/root&gt;
</pre>
Why did it skip the middle element? Because the DOMNodeList class has an undocumented &#034;feature&#034;: when the owner document of a DOMNodeList object is changed, the object is <strong>recreated</strong>. That means that, when we replace the first &#034;foo&#034; node, the second &#034;foo&#034; node <em>becomes</em> the new first node. Also, the length of the node list is now 2, not 3. But since $i has been incremented, the for loop misses the second node entirely, operates on the third, then exits normally.</p>
<p>The solution to this problem is to save a reference to each node in an array, then loop over the array:
<pre class="php">
for ($i = 0; $i &lt; $foos-&gt;length; $i++) {
  $nodes[$i] = $foos-&gt;item($i);
}

for ($i = 0; $i &lt; count($nodes); $i++) {
  $bar = $dom-&gt;createElement('bar');
  $document-&gt;replaceChild($bar, $nodes[$i]);
}
</pre>
This code outputs what we intuitively expected from the original code:
<pre class="xml">
&lt;root&gt;&lt;bar/&gt;&lt;bar/&gt;&lt;bar/&gt;&lt;/root&gt;
</pre></p>

<h3>Implementation: A DOMNodeIterator Class</h3>
<p>It&#039;s best to encapsulate this technique in a class. Here&#039;s a simple class that does the job:

<pre class="php">
class DOMNodeIterator implements Iterator
{
  protected $nodes;

  public function __construct(DOMNodeList $nodeList)
  {
    if ($nodeList-&gt;item(0)) {
      for ($i = 0; $i &lt; $nodeList-&gt;length; $i++) {
        $this-&gt;nodes[$i] = $nodeList-&gt;item($i);
      }
    }
  }

  public function current()
  {
    return current($this-&gt;nodes);
  }
    
  public function key()
  {
    return key($this-&gt;nodes);
  }

  public function next()
  {
    return  next($this-&gt;nodes);
  }

  public function rewind()
  {
    reset($this-&gt;nodes);
  }

  public function valid()
  {
    return $this-&gt;current() ? true : false;
  }
}
</pre></p>

<h3>On the Other Hand, Orphan Nodes</h3>
<p>Our iterator has one drawback: if we remove a node in the list via removeChild(), it will still exist in the iterator, but it will no longer be associated with our document. Unfortunately, the only way to check for this is to ascend the entire DOM tree each time we want to access a node, to make sure it is still a descendant of the root node. Rather than incur that overhead, we&#039;ll leave it to the devloper to use the iterator with care. We can safeguard the above code by putting the call to replaceChild() inside a try block:
  
<pre class="php">
try {
  $document-&gt;replaceChild($bar, $foo);
} catch (DOMException $e) {
  if ($e-&gt;getMessage() !== 'Not Found Error') {
    throw $e;
  }
}
</pre></p>

<h3>An Issue with PHP, or with DOM?</h3>
<p>Stay tuned for my next blog entitled &#034;Why the DOM Sucks.&#034; Till next time&#8230;</p> 
]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/domnodelist-gotchas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Use Ruby-style tags in PHP</title>
		<link>http://robrosenbaum.com/php/use-ruby-style-tags-in-php/</link>
		<comments>http://robrosenbaum.com/php/use-ruby-style-tags-in-php/#comments</comments>
		<pubDate>Tue, 05 Jun 2007 05:09:10 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/?p=6</guid>
		<description><![CDATA[Make PHP code more concise without the pesky XML syntax conflict.]]></description>
			<content:encoded><![CDATA[<p>One undeniable advantage of Ruby on Rails is its terse template syntax. The cumbersome</p>
<p class="leadingnoindent"><pre class="php">&lt;?php echo $something ?&gt;</pre></p>
<p class="leadingnoindent">is replaced by the elegant and readable</p>
<p class="leadingnoindent"><pre class="ruby">&lt;%= something %&gt;</pre></p>
<p class="leadingnoindent">The very good news is that you can use these same tags in PHP! Just add the following to your htaccess:</p>
<p class="leadingnoindent"><pre class="htaccess">php_flag asp_tags on</pre></p>
<p class="leadingnoindent">Voila! Readable templates. What&#039;s curious is that no one seems to use this option. Perhaps it is because they are referred to as &#034;ASP-style tags.&#034; (Can we just call them &#034;Ruby-style tags&#034;, instead?) On all my sites, I use the long <?php ?> tags for blocks of code, and the short <%= %> tags for any PHP code floating in the HTML sea. In symfony, that means the template files use one tag-style, and the rest of the code uses the other. I encourage everyone &#8211; yes, everyone &#8211; to start using Ruby-style tags in their templates. The more people use it, the more common it will be to have the &#034;asp_tags&#034; option on by default, so people on shared servers can join in the readable fun.</p>
<p>It&#039;s important for a second reason &#8211; arbitrary conventions should be standardized. That is, any time we are faced with a set of possibilities that are all of equal value &#8211; such as what weird punctuation our programming language should use to demarcate itself &#8211; we should pick one standard way and stick with it. That way we reduce the learning curve of <em>all</em> languages (or whatever the things the convention pertains to). Imagine if there were one, universal syntax for putting server-side code into HTML. Imagine if there were a templating language that every designer knew &#8211; because it&#039;s so simple &#8211; and that every server-side language supported. It would not be a universal programming language, since we should not be using the full power of a programming language from inside our templates; that&#039;s what the controller code is for. This universal templating language (What the hell, let&#039;s go ahead and call it UTL, because giving initials to computer-denizens makes them seem like real people) should support the following things, and probably nothing else:
<ol>
	<li>Variables, including objects and arrays</li>
	<li>if/else</li>
	<li>while</li>
	<li>foreach</li>
	<li>Very basic arithmetic and string operators</li>
	<li><strong>No</strong> function or method calls</li>
</ol>
That last one may raise some eyebrows. Why would we <em>not</em> include functions and methods? Because we can call all those funcitons in the controller, and assign their return values to variables, which we then use in the template per number 1 above. Also, allowing function calls brings the capacity for arbitrarily complex logic into UTL, as well as coupling it more tightly with the mother language, both of which defeat the purpose of UTL.</p>
<p>Make the dream a reality. Start by using Ruby tags.</p>]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/use-ruby-style-tags-in-php/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Mysteries of PHP, Part 1</title>
		<link>http://robrosenbaum.com/php/mysteries-of-php-part-1/</link>
		<comments>http://robrosenbaum.com/php/mysteries-of-php-part-1/#comments</comments>
		<pubDate>Sun, 03 Jun 2007 16:02:59 +0000</pubDate>
		<dc:creator>Rob Rosenbaum</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://robrosenbaum.com/?p=3</guid>
		<description><![CDATA[A class should be allowed to implement overlapping interfaces.]]></description>
			<content:encoded><![CDATA[<p>The PHP manual tells us that, though a class may implement more than one interface, "A class cannot implement two interfaces that share function names, since it would cause ambiguity." Makes perfect sense - until, that is, you realize that PHP interfaces contain no code. They're nothing but definitions. Therefore, there is nothing to be ambiguous.</p>
<p>Interfaces have a single purpose: by using them, functions and methods can require their arguments to implement a certain set of methods. (Actually, they merely require that methods matching certain <em>definitions</em> exist.) Suppose we are writing a graphics library, and we have a set of functions for manipulating and drawing objects that have a color. In that case, we may want to have an interface like the following:</p>
<pre>
interface DrawableInColor 
{ 
  public function getColor(); 
  public function setColor($color); 
  public function draw($x, $y); 
}</pre>
<p class="leadingnoindent">But suppose we also want to deal with objects that can be resized. Then we may want an interface like this:</p>
<pre>
interface DrawableAndResizable 
{ 
  public function scaleX($x_factor); 
  public function scaleY($y_factor); 
  public function draw($x, $y); 
}</pre>
<p>So what if we have a classof objects that are colored <em>and</em> resizable? So long as we give the class's methods the appropriate names, the class will be an implementation of both the above interfaces. There is no ambiguity, since there is only one method named "draw." In fact, no class can have two functions by the same name, so there can <em>never</em> be ambiguity in declaring that a class implements two overlapping interfaces. But we can't declare it! To use our class with both sets of functions, we would need to remove the functions' interface requirements entirely. The only other solution is to rename the draw() function of one of the interfaces (to draw2(), let's say) and add a dummy function to our class, like this:</p>
<pre>
public function draw2($x, $y) 
{ 
  $this-&gt;draw($x, $y); 
}</pre>
<p class="leadingnoindent">Both "solutions" are terribly ugly, and although the core developers of PHP insist that it is not an object-oriented language, it should at least allow the OO features of the language to be used as such. The restriction on interfaces severely limits their utility in PHP, and the development team should really consider removing it in future releases.</p>]]></content:encoded>
			<wfw:commentRss>http://robrosenbaum.com/php/mysteries-of-php-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
