<?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>Matthew Turland &#187; Uncategorized</title> <atom:link href="http://matthewturland.com/category/uncategorized/feed/" rel="self" type="application/rss+xml" /><link>http://matthewturland.com</link> <description></description> <lastBuildDate>Tue, 15 May 2012 02:29:07 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator> <item><title>Restaurants and Web Sites</title><link>http://matthewturland.com/2011/05/14/restaurants-and-web-sites/</link> <comments>http://matthewturland.com/2011/05/14/restaurants-and-web-sites/#comments</comments> <pubDate>Sun, 15 May 2011 03:02:02 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category><guid
isPermaLink="false">http://matthewturland.com/?p=783</guid> <description><![CDATA[Today I saw the most recent episode of Kitchen Nightmares, which takes place in the city of Metairie in my home state of Louisiana. After the episode, I visited the web site of the featured restaurant. My experience there combined with other similar recent experiences inspired me to write this blog post. The topic of [...]]]></description> <content:encoded><![CDATA[<p>Today I saw the <a
title="Hulu - Kitchen Nightmares: Zeke's - Watch the full episode now." href="http://www.hulu.com/watch/240027/kitchen-nightmares-zekes">most recent episode of Kitchen Nightmares</a>, which takes place in the city of Metairie in my home state of Louisiana. After the episode, I visited the <a
title="Zekes Restaurant" href="http://www.eatatzekes.com/">web site of the featured restaurant</a>. My experience there combined with other similar recent experiences inspired me to write this blog post.</p><p>The topic of this post is not new. Let&#8217;s face it: once there&#8217;s an <a
title="What I want from a restaurant website - The Oatmeal" href="http://theoatmeal.com/comics/restaurant_website">Oatmeal strip</a> about a topic, chances are it&#8217;s been around the block once or twice. However, it seems like the point isn&#8217;t being driven home to its intended audience: restaurant owners. So, I&#8217;m aiming to present the material at a slightly different angle than I generally see it presented in hopes that it has the intended effect. Feel free to pass the link around to anyone you think is a member of that audience.</p><p>Let&#8217;s look at a hypothetical scenario. There&#8217;s a person, who we&#8217;ll call Joe, and he&#8217;s coming up on his lunch break at his office job. A few of his coworkers come around, say they&#8217;re thinking of dining out for lunch, and invite him to join. The group then tries to decide on a venue. To give them a better idea of their options, Joe pulls up a web site like <a
title="Google" href="http://www.google.com/">Google</a>, <a
title="Google Maps" href="http://maps.google.com/">Google Maps</a>, or <a
title="Urbanspoon" href="http://www.urbanspoon.com/choose">Urbanspoon</a> to see what&#8217;s nearby. A number of questions need to be answered when considering any individual option.</p><ul><li>What are the restaurant&#8217;s hours?</li><li>Is it open for breakfast, lunch, or dinner?</li><li>What type of food is served (e.g. burgers, Chinese, etc.) and how is it priced?</li><li>Where is the restaurant and what are the directions to get there from the office?</li><li>Does the restaurant offer orders for carry-out or delivery?</li><li>How long is the wait time before a customer is served?</li><li>Is a reservation required? If so, how far in advance does it need to be made and can it be done online?</li><li>For more uncommon questions, how can the restaurant be contacted?</li></ul><p><strong></strong>How much of this information does your site provide and how easily can potential customers find it? Are different pages of the site clearly named, linked to in a prominent navigation section, and populated with well-organized and relevant information? Are important basics like location, hours, and phone number prominently featured on every page?</p><p>Now, information from internet sources isn&#8217;t always accurate. Let&#8217;s say that the group chooses a restaurant, drives there, and realizes that the restaurant has closed down. They&#8217;re no longer near a computer, but with the increasing availability of mobile devices, each has a mobile phone. They use them to search again and review other options. There are several things that might make the group pass up a particular venue at this point.</p><ul><li>Desktop-targeted web sites. While these can be viewable on a mobile  phone, they can require a lot of zooming and panning to read and may not  display as well in mobile browsers. Offer an alternative minimalistic  version of the site for mobile devices.</li><li>Flash animations. Not only can they be large to download over a mobile network, but many mobile phones don&#8217;t support them and simply won&#8217;t display them. You probably don&#8217;t need Flash on your web site to begin with. If you really think you do, only use it on the desktop version; leave it out of the mobile version.</li><li>Menus in PDF format. Like Flash animations, they&#8217;re typically larger than a web page and many mobile phones can&#8217;t read them without supplemental software. Even with that software, they can be annoying to navigate. PDF files are great for printing and passing around the office, but the ideal situation for mobile phones is having the menu content on an actual web page, preferably one that&#8217;s mobile-specific. This also gives search engines additional content to pick up and associate with your restaurant.</li></ul><p><strong></strong>How mobile-friendly is your web site? Can all the information it offers be easily consumed by mobile devices as well as desktop computers?</p><p>One last parting thought: the end goal of a web site depends on the business it represents. Too often, I see restaurant owners lose sight of what the purpose of their web site should be: to get customers off the site and into the restaurant as quickly as possible. This contrasts with some sites like Facebook or Amazon, where the goal is to keep customers on the site as long as possible.</p><p>A restaurant web site can accomplish its goal by enabling prospective customers to get the information about the restaurant that they need and then leave. While it isn&#8217;t always feasible to measure, a web site that doesn&#8217;t do this effectively can have a very real, negative impact on the bottom line of the restaurant as a business because it is a reflection of that business.</p><p>If you own a restaurant and don&#8217;t have a web site yet, please keep these things in mind when  having one developed. If you already have a web site and it veers from  these guidelines, I urge you to consider having it changed. As usage of the internet  and mobile devices increases, these guidelines will only become more  important.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2011/05/14/restaurants-and-web-sites/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Twitter XSS Vulnerability</title><link>http://matthewturland.com/2010/09/21/twitter-xss-vulnerability/</link> <comments>http://matthewturland.com/2010/09/21/twitter-xss-vulnerability/#comments</comments> <pubDate>Tue, 21 Sep 2010 13:26:08 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category><guid
isPermaLink="false">http://matthewturland.com/?p=701</guid> <description><![CDATA[So by now a lot of people have realized that the Twitter web interface has succumbed to an XSS vulnerability. The JavaScript contained in one particular tweet that&#8217;s part of this causes you to retweet it so that it will spread to others and then establishes a modal overlay on your Twitter home page so [...]]]></description> <content:encoded><![CDATA[<p>So by now a lot of people have realized that the Twitter web interface has succumbed to an <acronym
title="Cross-Site Scripting"><a
title="Cross-site scripting - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a></acronym> vulnerability. The JavaScript contained in one particular tweet that&#8217;s part of this causes you to retweet it so that it will spread to others and then establishes a modal overlay on your Twitter home page so that mousing over it forces you to continue retweeting it over and over again.</p><p>I had a hunch on how to get around this that turned out to be correct. Go to your Twitter user page (in my case, <a
title="Matthew Turland (elazar) on Twitter" href="http://twitter.com/elazar">http://twitter.com/elazar</a>). This JavaScript doesn&#8217;t appear to affect that page, allowing you to undo the retweets so you can access your Twitter home page again. Note that this won&#8217;t prevent retweets from people you follow from showing up in your feed. The best you can really do about that is help to spread the word about how to fix this situation.</p><p>At this point, I would suggest deleting your cookies, logging into Twitter, navigating manually to <a
title="Twitter / Settings" href="http://twitter.com/login?redirect_after_login=%2Fsettings%2Faccount">http://twitter.com/settings/account</a>, changing your password, logging out, and logging in again. It may also be best to use a Twitter client instead of relying on the web interface until it&#8217;s fixed. <a
href="http://status.twitter.com/">No word from Twitter</a> on this as of yet.</p><p>If you have any other comments that may be handy in this situation, please leave them on this blog post.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2010/09/21/twitter-xss-vulnerability/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Stop Asking, Start Helping</title><link>http://matthewturland.com/2009/01/29/stop-asking/</link> <comments>http://matthewturland.com/2009/01/29/stop-asking/#comments</comments> <pubDate>Thu, 29 Jan 2009 17:01:40 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[PHP]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[Full disclosure: I&#8217;m not on the internals team. The topic of this blog post just happens to push my buttons and I want to be able to point people to a URL rather than answer the question over and over again. A question that seems to be popping up more and more these days is, [...]]]></description> <content:encoded><![CDATA[<p><em>Full disclosure: I&#8217;m <span
title="I do hope to eventually contribute something beyond the occasional bug report, though.">not on the internals team</span>. The topic of this blog post just happens to push my buttons and I want to be able to point people to a URL rather than answer the question over and over again.</em></p><p>A question that seems to be popping up more and more these days is, &quot;When will PHP 6 be released?&quot; It&#8217;s especially annoying because the people that <s>enjoy an exercise in futility</s> ask this question are the same people that simply refuse to take <acronym
title="When It's Ready">WIR</acronym> for an answer. Or maybe they just read into <a
href="http://www.amazon.com/s/ref=nb_ss_gw?url=search-alias%3Daps&amp;field-keywords=%22php+6%22&amp;x=0&amp;y=0" title="Amazon.com: php 6">the hype</a> generated by trigger-happy publishers who want to preempt a stable release, I don&#8217;t really know.</p><p>There&#8217;s been no alpha or beta release of 6; it hasn&#8217;t moved anywhere outside of the CVS repository yet. I would think that would provide some indication that 6 is still a ways off. The <a
href="http://news.php.net/php.internals/38911" title="php.internals: tentative 5.3 release plan">feature freeze</a> for 5.3 was originally set for 7/24/08. The <a
href="http://news.php.net/php.internals/42876" title="php.internals: PHP 5.3.0beta1">first beta release</a> only came out this week. This is all public knowledge and I think a pretty good indicator of the speed at which the landscape is changing.</p><p>Given what was <a
href="https://wiki.php.net/todo/php60" title="PHP: todo:php60 [PHP Wiki]">originally planned for 6</a> and how much of it <a
href="https://wiki.php.net/todo/php53" title="PHP: todo:php53 [PHP Wiki]">ended up in 5.3</a>, the 6 envisioned today could be worlds away from what actually ends up being released. Take a look at those TODO lists; the amount of work left to be done is anything but trivial. The internals team is not a corporate entity and its members are not compensated for their work in any way. They are volunteers and most work on PHP when they&#8217;re off the clock from their day jobs. This limits how quickly progress can be made and how accurate estimated release dates can be. So respect them and their time and stop asking when it&#8217;s going to be ready, because they don&#8217;t really know much better than you do.</p><p>Another thing: PHP is server-side software. It&#8217;s not a new web browser coming out where the user may or may not upgrade when you <span
title="These days, public beta versions are released well enough before stable ones that if you haven't tested by that time, you're in the wrong.">have had time to adapt your application</span> to work with both the old and new versions. No one is forcing you to upgrade the installation you use internally. If you have customers that maintain their own PHP installations, don&#8217;t feel pressured to be on the bleeding edge just because they want to be.</p><p>Be sensible: don&#8217;t lag more than two or so minor point versions behind the current stable offering, don&#8217;t immediately upgrade to <a
href="http://www.php.net/archive/2008.php#id2008-12-07-1" title="PHP: News Archive - 2008">a brand new stable version</a>, and have automated tests that can be run against <a
href="http://qa.php.net/rc.php" title="Release Candidates">release candidates</a> so it&#8217;s easier to discern issues that might arise when a stable release does come out and you want to upgrade.</p><p>If you <em>really</em> want to be prepared, there are several things you can do. Keep tabs on the <a
href="https://wiki.php.net/rfc" title="PHP: rfc [PHP Wiki]">accepted</a> and <a
href="https://wiki.php.net/rfc" title="PHP: rfc [PHP Wiki]">implemented</a> RFCs to see what features are being added and what effect, if any, they have on <acronym
title="Backward Compatibility">BC</acronym>. Search the <a
href="https://bugs.php.net/" title="PHP Bugs">bug tracker</a> for issues reported and fixed in the branch relevant to you. Don&#8217;t limit yourself to testing new versions with your own test suites, but <a
href="http://qa.php.net/howtohelp.php" title="How To Help [PHP-QAT: Quality Assurance Team]">help to write tests</a> for PHP itself to ensure that new versions are as stable as possible. These will make your time much better spent than asking a question that has no definitive answer. And it will keep the rest of our blood pressures all the lower for it.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2009/01/29/stop-asking/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Natural Ordering in MySQL</title><link>http://matthewturland.com/2008/11/05/natural-ordering-in-mysql/</link> <comments>http://matthewturland.com/2008/11/05/natural-ordering-in-mysql/#comments</comments> <pubDate>Wed, 05 Nov 2008 22:11:41 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Databases]]></category> <category><![CDATA[MySQL]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[I ran into an instance recently where I wanted to implement natural sorting of a result set in MySQL. When you&#8217;re dealing with numerical strings or strings with a common non-numeric prefix, the common solution of casting the order column to an integer by adding zero to it works fine. However, if neither of the [...]]]></description> <content:encoded><![CDATA[<p>I ran into an instance recently where I wanted to implement <a
href="http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html" title="Coding Horror: Sorting for Humans : Natural Sort Order">natural sorting</a> of a result set in MySQL. When you&#8217;re dealing with numerical strings or strings with a common non-numeric prefix, the common solution of casting the order column to an integer by adding zero to it works fine. However, if neither of the aforementioned conditions is the case, it takes a little more work.</p><p>What actually happens when you add zero to a non-numeric column depends on the characters at the beginning of the column value. If the column does not begin with a sequence of one or more numeric characters, then adding zero to that column produces zero. (Ex: &#8220;dog&#8221; + 0 = 0) If the column does begin with numeric characters, then adding zero to it produces the sequence of numeric characters up to the first non-numeric character in the original value or the end of the value, whichever comes first. (Ex: &#8220;12 dogs&#8221; + 0 = 12) An example might be the easiest way to illustrate this.</p><pre>
mysql> SELECT name+0<>0, name+0, name
    -> FROM `recommendation`
    -> ORDER BY name+0<>0 DESC, name+0, name;
