<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Tower Of Power</title>
	
	<link>http://www.toosweettobesour.com</link>
	<description>Far Too Sweet To Be Sour</description>
	<lastBuildDate>Mon, 08 Apr 2013 02:46:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/toosweettobesour/HrtK" /><feedburner:info uri="toosweettobesour/hrtk" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>30.571905</geo:lat><geo:long>-96.298825</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/</creativeCommons:license><item>
		<title>New Blog, This One Is Inactive</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/YkI3Nv9njSo/</link>
		<comments>http://www.toosweettobesour.com/2013/04/07/new-blog-this-one-is-inactive/#comments</comments>
		<pubDate>Mon, 08 Apr 2013 02:46:21 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=506</guid>
		<description><![CDATA[If you are reading this you are subscribed to my old blog site or arrived here via a google search or something similar. You can find my new blog at dcousineau.com. I will be making no further updates to this blog. I may or may not import my old posts into the above site but [...]]]></description>
				<content:encoded><![CDATA[<p>If you are reading this you are subscribed to my old blog site or arrived here via a google search or something similar. </p>
<p>You can find my new blog at <a href="http://dcousineau.com" title="My new blog">dcousineau.com</a>. I will be making no further updates to this blog. I may or may not import my old posts into the above site but I will be leaving this blog up for quite some time until I do.</p>
<p>My new blog&#8217;s ATOM feed (for use with your feed reader of choice) is <a href="http://dcousineau.com/atom.xml">http://dcousineau.com/atom.xml</a>.</p>
<p>Thank you for reading</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2013/04/07/new-blog-this-one-is-inactive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2013/04/07/new-blog-this-one-is-inactive/</feedburner:origLink></item>
		<item>
		<title>Flex Box: Prevent Children From Stretching</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/k_9cFJ5qcvw/</link>
		<comments>http://www.toosweettobesour.com/2011/07/14/flex-box-prevent-children-from-stretching/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 21:47:57 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[columns]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[flex box]]></category>
		<category><![CDATA[moz-box-flex]]></category>
		<category><![CDATA[webkit-box-flex]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=497</guid>
		<description><![CDATA[So, flex boxes are a glorious addition to CSS3 to make advanced layouts rapidly. No more crazy floats and nested divs and weird percentage values for columns! Just setup your orientation to horizontal and toss a box-flex: 1 in for kicks. However, just a tip: In the course of working with flex boxes, you will [...]]]></description>
				<content:encoded><![CDATA[<p>So, <a href="http://www.the-haystack.com/2010/01/23/css3-flexbox-part-1/">flex boxes</a> are a glorious addition to CSS3 to make advanced layouts rapidly. No more crazy floats and nested divs and weird percentage values for columns! Just setup your orientation to horizontal and toss a <code>box-flex: 1</code> in for kicks.</p>
<p>However, just a tip: In the course of working with flex boxes, you will find that if you given a parent container a flex value, the children can still stretch it out. For example, a long paragraph will push its parent wider and wider to accommodate unless you give it a static width (which kinda defeats the purpose of using flex boxes really).</p>
<p>A nifty trick, however, is if you give an element with a defined <code>box-flex</code> a <code>width: 0px;</code>, the sizing algorithm will ignore said element&#8217;s children when sizing the element.</p>
<p>Here&#8217;s an example of automatic vertical columns:</p>
<pre name="code" class="html">
&lt;div id="wall"&gt;
    &lt;div id="col1" class="column top"&gt;
        
        &lt;div class="entry"&gt;
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam eget tristique velit. In ut ligula nibh, a pulvinar lorem. Nam sed elit eget tellus vestibulum
        &lt;/div&gt;
        
    &lt;/div&gt;
    &lt;div id="col2" class="column bottom"&gt;
        
        &lt;div class="entry"&gt;
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam eget tristique velit. In ut ligula nibh, a pulvinar lorem. Nam sed elit eget tellus vestibulum
        &lt;/div&gt;
        
    &lt;/div&gt;
    &lt;div id="col3" class="column top"&gt;&lt;/div&gt;
    &lt;div id="col4" class="column bottom"&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<pre name="code" class="css">
#wall {
    display: -webkit-box;
    -webkit-box-orient: horizontal;
    
    position: absolute !important;
    top:0; 
    right:0; 
    bottom:0; 
    left:0;
    
    overflow: hidden;
}

#wall .column {
    display: -webkit-box;
    -webkit-box-sizing: border-box;
    
    -webkit-box-orient: vertical;
    
    -webkit-box-flex: 1;
    width:0px;
    
    border-right: 1px solid #333;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2011/07/14/flex-box-prevent-children-from-stretching/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2011/07/14/flex-box-prevent-children-from-stretching/</feedburner:origLink></item>
		<item>
		<title>A Lesson In Good Architecture</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/H-8ouwNUkq4/</link>
		<comments>http://www.toosweettobesour.com/2011/01/29/a-lesson-in-good-architecture/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 19:58:56 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=487</guid>
		<description><![CDATA[We recently began working on our biggest event for our biggest client. In the process of getting everything up and running before the event started, we noticed a show-stopper bug appear out of nowhere. Our media processor when finished converting videos and creating thumbnails of images publishes said files to our CDN. Only a few [...]]]></description>
				<content:encoded><![CDATA[<p>We recently began working on our biggest event for our biggest client. In the process of getting everything up and running before the event started, we noticed a show-stopper bug appear out of nowhere.</p>
<p>Our media processor when finished converting videos and creating thumbnails of images publishes said files to our CDN. Only a few hours before our event and our CDN was failing probably 80% of the SSL handshakes for our requests to publish files. There is no need to name names as it was a difficult and obscure bug to diagnose in an extremely short amount of time. We needed to get it working, our CDN provider wasn&#8217;t going to be able to resolve the problem in the extremely short timeframe we required, so the decision was clear: we needed to switch providers for the new content.</p>
<p>Normally this is a 2 week job, switching API calls, testing, finding all the occurrences (we process both videos and photos in different styles of batches), etc. We were able to complete it and have it live in under 1.5 hours. Why? We (and really I mean my coworker as this decision was made before I came on) made som really damned good architecture decisions. Primarly:</p>
<ol>
<li>We used OSS, primarily <a href="">Zend Framework</a> which had well written API libraries for our new CDN</li>
<li>All file system operations were abstracted to adapters that all inherited a &#8220;FileStore&#8221; base class</li>
</ol>
<p>So, create a file store for our new CDN using the well written, off the shelf API. Change 4 lines of XML configuration, deploy, and we were in business.</p>
<p>Had my coworker succumbed to laziness or listen to some people who claim &#8220;oh you&#8217;re just making it too complicated&#8221; or &#8220;just get it up quickly, damn the design decisions&#8221; we would have been sunk. Instead he took the time to utilize the adapter pattern (even though it probably added an extra 2 days to his total coding time) despite all signs pointing to us never needing to switch CDN&#8217;s (and certainly not within a 2 hour timeframe).</p>
<p>So let this be a lesson to us all. Abstraction and design patterns sometimes feel like an &#8220;enterprisey overcomplication&#8221; but they aren&#8217;t there for everyday needs. They exist for those days when a service provider gets hit by an obscure bug and you have to swap out a component under extreme time schedules. So suck it up, use them, and thank yourself when you find yourself in such a situation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2011/01/29/a-lesson-in-good-architecture/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2011/01/29/a-lesson-in-good-architecture/</feedburner:origLink></item>
		<item>
		<title>Doctrine 1.2 MSSQL Alternative LIMIT/Paging</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/g2WxQ2IDAZs/</link>
		<comments>http://www.toosweettobesour.com/2010/09/16/doctrine-1-2-mssql-alternative-limitpaging/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 22:11:47 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[mssql]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=477</guid>
		<description><![CDATA[At work I had been having all sorts of issues with Doctrine_Connection_Mssql&#8216;s LIMIT alteration, based on Zend_Db&#8216;s code. The code used the more-compatible-with-SQL-Server-2000 technique of modifying the query to SELECT TOP (offset + limit), reverse the ORDER BY clause and SELECT TOP (limit), then finally reversing the returned dataset. As ugly as this technique is, [...]]]></description>
				<content:encoded><![CDATA[<p>At work I had been having all sorts of issues with <code>Doctrine_Connection_Mssql</code>&#8216;s <code>LIMIT</code> alteration, based on <code>Zend_Db</code>&#8216;s code.</p>
<p>The code used the more-compatible-with-SQL-Server-2000 technique of modifying the query to <code>SELECT TOP (offset + limit)</code>, reverse the <code>ORDER BY</code> clause and <code>SELECT TOP (limit)</code>, then finally reversing the returned dataset.</p>
<p>As ugly as this technique is, it works. The problem is it requires an extreme amount of intelligence or an extreme amount of simplicity in the query in order for an automated system like Doctrine to be usable. The biggest caveat with this technique is good goddamned luck paging your query if it doesn&#8217;t have an <code>ORDER BY</code>. And sometimes queries that are complex enough break the modified <code>Zend_Db</code> code.</p>
<p>There exists an <a href="http://varjabedian.net/archive/2008/04/09/paging-made-easy-in-ms-sql-server-2005.aspx">easier MSSQL paging technique</a>. Using features first available in SQL Server 2005, with only 1 subquery you can mimic MySQL&#8217;s <code>LIMIT</code> clause with ease.</p>
<p>Basically, Microsoft provided the following special feature to determine the row number in your final resultset:</p>
<pre name="code" class="sql">SELECT Row_Number() OVER (ORDER BY column) AS RowIndex FROM table</pre>
<p>Notice the <code>OVER (ORDER BY column)</code> segment? This is provided as this query will most often be used in a subquery. Given that MSSQL does not allow <code>ORDER BY</code> statements in subqueries, just move them into the <code>OVER (...)</code> section.</p>
<p>To borrow Ralph Varjabedian&#8217;s example, the following MySQL query:</p>
<pre name="code" class="sql">SELECT * FROM users LIMIT 15, 15</pre>
<p>Becomes functionally equivalent to the following MSSQL query:</p>
<pre name="code" class="sql">SELECT 
    * 
FROM 
    (
    SELECT 
        Row_Number() OVER (ORDER BY userID) AS RowIndex, 
        * 
    FROM 
        users
    ) AS sub 
WHERE 
    sub.RowIndex > 15 
    AND sub.RowIndex <= 30</pre>
<p>Now all I needed to do was add the ability for Doctrine to parse a generated MSSQL query and reform it like the one above!</p>
<p>I've provided a copy of the Doctrine connection adapter I wrote. Simply add the following line to wherever you setup Doctrine:</p>
<p><strong>Please note: This was the result of about 6 hours of hacking today. There are certainly places in the code where it can be more robust or improved, especially in my little parser. Use at your own risk (though I have yet to encounter any errors in my application).</strong></p>
<pre name="code" class="php">&lt;?php
class CaseMan_Doctrine_Connection_Mssql extends Doctrine_Connection_Mssql
{
    /**
     * @var string $driverName                  the name of this connection driver
     */
    protected $driverName = 'Mssql';

    /**
     *
     * @var boolean $is2005OrBetter             cached result determining if server is SQL Server 2005 or better
     */
    protected $is2005OrBetter;

    /**
     * the constructor
     *
     * @param Doctrine_Manager $manager
     * @param PDO $pdo                          database handle
     */
    public function __construct(Doctrine_Manager $manager, $adapter)
    {
        parent::__construct($manager, $adapter);
    }

    /**
     * Adds an adapter-specific LIMIT clause to the SELECT statement.
     *
     * @param string $query
     * @param mixed $limit
     * @param mixed $offset
     * @return string
     */
    public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
    {
        if ($limit &lt;= 0 &#038;&#038; $offset &lt;= 0)
            return $query;
        
        if( !$this-&gt;is2005OrBetter() ) //Not at least 2005
            return parent::modifyLimitQuery ($query, $limit, $offset, $isManip);
        
        //SETUP FIELD ALIASES
        $inner_query_name = '_inner_query_';
        $row_count_name = '_inner_query_row_count_';

        //PREPARE TOKENIZER REGEXES
        $escaped = "\\\.";
        $sections = "SELECT|FROM|WHERE|GROUP[ ]+BY|HAVING|ORDER[ ]+BY";
        $open_delimiters = "[\[\(]";
        $close_delimiters = "[\]\)]";
        $string_delimiters = "[\"\']";

        //TOKENIZE QUERY
        $_split_query = preg_split(
            "#({$escaped}|{$sections}|{$open_delimiters}|{$close_delimiters}|{$string_delimiters})#i",
            trim($query),
            -1,
            PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
        );

        $query_parts = array();
        $_state = 'BEGIN';
        $_current_part = 'SELECT';
        $_stack = array();
        while( $_token = array_shift($_split_query) )
        {
            switch( $_state )
            {
                case 'BEGIN':

                    if( trim(strtoupper($_token)) == 'SELECT' )
                    {
                        $query_parts['SELECT'] = '';
                        $_current_part = 'SELECT';
                        $_state = 'SECTION';
                    }
                    else
                    {
                        throw new Doctrine_Exception("Invalid query passed to modifyLimitQuery, must begin with SELECT");
                    }

                    break;
                case 'SECTION':

                    if( preg_match("#^({$sections})$#i", trim($_token)) )
                    {
                        $_section = strtoupper(trim($_token));

                        $query_parts[$_section] = '';
                        $_current_part = $_section;
                        $_state = 'SECTION';
                    }
                    else
                    {
                        $query_parts[$_current_part] .= $_token;

                        if( preg_match("#^({$string_delimiters})$#i", trim($_token)) )
                        {
                            array_push($_stack, trim($_token));
                            $_state = 'STRING';
                        } else if( preg_match("#^({$open_delimiters})$#i", trim($_token)) )
                        {
                            array_push($_stack, trim($_token));
                            $_state = 'DELIMITED';
                        }
                    }

                    break;
                case 'DELIMITED':

                    $query_parts[$_current_part] .= $_token;

                    if( preg_match("#^({$close_delimiters})$#i", trim($_token)) )
                    {
                        $_prev_delimiter = array_pop($_stack);
                        switch( trim($_token) )
                        {
                            case ']':
                                if( $_prev_delimiter != '[' )
                                    throw new Doctrine_Exception("Mismatched ]");
                                break;
                            case ')':
                                if( $_prev_delimiter != '(' )
                                    throw new Doctrine_Excpetion("Mismatched )");
                                break;
                            default:
                                trigger_error("FATAL ERROR: UNRECOGNIZED CLOSE DELIMITER TOKEN '{$_token}' IN " . __CLASS__ . '::' . __METHOD__, E_USER_ERROR);
                        }

                        if( count($_stack) == 0 )
                            $_state = 'SECTION';
                    }
                    elseif( preg_match("#^({$open_delimiters})$#i", trim($_token)) )
                    {
                        array_push($_stack, trim($_token));
                    }

                    break;
                case 'STRING':

                    $query_parts[$_current_part] .= $_token;

                    if( preg_match("#^({$string_delimiters})$#i", trim($_token)) )
                    {
                        if( trim($_token) == end($_stack) )
                        {
                            array_pop($_stack);
                            $_state = 'SECTION';
                        }
                    }

                    break;
            }
        }
        unset($item, $_current_part, $_token, $_stack, $_state, $_section);

        //DIVIDE UP THE SELECT STATEMENT TO PREPARE TO INSERT THE ROW_NUMBER() SELECT FIELD
        $_select_split = array_map('trim', preg_split(
            "#^(DISTINCT|)[ ]*(TOP[ ]+[0-9]+|)#i",
            trim($query_parts['SELECT']),
            -1,
            PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
        ));

        $_select_details = array_pop($_select_split);

        $query_parts['SELECT'] = array_merge((array)implode(' ', $_select_split), (array)$_select_details);
        unset($_select_split, $_select_details);

        

        //SETUP OUTER QUERY SELECT STATEMENT
        $outer_select = array();
        foreach( array_map('trim', explode(',', end($query_parts['SELECT']))) as $_select )
        {
            $matches = array();
            if( preg_match('#AS[ ]+(?&lt;alias&gt;.*)$#i', $_select, $matches) )
            {
                $outer_select[] = "[{$inner_query_name}]." . trim($matches['alias']);
            }
            else if( preg_match('#^(?&lt;table&gt;(\[[^\]]+\]|[^\.]+)\.|)(?&lt;field&gt;.*)#i', $_select, $matches) )
            {
                $outer_select[] = "[{$inner_query_name}]." . trim($matches['field']);
            }
        }

        //SETUP ROW_COUNT OVER() SEGMENT
        if( isset($query_parts['ORDER BY']) )
        {
            $row_count_select = "Row_Number() OVER (ORDER BY " . $query_parts['ORDER BY'] . ") AS [{$row_count_name}]";
            unset($query_parts['ORDER BY']); //ORDER BY NOT ALLOWED IN SUBQUERY, OVER(...) TAKES ITS PLACE
        }
        else
        {
            $row_count_select = "Row_Number() OVER (ORDER BY (SELECT 0)) AS [{$row_count_name}]";
        }

        $query = implode(' ', array(
            'SELECT',
            count($query_parts['SELECT']) &gt; 1 ?
                $query_parts['SELECT'][0] . ' ' . implode(', ', array(
                    $row_count_select,
                    $query_parts['SELECT'][1]
                )) :
                implode(', ', array(
                    $row_count_select,
                    $query_parts['SELECT'][0]
                )),
        ));

        unset($query_parts['SELECT']);
        foreach( $query_parts as $section =&gt; $parameters )
            $query .= ' ' . $section . ' ' . $parameters;


        $outer_query = "SELECT " . implode(', ', $outer_select) . " FROM (" . $query . ") AS [{$inner_query_name}]";

        if( $limit || $offset )
        {
            $outer_where = array();
            if( $limit )
                $outer_where[] = "[{$inner_query_name}].[{$row_count_name}] &lt;= " . ($limit + $offset);
            if( $offset )
                $outer_where[] = "[{$inner_query_name}].[{$row_count_name}] &gt; " . $offset;

            $outer_query .= ' WHERE ' . implode(' AND ', $outer_where);
        }
        
        return $outer_query;
    }

    public function is2005OrBetter()
    {
        if( !isset($this-&gt;is2005OrBetter) )
        {
            $version = $this-&gt;getServerVersion();

            if( $version['major'] &gt;= 9 )
                $this-&gt;is2005OrBetter = true;
            else
                $this-&gt;is2005OrBetter = false;
        }

        return $this-&gt;is2005OrBetter;
    }

    /**
     * return version information about the server
     *
     * @param bool   $native  determines if the raw version string should be returned
     * @return array    version information
     */
    public function getServerVersion($native = false)
    {
        if ($this-&gt;serverInfo) {
            $serverInfo = $this-&gt;serverInfo;
        } else {
            $query      = 'SELECT @@VERSION';
            $serverInfo = $this-&gt;fetchOne($query);
        }
        // cache server_info
        $this-&gt;serverInfo = $serverInfo;
        if ( ! $native) {
            if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $serverInfo, $tmp)) {
                $serverInfo = array(
                    'major' =&gt; $tmp[1],
                    'minor' =&gt; $tmp[2],
                    'patch' =&gt; $tmp[3],
                    'extra' =&gt; null,
                    'native' =&gt; $serverInfo,
                );
            } else {
                $serverInfo = array(
                    'major' =&gt; null,
                    'minor' =&gt; null,
                    'patch' =&gt; null,
                    'extra' =&gt; null,
                    'native' =&gt; $serverInfo,
                );
            }
        }
        return $serverInfo;
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2010/09/16/doctrine-1-2-mssql-alternative-limitpaging/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2010/09/16/doctrine-1-2-mssql-alternative-limitpaging/</feedburner:origLink></item>
		<item>
		<title>Netbeans Code Completion and your Zend_View</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/r8RLn1h25J0/</link>
		<comments>http://www.toosweettobesour.com/2010/05/11/netbeans-code-completion-and-your-zend_view/#comments</comments>
		<pubDate>Tue, 11 May 2010 16:18:38 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Netbeans]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_View]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=472</guid>
		<description><![CDATA[Oh, look at me, blogging again! I definitely have a lot to blog about as I get the time, I&#8217;m coming off of a really involved project and learned a lot of tips I&#8217;d like to share about the Zend Framework. In the mean time I thought I&#8217;d share something I had a helluva time [...]]]></description>
				<content:encoded><![CDATA[<p>Oh, look at me, blogging again! I definitely have a lot to blog about as I get the time, I&#8217;m coming off of a really involved project and learned a lot of tips I&#8217;d like to share about the Zend Framework. In the mean time I thought I&#8217;d share something I had a helluva time figuring out.</p>
<p>If you&#8217;re using Zend Framework and NetBeans, you may be like me and bemoaning the lack of code completion in your Zend Views. As you may know, essentially what Zend_View does is includes your view within a method that belongs to a Zend_View object. This gives your view some nice variable encapsulation as well as access to the <code>$this</code> object (which is how Zend_View provides access to all the ViewHelpers and other functions).</p>
<p>Unfortunately NetBeans can&#8217;t figures this out (such is the problem with static analysis on a dynamic language) without help. If you&#8217;ve been using NetBeans and its code completion you&#8217;ll have already noticed that the PHPDocumentor syntax for <code>@var</code> or <code>@return</code> is how NetBeans figures out much of its code completion information, but that syntax doesn&#8217;t work in a view script.</p>
<p>Thanks to <a href="http://www.tiplite.com/useful-netbeans-6-8-php-tips/">Mystic at tiplite.com</a> I now know that to have code completion in your Zend_View scripts in NetBeans, add the following to the top of your view script:</p>
<pre name="code" class="php">&lt;?php
/* @var $this Zend_View */
?&gt;
</pre>
<p>Obviously if you&#8217;re using custom Zend_View objects you can pass in their class name instead.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2010/05/11/netbeans-code-completion-and-your-zend_view/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2010/05/11/netbeans-code-completion-and-your-zend_view/</feedburner:origLink></item>
		<item>
		<title>Python PHPSerialize Posted To Googlecode</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/-sVm-r3_d10/</link>
		<comments>http://www.toosweettobesour.com/2009/10/20/python-phpserialize-posted-to-googlecode/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 23:36:51 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Serialization]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=464</guid>
		<description><![CDATA[A while back I posted a Python snippet that I noticed could be used in a few other side projects. I have since posted it to Google Code so more than just myself will know it exists: http://code.google.com/p/phpserialize/.]]></description>
				<content:encoded><![CDATA[<p>A while back I posted a Python snippet that I noticed could be used in a few other side projects. I have since posted it to Google Code so more than just myself will know it exists: <a href="http://code.google.com/p/phpserialize/">http://code.google.com/p/phpserialize/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2009/10/20/python-phpserialize-posted-to-googlecode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2009/10/20/python-phpserialize-posted-to-googlecode/</feedburner:origLink></item>
		<item>
		<title>Doctrine Migrations Proper</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/5dobxPkiwqg/</link>
		<comments>http://www.toosweettobesour.com/2009/10/20/doctrine-migrations-proper/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 23:32:40 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[zendcon09]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=462</guid>
		<description><![CDATA[I was talking with someone (I will edit this post when I find her card and remember her name) here at ZendCon and discovered that they were having trouble with migrations in Doctrine. Having gone through the same issues of Doctrine seemingly not being able to figure out your changes and generate migration classes, I [...]]]></description>
				<content:encoded><![CDATA[<p>I was talking with someone (I will edit this post when I find her card and remember her name) here at ZendCon and discovered that they were having trouble with migrations in Doctrine. Having gone through the same issues of Doctrine seemingly not being able to figure out your changes and generate migration classes, I thought I&#8217;d post the solution here for future reference.</p>
<p>Assuming you have access to the Doctrine CLI tool, the sequence you need is:</p>
<ol>
<li>Make the changes to your YAML schema files</li>
<li>Run <code>$ doctrine generate-migrations-diff</code> to generate the migration deltas</li>
<li>Run <code>$ doctrine migrate</code> to determine if your migration deltas are working (a concern if you&#8217;re using SQL Server)</li>
<li>Run <code>$ doctrine generate-models-yaml</code> to update your models to reflect the status of your database</li>
</ol>
<p>The reasoning behind this, and if I&#8217;m wrong someone can correct me, is the &#8220;generate-migrations-diff&#8221; task compares the differences between your YAML schema files and your current <strong>models</strong>. If you have updated your models before generating the diff, obviously Doctrine will find no difference and generate no migration delta.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2009/10/20/doctrine-migrations-proper/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2009/10/20/doctrine-migrations-proper/</feedburner:origLink></item>
		<item>
		<title>Make The Most Of ZendCon</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/UfE9oYHTQYQ/</link>
		<comments>http://www.toosweettobesour.com/2009/10/16/make-the-most-of-zendcon/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 06:43:12 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPC]]></category>
		<category><![CDATA[zendcon09]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=459</guid>
		<description><![CDATA[I felt like I should take a break from finishing up my multi-part javascript series to rehash some points being made recently by Keith Casey and Chris Cornutt about making the most of your N-th conference (and in particular, ZendCon). My first ever professional conference (ignoring BarCamps) was last year&#8217;s ZendCon. I showed up in [...]]]></description>
				<content:encoded><![CDATA[<p>I felt like I should take a break from finishing up my <a href="http://www.toosweettobesour.com/2009/10/13/solve-a-sliding-puzzle-with-javascript-and-your-ai-course-part-1/">multi-part javascript series</a> to rehash some points being made recently by <a href="http://caseysoftware.com/blog/so-its-your-first-conference">Keith Casey</a> and <a href="http://blog.phpdeveloper.org/?p=221">Chris Cornutt</a> about making the most of your N-th conference (and in particular, ZendCon).</p>
<p>My first ever professional conference (ignoring BarCamps) was last year&#8217;s ZendCon. I showed up in Santa Clara not knowing anyone except for a few brief appearances on #phpc (freenode).</p>
<p>What made ZendCon absolutely enjoyable was indeed what everyone is suggesting to you: the hallway track. </p>
<p>I could have easily attended sessions then hid in my room until the next day, yet I chose to go out to the social events and thanks to that decision, ZendCon &#8217;08 remains currently one of my fondest memories.</p>
<p>It&#8217;s one thing to sit down and listen to talks from famous PHP developers, those that I read about all the time (or read their books in many cases). It&#8217;s a whole other beast to find yourself sharing a beer with them in some random &#8220;English Pub&#8221; while getting your ass kicked at trivia (I still have the beer glasses that were given to me by the real winners).</p>
<p>And these events didn&#8217;t happen because I&#8217;m some modest uber-genius (I am by no means modest), I&#8217;m famous, or even particularly well respected (&#8220;He&#8217;s not stupid&#8221; is as gracious as a comment as I could want in a programming community).</p>
<p>They happened because someone yelled &#8220;Pub Crawl!&#8221; and, dammit, I was there.</p>
<p>They happened because I struck up conversations with random people.</p>
<p>They happened because I got in religious flame wars with random people. (Ask me about the time, thought not at ZendCon, where I launched into a tirade against CakePHP with who I later found out was the founder of CakePHP)</p>
<p>As it has been reiterated time and time again, this conference is not really about the sessions (it&#8217;s a success if there&#8217;s just 1 talk that you go to). It&#8217;s about the people you meet and the friendships you foster.</p>
<p>In summation, I have a list of goals for you, my loyal readers that are attending ZendCon:</p>
<ol>
<li>Start a conversation with a random person in a hallway</li>
<li>Find and say hi to an author of one your PHP books. Tell them how awesome the book has been</li>
<li>Attend at least 1 UnCon session</li>
<li>Attend at least 1 post-session social (keep track on Twitter and ask your fellow attendees for info)</li>
<li>Find me and introduce yourself</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2009/10/16/make-the-most-of-zendcon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2009/10/16/make-the-most-of-zendcon/</feedburner:origLink></item>
		<item>
		<title>Solve A Sliding Puzzle With JavaScript And Your AI Course: Part 1</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/LR2dKPbt4-Y/</link>
		<comments>http://www.toosweettobesour.com/2009/10/13/solve-a-sliding-puzzle-with-javascript-and-your-ai-course-part-1/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 22:06:27 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[ai]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=456</guid>
		<description><![CDATA[In all my years of web development and formal computer science training, you know I never really got around to truly sitting down and learning JavaScript. Sure I knew the syntax (C based, not terribly hard), understood closures (LISP will do that to you), understood the prototype approach to Object Orientation (oddly enough playing with [...]]]></description>
				<content:encoded><![CDATA[<p>In all my years of web development and formal computer science training, you know I never really got around to truly sitting down and learning JavaScript.</p>
<p>Sure I knew the syntax (C based, not terribly hard), understood closures (LISP will do that to you), understood the prototype approach to Object Orientation (oddly enough playing with Python caused it to finally click).</p>
<p>Well <a href="http://thedailywtf.com/Articles/Sliding-Around.aspx">around a month ago</a> <a href="http://thedailywtf.com">The Daily WTF</a> posted one of their weekly programming puzzles.</p>
<p>Lo and behold, it&#8217;s the classic &#8220;Eight Puzzle&#8221; that I had to solve in LISP using several different algorithms!</p>
<p>Feeling particular motivated I decided to finally get around to really learning JavaScript (by learning I mean really knowing the language inside and out, like I know PHP and to a lesser extent Python).</p>
<p>The first thing I had to tackle was: Which algorithm would I choose? There are several to choose from, DFS (depth-first search), BFS (breadth-first search), Greedy, what have you. Well, a testament to my schooling, I do remember the most optimal I could remember was the <strong>A*</strong> algorithm.</p>
<p>The A* not terribly complex once you look at it properly. Most examples discuss the A*, like most navigation algorithms, as a tree structure which, while academically correct, never actually touches a tree data structure.</p>
<p>The A* algorithm works by examining the current node, the possible exit directions, and how much closer the new states after exit bring you to your goal. It arranges these new nodes in a priority queue and recurses on all the new nodes until such time that the current node is the goal node.</p>
<p>In simpler terms: examine the paths that bring you closer to the goal first.</p>
<p>The Eight-Puzzle is an excellent situation in which to first play with this algorithm as all the pieces we need for the algorithm are easy to conceptualize. It&#8217;s just a very simple navigation puzzle: How do we move the blank spot to it&#8217;s final destination (and making sure the other pieces are set too).</p>
<p>By pieces we need for the A* algorithm, I mean:</p>
<ul>
<li><strong>Heuristic</strong> (or &#8220;weight&#8221; of a current path, how far are we from the goal, etc.)</li>
<li><strong>Expansion Function</strong> (from our current node, what are the paths we can take?)</li>
</ul>
<p>The Expansion function is easy. It&#8217;s literally which way can you move the blank spot. If you&#8217;re in the exact center of the board, the expansion function will return UP, RIGHT, DOWN, LEFT. If you&#8217;re in the top left hand corner, the expansion function will return RIGHT, DOWN.</p>
<p>The Heuristic is a little trickier. If we knew the exact distance (number of moves) a certain state in the puzzle is to the finish, we would need a searching algorithm. Instead we estimate (hence this value being called a heuristic).</p>
<p>2 decent estimations would be counting the number of tiles that are not in their final position as well as calculating the <a href="http://en.wikipedia.org/wiki/Taxicab_geometry">manhattan distance</a> between the blank space and it&#8217;s final spot. The manhattan distance is the actual &#8220;walking&#8221; distance as opposed to the straight line distance. Think of the grid street system that is famously used in New York City. While drawing a line from point A to point B may be 2.5<em>ish</em> miles, in reality you walk maybe 4 miles as you must walk north about 2 miles and east about 2 miles.</p>
<p>Even better is combining the two values. As excellent as manhattan distance sounds for an estimation, you run into inconsistencies like an unsolved board where the blank spot is in the correct position being given more weight in searching than a board 1 step away from being solved with the blank spot only 1 block away from the correct (and final) position.</p>
<p>In Part 2 I will step away from the algorithm and step into JavaScript to build our basic utility function (namely creating and managing a board).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2009/10/13/solve-a-sliding-puzzle-with-javascript-and-your-ai-course-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2009/10/13/solve-a-sliding-puzzle-with-javascript-and-your-ai-course-part-1/</feedburner:origLink></item>
		<item>
		<title>Development Environment Help! Setting Up PHP mail() On Windows, Or: Where Is My Windows sendmail.exe?</title>
		<link>http://feedproxy.google.com/~r/toosweettobesour/HrtK/~3/BjuN1jOJ4lE/</link>
		<comments>http://www.toosweettobesour.com/2009/08/21/development-environment-help-setting-up-php-mail-on-windows-or-where-is-my-windows-sendmail-exe/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 16:39:00 +0000</pubDate>
		<dc:creator>Daniel Cousineau</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[hMailServer]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php.ini]]></category>
		<category><![CDATA[SMTP]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.toosweettobesour.com/?p=439</guid>
		<description><![CDATA[Lately at work I&#8217;ve been having the worst of trouble getting PHP on my workstation to send mail. Previously it was a simple trek to a website to download a Windows build of sendmail.exe, but for some reason I cannot get access to it, so I have to go another route. Enter hMailServer, a free, [...]]]></description>
				<content:encoded><![CDATA[<p>Lately at work I&#8217;ve been having the worst of trouble getting PHP on my workstation to send mail. Previously it was a simple trek to a website to download a Windows build of sendmail.exe, but for some reason I cannot get access to it, so I have to go another route.</p>
<p>Enter <a href="http://www.hmailserver.com/">hMailServer</a>, a free, full-featured SMTP/POP/IMAP server for Windows with a pretty, shiny GUI configuration interface. All I really want to do is setup SMTP for localhost only but one could easily use hMailServer as a production mail server.</p>
<p>To start things off, lets make sure our php.ini directives are setup correctly. By correct, I mean PHP needs to be looking for our SMTP server on my local machine (localhost) at the default SMTP port (25), and, just in case, set a default from address:</p>
<pre name="code" class="ini">
[mail function]
; For Win32 only.
smtp = localhost
smtp_port = 25

; For Win32 only.
sendmail_from = user@domain.tld
</pre>
<p>Looks good. Second step is to download and install hMailServer. This tutorial is working from <a href="http://www.hmailserver.com/?page=download_mirrors&#038;downloadid=185">version 5.2 build 356</a>, but you should be able to use the latest stable or unstable version that you might desire.</p>
<p>Once you&#8217;re installed and configured, run the administrative application. If you click over to status you will notice a message to the effect of &#8220;You haven&#8217;t specified the public host name for this computer in the SMTP settings.&#8221; That means we have some more configuration to do!</p>
<p><img src="http://www.toosweettobesour.com/wp-content/uploads/2009/08/hmailserver-1.png" alt="hMailServer Screenshot 1" title="hMailServer Screenshot 1" width="818" height="600" class="aligncenter size-full wp-image-440" /></p>
<p>Now mosey on over to Settings &raquo; Protocols &raquo; SMTP, navigate to the &#8220;Delivery of e-mail&#8221; tab. We set our &#8220;Local host name&#8221; to &#8220;localhost&#8221; and click &#8220;Save&#8221;.</p>
<p><img src="http://www.toosweettobesour.com/wp-content/uploads/2009/08/hmailserver-2.png" alt="hMailServer Screenshot 2" title="hMailServer Screenshot 2" width="818" height="600" class="aligncenter size-full wp-image-442" /></p>
<p>Next, for securities sake (as well as to ensure we don&#8217;t have to waste time configuring account as this is only a dev machine), go to Settings &raquo; Advanced &raquo; IP Ranges &raquo; My Computer. Un-check the POP3 and IMAP checkboxes under the &#8220;Allow Connections&#8221; as we don&#8217;t intend to receive mail, nor use the IMAP protocol. Then, un-check everything under &#8220;Requires SMTP authentication&#8221; as we want our PHP applications to have full reign. Finally, click &#8220;Save&#8221;. Remember, this is a dev box.</p>
<p><img src="http://www.toosweettobesour.com/wp-content/uploads/2009/08/hmailserver-3.PNG" alt="hMailServer Screenshot 3" title="hMailServer Screenshot 3" width="818" height="600" class="aligncenter size-full wp-image-443" /></p>
<p>UNDER NO CIRCUMSTANCES SHOULD YOU USE THESE SETTINGS ON A BOX THAT WILL BE EXPOSING ITSELF TO THE INTERNET OR ON A PRODUCTION SERVER! However, since our local machine will obviously have internet connectivity, lets remove all access from outsiders!</p>
<p>Navigate to Settings &raquo; Advanced &raquo; IP Ranges &raquo; Internet. Un-check EVERYTHING from &#8220;Allow connections&#8221; to deny outsiders any services, and, just in case, check EVERYTHING under &#8220;Require SMTP authentication&#8221;  and click &#8220;Save&#8221;.</p>
<p><img src="http://www.toosweettobesour.com/wp-content/uploads/2009/08/hmailserver-4.PNG" alt="hMailServer Screenshot 4" title="hMailServer Screenshot 4" width="818" height="600" class="aligncenter size-full wp-image-444" /></p>
<p>And <em>voilà</em>! We have a fully functioning SMTP server that our local PHP environment can use to send test email messages.</p>
<p>The nice thing about our administrative interface is if we go to Status, navigate to the &#8220;Logging&#8221; tab, and click &#8220;Start,&#8221; we can capture the dialogue between hMailServer and your PHP app when sending an email address (very useful for debugging).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.toosweettobesour.com/2009/08/21/development-environment-help-setting-up-php-mail-on-windows-or-where-is-my-windows-sendmail-exe/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.toosweettobesour.com/2009/08/21/development-environment-help-setting-up-php-mail-on-windows-or-where-is-my-windows-sendmail-exe/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.292 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-12 21:10:18 --><!-- Compression = gzip -->
