<?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>Jeremy Cook &#187; PDO</title>
	<atom:link href="http://jeremycook.ca/tag/pdo/feed/" rel="self" type="application/rss+xml" />
	<link>http://jeremycook.ca</link>
	<description>Random musings on web development and PHP</description>
	<lastBuildDate>Mon, 30 Jan 2012 02:31:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Some More PDO Weirdness</title>
		<link>http://jeremycook.ca/2010/11/22/some-more-pdo-weirdness/</link>
		<comments>http://jeremycook.ca/2010/11/22/some-more-pdo-weirdness/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 01:26:54 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PDO]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=187</guid>
		<description><![CDATA[I&#8217;ve said before that I&#8217;m a great fan of PDO and use it wherever possible. That said there are some annoying quirks in it, one of which I encountered today. I&#8217;ll outline what I was trying to do, what I expected to happen and what actually happened. I&#8217;m also curious as to what anyone else [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve said before that I&#8217;m a great fan of PDO and use it wherever possible. That said there are some annoying quirks in it, one of which I encountered today. I&#8217;ll outline what I was trying to do, what I expected to happen and what actually happened. I&#8217;m also curious as to what anyone else thinks of this problem and whether it&#8217;s something worth reporting as a bug or if it&#8217;s a &#8216;feature&#8217;.</p>
<h2>What I Was Trying to Do&#8230;</h2>
<p>I&#8217;m currently adding a clearance item section to a website. This will aggregate items from over 35 stores across Canada and allow a user to search for items in a number of ways. As part of this I&#8217;ve created a business object to represent a clearance item. This mainly consists of protected properties with accessors and mutators for setting and getting the properties. Since the site is in English and French the accessors allow the properties to be formatted accordingly before being returned. I use this clearance item class when importing information into the database (items are imported from Excel worksheets, but that&#8217;s a topic for another post) and when returning results from searches. I use data mappers to handle the CRUD operations in the database. What I wanted to do was to find a quick and easy way to transform a row from a resultset into an instance of a clearance item object without using a full ORM solution. I thought I had found this with PDO.</p>
<h2>The &#8216;Solution&#8217;</h2>
<p>PDO allows you to set the fetch mode to fetch an object of a user defined class for each row returned from the database. You can either use PDOStatement::fetchObject() or PDOStatement::setFetchMode() to define this behaviour. It will take the names of the columns and assume that these are properties of the object, setting the appropriate values for these properties. In theory this sounds great but unfortunately it&#8217;s not as easy as it sounds.</p>
<h2>The Problem</h2>
<p>The problem in my case is that all properties of my object are declared as protected and I use mutators to set them. I anticipated this and provided a __set() method to provide the needed property overloading. I thought that what would happen is that PDO would attempt to set an undefined public property, triggering the __set() method where there is logic to call the appropriate mutator. Unfortunately it doesn&#8217;t work like that at all. According to comments in the PHP manual it seems that PDO uses something called reflection injection to set the properties inside the object regardless of their visibility. This meant that I was getting back an instance of my clearance item class with the protected properties set directly by PDO. This may not seem like too much of a problem, but my mutators include logic to transform the properties being set to the correct data type. For instance, columns containing integers or floating point numbers come back as strings and the mutators make sure they are set as numeric data types. Worst of all for me was the information on stores. I&#8217;m using MySQL&#8217;s GROUP_CONCAT() function to &#8216;implode&#8217; information about stores and the inventory in each into a string, meaning that I can fetch all of the information I need in a single query. The logic in the mutator then splits that string apart into an array of information on stores and the inventory. PDO was bypassing this completely and setting the protected stores property as the string that came back from GROUP_CONCAT().</p>
<h2>A Partial Solution</h2>
<p>Once again the PHP manual was my partial saviour. There is a way to fetch a row from a resultset into an existing instance of a class. In this case the visibility of properties is honoured and the __set() function is called, in turn triggering the correct mutators. The code I came up with looks like this:</p>
<pre class="brush: php; title: ; notranslate">

//The statement is prepared before this.

$item = new ClearanceItem($this-&gt;lang);
 $st-&gt;setFetchMode(PDO::FETCH_INTO, $item);
 $st-&gt;bindParam(':ItemId', $id, PDO::PARAM_INT);
 $st-&gt;execute();
 foreach ($st as $result) {
//The query in this case only returns a single row.

return $result;
 }
</pre>
<p>While this works it&#8217;s a bit of a hack to say the least. It seems that PDOStatement::fetch() doesn&#8217;t work here to fetch the info into the object, necessitating the foreach loop and the immediate return. This is fine in this case but in other areas of the code I need to iterate over a resultset, getting a new instance of ClearanceItem each time. This wouldn&#8217;t work as the information is populated into the existing object bound to the statement. The best I could do is to clone the object each time through the loop and store the cloned copy.</p>
<p>There is another way out of this: return each row as an associative array and create a factory method to return instances of ClearanceItem from this. I actually coded this solution already when I intitially found the strangeness that PDO was doing in return instances of ClearanceItem. That solution works perfectly well but it seems strange that it&#8217;s not possible to loop over a record set, getting a new instance of a class each time.</p>
<h2>Conclusion</h2>
<p>It seems that it&#8217;s quite possible to return instances of a class from a PDOStatement providing that all of the properties are public or if you don&#8217;t mind PDO directly setting your private and protected properties. If you want to use mutators to control how your data is set and to make sure it&#8217;s of the correct type it seems that the options are far more limited and you may be out of luck. Of course there are other options, such as writing a factory method to create an object from an array or using a full blown ORM like Doctrine. In this instance, as I haven&#8217;t used Doctrine before and as time is of the essence I was hoping that PDO would give me what I need.</p>
<p>It seems very strange that PDO is allowed to directly set private and protected properties when all other code accessing instances of ClearanceItem have to use the accessors and mutators. It seems to me to drive a coach and horses through the concept of property visibility. Why should PDO (at least I&#8217;m assuming it&#8217;s just PDO) have the ability to bypass the visibility protections that OO code provides while everyone else has to work with it? Is there some good reason for doing this that I&#8217;m missing? I&#8217;d be really interested to hear what the possible advantages of this are.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2010/11/22/some-more-pdo-weirdness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Quick Tip</title>
		<link>http://jeremycook.ca/2010/05/15/a-quick-tip/</link>
		<comments>http://jeremycook.ca/2010/05/15/a-quick-tip/#comments</comments>
		<pubDate>Sat, 15 May 2010 14:00:10 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[PDO]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=84</guid>
		<description><![CDATA[I haven&#8217;t written anything here for ages due to illness, work and life getting in the way. I&#8217;ve got a longer post brewing that I&#8217;ll hopefully add in the next couple of days but for now here&#8217;s a quick tip that I hope someone will find useful. I recently had a situation where I wanted [...]]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t written anything here for ages due to illness, work and life getting in the way. I&#8217;ve got a longer post brewing that I&#8217;ll hopefully add in the next couple of days but for now here&#8217;s a quick tip that I hope someone will find useful.</p>
<p>I recently had a situation where I wanted to use an array of values as bound parameters in a SQL IN clause. Easy enough to do except the array was of variable length and I didn&#8217;t know how long it would be each time the script was ran. Here&#8217;s the solution I came up with.</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php

try {

$array = array('some value', 'another', 'another');//Variable length array, unknown length before runtime

$db = new PDO(CONNSTR, USERNAME, PASS);

$sql = &quot;SELECT SomeColumn FROM table WHERE SomeOtherColumn IN (&quot; . implode(',', array_fill(0, count($array), '?')) . ') ORDER BY SomeColumn';

$st = $db-&gt;prepare($sql);

$st-&gt;execute($array);

}

catch (PDOExeception $e) {}

?&gt;
</pre>
<p>Quick and easy!</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2010/05/15/a-quick-tip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling Binary Data with PDO</title>
		<link>http://jeremycook.ca/2010/02/21/handling-binary-data-with-pdo/</link>
		<comments>http://jeremycook.ca/2010/02/21/handling-binary-data-with-pdo/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 17:27:11 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[PDO]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=64</guid>
		<description><![CDATA[This post looks at an issue with handling binary data from a database using PDO and a partial workaround for the problem.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a great fan of the <a href="http://www.php.net/pdo">PDO</a> database access library in PHP 5 and use it for all of my database work in PHP. I love its&#8217; clean, object oriented syntax and great support for prepared statements. I also like the fact that it supports most of the most common database engines. Although all of my dev work in PHP so far has been with MySQL I like the fact that if I needed to use MS SQL Server, Oracle or any of the other big RDBMS&#8217;s I could use the same PDO syntax to access them rather than learning a new database access library. However, there do seem to be some bugs in PDO  according to what I&#8217;ve read on the web. While I haven&#8217;t encountered most of them and can&#8217;t comment on them I&#8217;d like to write about one that I ran into the other day and how I worked around it.</p>
<p>I have a project that I&#8217;m working on where I&#8217;m storing some images in a database as binary data. PDO allows you to bind a file handle to a parameter in a prepared statement and when the statement is executed the contents of the file are slurped into the database. This works perfectly but the problem comes when getting the image out of the database again to display it. According to the <a href="http://www.php.net/manual/en/pdo.lobs.php">PHP manual</a> the following code should work:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db-&gt;prepare(&quot;select contenttype, imagedata from images where id=?&quot;);
$stmt-&gt;execute(array($_GET['id']));
$stmt-&gt;bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt-&gt;bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt-&gt;fetch(PDO::FETCH_BOUND);

header(&quot;Content-Type: $type&quot;);
fpassthru($lob);
?&gt;
</pre>
<p>Binding a column from a result set to a variable using PDO::PARAM_LOB is supposed to return a stream resource into the variable when PDO::fetch() is called. This stream can then be operated on using any PHP function that handles files. Unfortunately there&#8217;s a <a href="http://bugs.php.net/bug.php?id=40913">bug</a> which means that instead of returning a stream into $lob PDO returns a string containing the binary data. When this is then passed to fpassthru() an error is triggered. Fortunately there&#8217;s a simple fix for displaying the image: replace the call to fpassthru() with echo or print. Since the browser is expecting an image after the call to header() writing the binary data using echo or print has the same effect as calling fpassthru(). In my code I&#8217;ve added the following just in case this bug is fixed in a future release:</p>
<pre class="brush: php; title: ; notranslate">

if (is_string($lob)) {

echo $lob;

} else {

fpassthru($lob);

}
</pre>
<p>This neatly gets around the problem if you just want to send the binary data back to the browser to be displayed. Anything more requiring the use of any file functions or image editing functions would need quite a few contortions in the code. The information from the database would probably need to be written to a temporary file to allow it to be operated on. This bug was first reported almost three years ago in PHP 5.2.6 and it&#8217;s still not fixed today in the most recent version, 5.3.1. It would be great if this bug was finally taken care of.</p>
<p><strong>Edit:</strong> Joshua Johnston has posted a comment below that explains how to convert a string of data into a stream using the data stream wrapper. I&#8217;ve tried it out and it works very well. I think it gives a cleaner solution to the problem and allows the data returned from the database to be manipulated with file functions.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2010/02/21/handling-binary-data-with-pdo/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