+-----------+--------+------------------------+
| name+0<>0 | name+0 | name                   |
+-----------+--------+------------------------+
|         1 |      3 | 3 month follow-up      |
|         1 |      6 | 6 month follow-up      |
|         1 |     12 | 12 month follow-up     |
|         0 |      0 | Intervention           |
|         0 |      0 | Observation            |
|         0 |      0 | Specialty Consultation |
+-----------+--------+------------------------+
6 rows in set (0.00 sec)
</pre><p>The first ORDER BY clause checks the string to see if it begins with numeric characters, then places results for those that do first. If you prefer that numeric results appear after non-numeric results, then you can exclude this clause.</p><p>The second ORDER BY clause orders the numeric results by casting them to integers and ordering by those integers.</p><p>The third clause orders the non-numeric results by the original column value.</p><p>And that&#8217;s all there is to it. Hope this proves helpful to someone.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/11/05/natural-ordering-in-mysql/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>EAV Modeling – Square Peg in a Round Hole?</title><link>http://matthewturland.com/2008/07/19/eav-modeling-square-peg-in-a-round-hole/</link> <comments>http://matthewturland.com/2008/07/19/eav-modeling-square-peg-in-a-round-hole/#comments</comments> <pubDate>Sat, 19 Jul 2008 19:39:57 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Databases]]></category> <category><![CDATA[MySQL]]></category> <category><![CDATA[PHP]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[So I got the June 2008 issue of php&#124;architect (or volume 7 issue 6 for those of you who track it that way) in recently. Right off, I found the cover article on EAV modeling to be of interest seeing as my current employment is in the medical IT industry and I&#8217;d never heard of [...]]]></description> <content:encoded><![CDATA[<p>So I got the <a
title="php|architect / June 2008 — php|architect, PHP Magazine, PHP Conferences, PHP Books" href="http://www.phparch.com/magazine/2008-2/june/">June 2008 issue of php|architect</a> (or volume 7 issue 6 for those of you who track it that way) in recently. Right off, I found the cover article on <a
title="Entity-Attribute-Value model - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Entity-Attribute-Value_model"><acronym
title="Entity-Attribute-Value">EAV</acronym> modeling</a> to be of interest seeing as my current employment is in the medical IT industry and I&#8217;d never heard of this technique for storing data. I actually more or less knew what it was, but had never put a name to the face so to speak.</p><p>The mental image that came to me when reading about this approach to data modeling was taking the traditional relational table and turning it on its head. Despite what the Wikipedia article on the topic might tout early on, there are <a
href="http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides">disadvantages to using the EAV approach</a>. EAV actually has to circumvent, work around, or reimplement features that most mainstream database servers today provide &#8220;for free&#8221; to the traditional relational counterparts of EAV in order to get equal functionality. These include native data type validation and data type-specific operations without explicit typecasting (if you&#8217;re not separating EAV values by data type), row-level referential integrity, and schema metadata. EAV also adds a dimension of complexity to query construction in an era where storage is becoming cheaper and database technologies are evolving. It may work, but I don&#8217;t foresee it scaling very well for larger systems. In short, it seems an attempt to force a square peg into the round hole that are traditional relational database systems.</p><p>In a <a
title="MySQL :: The world's most popular open source database" href="http://mysql.com">MySQL</a> world, there are alternative approaches for deploying <a
href="http://en.wikipedia.org/wiki/Data_Description_Language"><acronym
title="Data Definition Language">DDL</acronym></a> modifications. One is to implement master-slave replication to propagate DDL modifications and load balancing to maintain uptime as changes are propagated from server to server. Another is to use MySQL Proxy to direct queries to servers hosting unmodified schemas and queue <a
href="http://en.wikipedia.org/wiki/Data_Manipulation_Language"><acronym
title="Data Manipulation Language">DML</acronym></a> operations in the binary log while DDL modifications are made. Once DDL is complete, the server goes into &#8220;read only&#8221; mode while queued DML operations are applied and incoming DML operations received during that time are blocked until the queue is empty. (This may be a potential point of improvement.)</p><p>Outside of MySQL, there are document-focused database systems such as <a
href="http://lucene.apache.org/core/index.html">Apache Lucene</a> and its current <a
title="Lucene.Net" href="http://incubator.apache.org/lucene.net/">.NET</a> and <a
title="Zend Framework: Zend_Search_Lucene" href="http://framework.zend.com/manual/en/zend.search.lucene.html">PHP</a> ports as well as <a
title="Apache CouchDB: The CouchDB Project" href="http://couchdb.apache.org/">Apache CouchDB</a>. While some of these are still a little early in development, I see them as being more ideal for applications demanding more fluid data storage and hope that the development of similar solutions continues.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/07/19/eav-modeling-square-peg-in-a-round-hole/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Output Filters in Zend_View</title><link>http://matthewturland.com/2008/06/04/output-filters-in-zend_view/</link> <comments>http://matthewturland.com/2008/06/04/output-filters-in-zend_view/#comments</comments> <pubDate>Wed, 04 Jun 2008 15:07:25 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[PHP]]></category> <category><![CDATA[Zend Framework]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[A feature of Zend Framework MVC that isn&#8217;t currently very well documented is output filters. They&#8217;re mentioned in passing in the Zend_View documentation, but not reviewed in detail anywhere in the Reference Guide as of version 1.5.2. I was curious enough about how to implement markup minification that I decided to trace through the Zend_View [...]]]></description> <content:encoded><![CDATA[<p>A feature of <a
title="Zend Framework" href="http://framework.zend.com">Zend Framework</a> <a
title="Zend Framework: Document - 7.1 Zend_Controller Quick Start" href="http://framework.zend.com/manual/en/zend.controller.html#zend.controller.quickstart"><acronym
title="Model-View-Controller">MVC</acronym></a> that isn&#8217;t currently very well documented is output filters. They&#8217;re mentioned in passing in the <a
title="Zend Framework:Documentation - 42 Zend_View" href="http://framework.zend.com/manual/en/zend.view.html">Zend_View</a> documentation, but not reviewed in detail anywhere in the Reference Guide as of version 1.5.2. I was curious enough about how to implement markup <a
title="Minification v Obfuscation - Yahoo! User Interface Blog" href="http://yuiblog.com/blog/2006/03/06/minification-v-obfuscation/">minification</a> that I decided to trace through the Zend_View source code in attempt to discern how output filters actually worked. As it turns out, it&#8217;s actually pretty simple.</p><p>First, you need to get a reference to the current Zend_View instance. If you&#8217;re using the <a
title="Zend Framework: Documentation - 20 Zend_Layout" href="http://framework.zend.com/manual/en/zend.layout.html">Zend_Layout</a> <a
title="Zend Framework: Documentation - 20.2.2. Using Zend_Layout with the Zend Framework MVC" href="http://framework.zend.com/manual/en/zend.layout.quickstart.html#zend.layout.quickstart.mvc">MVC integration</a>, you can get this by calling $this-&gt;<a
title="Zend_Controller_Action::$_helper" href="http://framework.zend.com/apidoc/core/Zend_Controller/Zend_Controller_Action.html#$_helper" class="broken_link">_helper</a>-&gt;<a
title="Zend_Layout_Controller_Action_Helper_Layout" href="http://framework.zend.com/apidoc/core/Zend_Controller/Zend_Controller_Action/Zend_Layout_Controller_Action_Helper_Layout.html" class="broken_link">layout</a>-&gt;<a
title="Zend_Layout_Controller_Action_Helper_Layout::getLayoutInstance" href="http://framework.zend.com/apidoc/core/Zend_Controller/Zend_Controller_Action/Zend_Layout_Controller_Action_Helper_Layout.html#getLayoutInstance" class="broken_link">getLayoutInstance</a> within your Zend_Controller_Action class to get the current Zend_Layout instance and then <a
title="Zend_Layout::getView" href="http://framework.zend.com/apidoc/core/Zend_Layout/Zend_Layout.html#getView" class="broken_link">getView</a> on that to get your Zend_View instance. Otherwise, the Zend_View instance is available via the <a
title="Zend_Controller_Action::$view" href="http://framework.zend.com/apidoc/core/Zend_Controller/Zend_Controller_Action.html#$view" class="broken_link">view property</a> of Zend_Controller_Action instance.</p><p>Next, call <a
title="Zend_View_Abstract::addFilterPath" href="http://framework.zend.com/apidoc/core/Zend_View/Zend_View_Abstract.html#addFilterPath" class="broken_link">addFilterPath</a> or <a
title="Zend_View_Abstract::setFilterPath" href="http://framework.zend.com/apidoc/core/Zend_View/Zend_View_Abstract.html" class="broken_link">setFilterPath</a> on your Zend_View instance from your Zend_Controller_Action class. Pass in a path to the directory to contain your output filter classes and a naming prefix that all of your output filter classes will use. I&#8217;m not sure why the class prefix defaults to &#8220;Zend_View_Filter_&#8221; since no such classes exist. In my opinion, it would have made more sense to derive the prefix based on the provided directory path. Anyway, create the directory you&#8217;ve specified if it doesn&#8217;t already exist and create a new class file within that directory. In my case, I named the directory Vendor/View/Filter, the file Minify.php, and the class contained in the file Vendor_View_Filter_Minify.</p><p>Within this class, you must implement at least one method, filter. This method should accept a single parameter, which will be a string containing the view ouput to be filtered, and should return the filtered version of that string. Optionally, if your filter requires access to the related Zend_View instance, you can also declare a setView method that accepts the Zend_View instance as its only parameter and it will automatically be passed in when your output filter class is instantiated. Within setView, you can store the Zend_View instance in an instance property of the output filter class so it can be referred to later in the filter method.</p><p>Once you&#8217;ve finished your output filter class, you need to explicitly add it to the output filters in use from your Zend_Controller_Action class. You can use <a
title="Zend_View_Abstract::addFilter" href="http://framework.zend.com/apidoc/core/Zend_View/Zend_View_Abstract.html#addFilter" class="broken_link">addFilter</a> or <a
title="Zend_View_Abstract::setFilter" href="http://framework.zend.com/apidoc/core/Zend_View/Zend_View_Abstract.html#setFilter" class="broken_link">setFilter</a> for this. Pass in the name of your output filter class without the class prefix. In my case, I passed in &#8220;Minify.&#8221; At this point, the filter should be used when rendering your page. I poked around in the DOM and Tidy PHP extension documentation, but couldn&#8217;t find a feature for markup minification, so I ended up using the PCRE extension to do the job. Below is the final source code for my output filter class.</p><p>Vendor/View/Filter/Minify.php</p><pre class="brush: php; title: ; notranslate">class Vendor_View_Filter_Minify
{
    public function filter($string)
    {
        return preg_replace(
            array('/&gt;\s+/', '/\s+&lt;/', '/[\x0A\x0D]+/'),
            array('&gt;', '&lt;', ' '),
            $string
        );
    }
}</pre><p>Vendor/Controller.php</p><pre class="brush: php; title: ; notranslate">class Vendor_Controller extends Zend_Controller_Action
{
    public init()
    {
        $this-&gt;_helper-&gt;layout-&gt;getLayoutInstance()-&gt;getView()
            -&gt;addFilterPath('Vendor/View/Filter', 'Vendor_View_Filter_')
            -&gt;addFilter('Minify');
    }
}</pre>]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/06/04/output-filters-in-zend_view/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Oracle XE 10gR2 on Kubuntu 64-bit</title><link>http://matthewturland.com/2008/05/25/oracle-xe-10gr2-on-kubuntu-64-bit/</link> <comments>http://matthewturland.com/2008/05/25/oracle-xe-10gr2-on-kubuntu-64-bit/#comments</comments> <pubDate>Sun, 25 May 2008 21:10:33 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Kubuntu]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[Oracle]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[So I started poking around for instructions on installing Oracle XE 10gR2 on my Kubuntu Hardy 64-bit installation recently. I came across this article from Oracle, which seemed like exactly what I wanted. Unfortunately, it assumes that the intended host operating system is 32-bit, which causes issues if you try to install XE through apt [...]]]></description> <content:encoded><![CDATA[<p>So I started poking around for instructions on installing Oracle XE 10gR2 on my Kubuntu Hardy 64-bit installation recently. I came across <a
title="Installing Oracle Database XE on Debian, Ubuntu, and Kubuntu" href="http://www.oracle.com/technetwork/topics/linux/whatsnew/index.html">this article</a> from Oracle, which seemed like exactly what I wanted. Unfortunately, it assumes that the intended host operating system is 32-bit, which causes issues if you try to install XE through apt as the Oracle article suggests. After following these instructions, I immediately received this error:</p><p><code>W: Failed to fetch http://oss.oracle.com/debian/dists/unstable/Release \ Unable to find expected entry main/binary-amd64/Packages in \ Meta-index file (malformed Release file?)</code></p><p>After that, any apt command issued (related or not) produced this error.</p><p><code>E: The package oracle-xe needs to be reinstalled, but I can't find an \ archive for it.</code></p><p>And finally, when I resorted to using <a
title="How To Install Oracle XE in Ubuntu 64 Bit | little brain" href="http://justalittlebrain.wordpress.com/2008/05/12/how-to-install-oracle-xe-in-ubuntu-64-bit/">this excellent guide</a> instead, I ran into this problem because of the earlier failed installation.</p><p><code>dpkg: regarding oracle-xe-universal_10.2.0.1-1.1_i386.deb containing \ oracle-xe-universal: oracle-xe-universal conflicts with oracle-xe oracle-xe (version 10.2.0.1-1.0) is present and broken due to failed \ removal or installation.dpkg: error processing oracle-xe-universal_10.2.0.1-1.1_i386.deb \ (--install): conflicting packages - not installing oracle-xe-universalErrors were encountered while processing: oracle-xe-universal_10.2.0.1-1.1_i386.deb</code></p><p>Luckily, I was able to find <a
title="Package Installation error and solution -- Ubuntu Geek" href="http://www.ubuntugeek.com/package-installation-error-and-solution.html">a solution</a> to purge the failed installation from the system.</p><p><code>dpkg --remove --force-remove-reinstreq oracle-xe-universal</code></p><p>One thing that the Oracle article was useful for was creating a swap file large enough for Oracle to use, as the issue described in the article with not having enough swap space did arise when I initially tried the installation. Beyond that, the non-Oracle guide mentioned earlier worked like a charm and I now have a working XE installation on my system.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/05/25/oracle-xe-10gr2-on-kubuntu-64-bit/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>DomQuery</title><link>http://matthewturland.com/2008/05/25/domquery/</link> <comments>http://matthewturland.com/2008/05/25/domquery/#comments</comments> <pubDate>Sun, 25 May 2008 04:26:53 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[PHP]]></category> <category><![CDATA[XML]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[Ever since I started working with the jQuery JavaScript library, I&#8217;ve loved it. It offers the power to do a lot with only a little code and makes features offered by the JavaScript DOM implementation much easier to access. My interest in web scraping prompted me to consider creating an equivalent of sorts for PHP. [...]]]></description> <content:encoded><![CDATA[<p>Ever since I started working with the <a
title="jQuery: The Write Less, Do More, JavaScript Library" href="http://jquery.com">jQuery</a> JavaScript library, I&#8217;ve loved it. It offers the power to do a lot with only a little code and makes features offered by the JavaScript <a
title="Document Object Model - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Document_Object_Model"><acronym
title="Document Object Model">DOM</acronym></a> implementation much easier to access. My interest in web scraping prompted me to consider creating an equivalent of sorts for PHP.</p><p>This obviously doesn&#8217;t include some features specific to the client-side or any that require evaluating CSS, but it does include many for extracting data from a valid XML or HTML document. I&#8217;ve posted my initial work on the concept in an <a
title="DomQuery" href="https://github.com/elazar/domquery">GitHub repository</a>. The code there is commented with docblocks and includes unit tests with over 99% code coverage. Comments and suggestions are welcome.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/05/25/domquery/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>PHP 5.2 and SQL Server 2000 on Windows XP</title><link>http://matthewturland.com/2008/05/10/php-5-2-and-sql-server-2000-on-windows-xp/</link> <comments>http://matthewturland.com/2008/05/10/php-5-2-and-sql-server-2000-on-windows-xp/#comments</comments> <pubDate>Sat, 10 May 2008 17:38:59 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Databases]]></category> <category><![CDATA[PHP]]></category> <category><![CDATA[SQL Server]]></category> <category><![CDATA[Windows]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[Recently at work, I was tasked with finding a method to retrieve data from a third-party SQL Server 2000-based system into our own MySQL-based application. It&#8217;s worth noting that both system are behind their own firewalls and I was trying to bear security in mind as I did this. First, I had to actually get [...]]]></description> <content:encoded><![CDATA[<p>Recently at work, I was tasked with finding a method to retrieve data from a third-party SQL Server 2000-based system into our own MySQL-based application. It&#8217;s worth noting that both system are behind their own firewalls and I was trying to bear security in mind as I did this.</p><p>First, I had to actually get into the system with the SQL Server database. For this, I used <a
title="Citrix Systems - Citrix GoToAssist" href="http://www.citrix.com/English/ps2/products/product.asp?contentID=13972&amp;ntef=hp_nav_US">Citrix GoToAssist</a>. The company behind the software makes their money off of hosting the servers it uses and selling access to them as a service. The client software uses HTTPS for security and to get around firewall configurations. While their software is nice, I&#8217;d be interested to see if anyone knows of any OSS equivalents of it.</p><p>Once I had access to the system, I needed something akin to <a
title="phpMyAdmin | MySQL Database Administration Tool | www.phpmyadmin.net" href="http://www.phpmyadmin.net/home_page/index.php">phpMyAdmin</a> or <a
title="Oracle SQL Developer" href="http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html">Oracle SQL Developer</a> in order to see what resources were available on the SQL Server itself. For that, I found a local copy of <a
title="EMS SQL Manager - EMS SQL Manager for SQL Server: Microsoft SQL Server Tool, MSSQL Database Design, MS SQL Server Management and Administration, Export and Import Database Tools for MS SQL Server" href="http://www.sqlmanager.net/products/mssql/manager/">EMS SQL Manager</a> already on the system. This wasn&#8217;t the most full-fledged product I&#8217;d seen for this type of purpose, but it was free, included everything I needed, and did the job in a pinch.</p><p>After doing some reconnaisance on the database structure using the information that had been given to me by the third-party vendor, I downloaded the ZIP archive containing the standard build of PHP 5.2 for Windows. Side note: one of the things I like about PHP on Windows is that, for CLI purposes, it only takes decompressing the ZIP archive, tweaking the configuration file to get the settings and extensions you want, and executing the binary to get it up and running.</p><p>With my SQL Server experience being dated by about six years, I started throwing PHP code at the system to see what would stick. I noticed that the server was already set up to accept trusted connections, and being that I was running the script on the local system, this made it likely that authentication wouldn&#8217;t present any issues, or so I thought.</p><p>I created my PDO instance like so:</p><pre>$db = new PDO('mssql:localhost;dbname=...');</pre><p>And then attempted to call a particular stored procedure that I&#8217;d been told would have some of the data I was looking to extract. I was surprised to get this in response when calling PDO::errorInfo().</p><pre>Array(    [0] =&gt; HY000    [1] =&gt; 10007    [2] =&gt; Could not find stored procedure ... [10007] (severity 5) [EXEC ...]    [3] =&gt; -1    [4] =&gt; 5)</pre><p>Now I had just been in EMS SQL Manager and seen the stored procedure myself, so I knew it was there. I tried using the sa account, but that didn&#8217;t seem to work either. After some digging, I found that I had to create an account for the current Windows user on the current network domain in order to make PHP capable of seeing the stored procedure when using a trusted connection. Once I&#8217;d created the account and given it access to execute the specific stored procedure I was trying to call, I tried again and PDO::errorInfo then gave me this.</p><pre>Array(    [0] =&gt; HY000    [1] =&gt; 10007    [2] =&gt; Unicode data in a Unicode-only collation or ntext data cannot be sent to clients using DB-Library (such as ISQL) or ODBC version 3.7 or earlier. [10007] (severity 5) [EXEC ...]    [3] =&gt; -1    [4] =&gt; 5)</pre><p>Apparently there are issues with the MS SQL stand-alone PHP extension and SQL Servers using unicode collation. Some more digging turned up that the only way to get around this was to use ODBC. Once I did that, I found that I was no longer getting an error when trying to call the stored procedure.</p><pre>$db = new PDO('odbc:Driver={SQL Server};Server=localhost;Database=...;Trusted_Connection=yes;');</pre><p>Though I knew of stored procedures conceptually, my previous experience with SQL Server had never included using them. As such, I wasn&#8217;t familiar with the syntax and came across something rather strange while trying to troubleshoot it: if the arguments to a stored procedure are surrounded by parentheses in the&nbsp; query calling that stored procedure, the code silently fails and returns no results.</p><pre>// $stmt = $db-&gt;prepare('EXEC ...(?, ?)'); // Fails silently$stmt = $db-&gt;prepare('EXEC ... ?, ?'); // Works as expected</pre><p>Last on the list of &#8220;interesting things I experienced&#8221; while on this little trek wasn&#8217;t related to the database, but to what was happening when I attempted to push data from the SQL Server machine to our LAMP machine. I was using the PHP serialize() function to encode the data into a string, then using the streams HTTPS wrapper to send it via a POST request to a PHP file on the LAMP machine. This meant I wouldn&#8217;t have to poke a hole in the firewall on either side since both were already open to web traffic. When attempting to run the code for this, I got an error on the client side:</p><pre>PHP Warning:  file_get_contents(): SSL: An existing connection was forcibly closed by the remote host.PHP Warning:  file_get_contents(https://...): failed to open stream: HTTP request failed!</pre><p>The cause for this wasn&#8217;t immediately apparent. Upon checking Apache error logs, I came across this:</p><pre>PHP Fatal error:  Allowed memory size of 16777216 bytes exhausted (tried to allocate 3381676 bytes)</pre><p>The actual issue had to do with how much data I was trying to send; it was exceeding the value specified in the memory_limit configuration setting, which as it turned out was set to the recommended value for a significantly older version of PHP. After updating it to a more current recommended value and bouncing Apache, all was well.</p><p>Hope the details of my experiences prove helpful to someone else. Thanks to those who provided assistance along the way.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/05/10/php-5-2-and-sql-server-2000-on-windows-xp/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Phergie on C7Y Yet Again</title><link>http://matthewturland.com/2008/04/27/phergie-on-c7y-yet-again/</link> <comments>http://matthewturland.com/2008/04/27/phergie-on-c7y-yet-again/#comments</comments> <pubDate>Sun, 27 Apr 2008 14:30:09 +0000</pubDate> <dc:creator>Matthew Turland</dc:creator> <category><![CDATA[Uncategorized]]></category> <category><![CDATA[Phergie]]></category> <category><![CDATA[PHP]]></category> <category><![CDATA[Podcasts]]></category><guid
isPermaLink="false"></guid> <description><![CDATA[The guys at C7Y really seem to like Phergie. The articles about the Phergie project on C7Y got a brief shout-out in the P3 Podcast for 4/17/08. Thanks for the plug guys! The rest of the podcast was really awesome too. I definitely recommend checking it out.]]></description> <content:encoded><![CDATA[<p>The guys at C7Y really seem to like <a
title="Phergie" href="http://phergie.org">Phergie</a>. The articles about the Phergie project on C7Y got a brief shout-out in the <a
title="Welcome&mdash; php|architect&#039;s C7Y, The PHP Community Website" href="http://wayback.archive.org/web/jsp/Interstitial.jsp?seconds=5&amp;date=1217560426000&amp;url=http%3A%2F%2Fc7y.phparch.com%2Fc%2Fentry%2F1%2Fp3%2C20080417&amp;target=http%3A%2F%2Fweb.archive.org%2Fweb%2F20080801031346%2Fhttp%3A%2F%2Fc7y.phparch.com%2Fc%2Fentry%2F1%2Fp3%2C20080417">P3 Podcast</a> for 4/17/08. Thanks for the plug guys! The rest of the podcast was really awesome too. I definitely recommend checking it out.</p> ]]></content:encoded> <wfw:commentRss>http://matthewturland.com/2008/04/27/phergie-on-c7y-yet-again/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using apc
Page Caching using disk: enhanced
Database Caching 33/36 queries in 0.009 seconds using apc

Served from: matthewturland.com @ 2012-05-21 16:30:30 -->
