<?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>Norm 2782 &#187; PHP</title>
	<atom:link href="http://www.norm2782.com/category/programming/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.norm2782.com</link>
	<description>Why are you here?</description>
	<lastBuildDate>Sat, 07 Mar 2009 08:03:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Properties in PHP &#8211; revisited</title>
		<link>http://www.norm2782.com/2009/01/properties-in-php-revisited/</link>
		<comments>http://www.norm2782.com/2009/01/properties-in-php-revisited/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 10:47:25 +0000</pubDate>
		<dc:creator>norm2782</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Proof-of-concepts]]></category>

		<guid isPermaLink="false">http://www.norm2782.com/?p=94</guid>
		<description><![CDATA[A while ago I was daydreaming about native property support in PHP. Unfortunately it will be a while before PHP itself will support this natively and an even longer while before shared hosting providers will upgrade to a newer version of PHP. So what&#8217;s the big deal about those properties? In short, they make a [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I was daydreaming about native <a href="http://www.norm2782.com/2009/01/properties-in-php/">property support in PHP</a>. Unfortunately it will be a while before PHP itself will support this natively and an even longer while before shared hosting providers will upgrade to a newer version of PHP.</p>
<p>So what&#8217;s the big deal about those properties? In short, they make a developers life easier by allowing the developer to code no more than needed at that moment. And lets face it&#8230; less code is better! In this post we&#8217;ll see that it&#8217;s not impossible to enjoy properties in PHP <em>today</em>. As with a lot of good things, it does come with a small price though&#8230;</p>
<p><span id="more-94"></span><br />
Lets have a look at a use-case to demonstrate where properties will not only save you time, but it will also save your sanity. In this example we&#8217;re modeling a Person class. In the beginning of the project, the requirements for the Person class are quite simple: a Person has an age and a name. In the simplest form we can code that as follows:</p>
<pre name="code" class="php:nogutter">
&lt;?php
class Person
{
    public $age;

    public $name;
}
</pre>
<p>This look easy enough, and it is. It even works like a charm and it&#8217;s possibly the fastest implementation for the Person class.</p>
<p>But, pesky as they are, the client suddenly wants some logic added to our Person class! A Person suddenly can&#8217;t be younger than 21 years old. This poses a problem. To add logic to our Person class, we would have to switch the public age attribute with a pair of getters and setters:</p>
<pre name="code" class="php:nogutter">
&lt;?php
class Person
{
    private $_age = null;

    public $name = null;

    public function getAge()
    {
        return $this-&gt;_age;
    }

    public function setAge($age)
    {
        if ($age &lt; 21) {
            throw new Exception('You need to be at least 21 years or older!');
        }

        $this-&gt;_age = $age;
    }
}
</pre>
<p>Technically this works like a charm, however it will force me to go through my entire application and switch all references from the public attribute to the getter and setter. Not an ideal situation. One possible solution is to do things the Java way: just create all getters and setters up-front so you don&#8217;t have to do so afterwards. Even though this works fine, it&#8217;s in violation of our mission to write no more code than we actually need at the moment of writing.</p>
<p>The solution? Properties! But wait&#8230; PHP doesn&#8217;t support those, remember? Luckily we still have magic methods. It&#8217;s nowhere near as nice as a native solution, but at least it helps us write no more code than we need at the moment we&#8217;re first writing our code:</p>
<pre name="code" class="php:nogutter">
&lt;?php
abstract class ModelAbstract
{
    public function __get($key)
    {
        $method = 'get' . ucfirst($key);

        if (!method_exists($this, $method)) {
            throw new Exception('No property found for ' . $key);
        }

        return $this-&gt;$method();
    }

    public function __set($key, $value)
    {
        $method = 'set' . ucfirst($key);

        if (!method_exists($this, $method)) {
            throw new Exception('No property found for ' . $key);
        }

        $this-&gt;$method($value);
    }
}
</pre>
<p>We&#8217;ll take a look at what this does exactly later. The important thing to note is that we can now do the following:</p>
<pre name="code" class="php:nogutter">
&lt;?php
class Person extends ModelAbstract
{
    private $_age = null;

    public $name = null;

    public function getAge()
    {
        return $this-&gt;_age;
    }

    public function setAge($age)
    {
        if ($age &lt; 21) {
            throw new Exception('You need to be at least 21 years or older!');
        }

        $this-&gt;_age = $age;
    }
}

$person = new Person();

try {
    $person-&gt;age = 10;
} catch (Exception $e) {
    // Will print "You need to be at least 21 years or older!"
    echo $e-&gt;getMessage();
}
</pre>
<p>With this construction in place, we can safely switch from a public attribute to getters and setters, without changing the rest of the application code. The only real downside to this &#8211; aside from the minor speed impact &#8211; is the fact that you have to subclass ModelAbstract to make this work. Luckily it&#8217;s not a lot of code, so should there be a big need to get rid of the ModelAbstract inheritance it&#8217;s not a big disaster to do some copy/paste work.</p>
<p>This method works by assuming you have get- and set methods that have the same name as the property you&#8217;re trying to access. When there&#8217;s a public attribute, it will use that. If there&#8217;s no public attribute, it will fall back to __get or __set and the logic will take it from there.</p>
<p>All of this is just a proof-of-concept of implementing properties in PHP and of the way I want to be using properties to access data the data in my objects. Please comment your experiences with this approach or similar approaches. I&#8217;m curious to see how practical this solution would be in a real-life situation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.norm2782.com/2009/01/properties-in-php-revisited/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Filters for Zend_Paginator</title>
		<link>http://www.norm2782.com/2009/01/filters-for-zend_paginator/</link>
		<comments>http://www.norm2782.com/2009/01/filters-for-zend_paginator/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 12:57:53 +0000</pubDate>
		<dc:creator>norm2782</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.norm2782.com/?p=72</guid>
		<description><![CDATA[Zend_Paginator has a new feature! It is now possible to add a filter to your Paginator object which acts on the data retrieved from the adapter. This filter can be any instance of Zend_Filter_Interface, including a filter-chain. If a filter(-chain) is set, the raw data from the adapter will be passed to the filter() method. [...]]]></description>
			<content:encoded><![CDATA[<p>Zend_Paginator has a new feature! It is now possible to add a filter to your Paginator object which acts on the data retrieved from the adapter. This filter can be any instance of Zend_Filter_Interface, including a filter-chain. If a filter(-chain) is set, the raw data from the adapter will be passed to the filter() method.</p>
<p><span id="more-72"></span><br />
So why would you want to apply filters to your result set? Usually my domain models don&#8217;t inherit from Zend_Db_Table_Row but that is the data type I get from the Paginator when I use the DbTableSelect adapter (wrapped in a nice Zend_Db_Table_Rowset). Instead, I would like to load my rows into my models and preferably without using the Paginator abilities or having to apply weird hacks. Previously this was only possible (in a sane way) by subclassing an adapter so it could return a collection of model objects instead of a rowset. With the new filter support you can just inject a filter to do this for you.</p>
<p>Lets have a look at an example. In this example I want to list all my users from the database. I&#8217;ll grab the name of the user from the row and inject it into a User object.</p>
<pre name="code" class="php:nogutter">
&lt;?php
class User
{
    private $_name = '';

    public function getName()
    {
        return $this-&gt;_name;
    }

    public function setName($name)
    {
        $this-&gt;_name = $name;
    }
}

class UserFilter implements Zend_Filter_Interface
{
    public function filter($rows)
    {
        $users = array();

        foreach ($rows as $row) {
            $user = new User();
            $user-&gt;setName($row-&gt;name);

            $users[] = $user;
        }

        return $rows;
    }
}

class MyModel
{
    public static function getUserPaginator()
    {
        $userTable = new UserTable();
        $paginator = Zend_Paginator::factory($userTable-&gt;select());
        $paginator-&gt;setFilter(new UserFilter());

        return $paginator;
    }
}

$paginator = MyModel::getUserPaginator();
$items = $paginator-&gt;getCurrentItems();

foreach ($items as $user) {
    echo 'Current name: ' . $user-&gt;getName() . '&lt;br /&gt;' . PHP_EOL;
}
</pre>
<p>To simplify adding a simple filter to your paginator I&#8217;ve also added Zend_Filter_Callback. This allows you to specify a callback method that does the same as the filter in the previous example.</p>
<pre name="code" class="php:nogutter">
&lt;?php
class MyModel
{
    public static function getUserPaginator()
    {
        $userTable = new UserTable();
        $paginator = Zend_Paginator::factory($userTable-&gt;select());
        $paginator-&gt;setFilter(new Zend_Filter_Callback(
            array('MyModel', 'filter'))
        );

        return $paginator;
    }

    public static function filter($rows)
    {
        $users = array();

        foreach ($rows as $row) {
            $user = new User();
            $user-&gt;setName($row-&gt;name);

            $users[] = $user;
        }

        return $rows;
    }
}
</pre>
<p>The callback also accepts object instead of a static reference to a class. Internally it uses call_user_func to execute the filter() method, so any notation that works there, works with the Callback filter.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.norm2782.com/2009/01/filters-for-zend_paginator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZF-3239</title>
		<link>http://www.norm2782.com/2009/01/zf-3239/</link>
		<comments>http://www.norm2782.com/2009/01/zf-3239/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 11:48:31 +0000</pubDate>
		<dc:creator>norm2782</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.norm2782.com/?p=68</guid>
		<description><![CDATA[Zend_Db_Table_Select users, rejoice! I&#8217;ve just committed a patch for ZF-3239 in revision 13530. This should be a relief for those of you who have been implementing workarounds for those &#8220;No table has been specified for the FROM clause&#8221; exceptions.]]></description>
			<content:encoded><![CDATA[<p>Zend_Db_Table_Select users, rejoice! I&#8217;ve just committed a patch for <a href="http://framework.zend.com/issues/browse/ZF-3239">ZF-3239</a> in revision 13530. This should be a relief for those of you who have been implementing workarounds for those &#8220;No table has been specified for the FROM clause&#8221; exceptions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.norm2782.com/2009/01/zf-3239/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AMF Server class for WordPress</title>
		<link>http://www.norm2782.com/2009/01/amf-server-class-for-wordpress/</link>
		<comments>http://www.norm2782.com/2009/01/amf-server-class-for-wordpress/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 14:49:42 +0000</pubDate>
		<dc:creator>norm2782</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.norm2782.com/?p=27</guid>
		<description><![CDATA[After browsing through WordPress&#8217; code I quickly found that there&#8217;s no sane way to create AMF support as a WP plugin. At least not for someone who hasn&#8217;t done any old-skool procedural PHP in years. Instead of writing a plugin, I decided to write a standalone server script. It&#8217;s still very basic and currently setup [...]]]></description>
			<content:encoded><![CDATA[<p>After browsing through WordPress&#8217; code I quickly found that there&#8217;s no sane way to create AMF support as a WP plugin. At least not for someone who hasn&#8217;t done any old-skool procedural PHP in years. Instead of writing a plugin, I decided to write a standalone server script. It&#8217;s still very basic and currently setup to work for me. To get it working for your WP setup you should probably make some minor modifications. Click the read more link to check out the code. I&#8217;ve released it under the generous BSD license, so knock yourself out! Use it at your own risk&#8230; I&#8217;m not going to support it. Any updates will be posted in this post. Also, please note that I haven&#8217;t tested it yet. If you access the script directly it should output &#8220;Zend Amf Endpoint&#8221; just fine, but that&#8217;s all I can guarantee at this point <img src='http://www.norm2782.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><span id="more-27"></span></p>
<pre name="code" class="php:nogutter">
&lt;?php
/**
 * BSD LICENSE
 *
 * Copyright (c) 2009, norm2782
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of norm2782 nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY norm2782 ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL norm2782 BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Set production mode.
 * If set to false, exceptions will bubble through to the Flex frontend
 *
 * @var bool
 */
$production = false;

/**
 * Determine the absolute path of the AMF server
 *
 * @var string
 */
define('ABSPATH', dirname(__FILE__) . '/');

/**
 * One directory below docroot. Your config file and library dir should be here.
 *
 * @var string
 */
define('SUBPATH', dirname(ABSPATH));

/**
 * You should make sure Zend Framework is in your include path
 */
set_include_path(
    implode(PATH_SEPARATOR, array(
        SUBPATH . '/library',
        get_include_path()
    ))
);

/**
 * Include the WordPress config file
 */
$configFile = SUBPATH . '/wp-config.php';

if (!file_exists($configFile)) {
    throw new Exception('WordPress config file was not found!');
}

require_once $configFile;

/**
 * No need to config more stuff from this point on
 */

/**
 * @see Zend_Amf_Server
 */
require_once 'Zend/Amf/Server.php';

/**
 * @see Zend_Db_Adapter_Pdo_Mysql
 */
require_once 'Zend/Db/Adapter/Pdo/Mysql.php';

/**
 * @see Zend_Paginator
 */
require_once 'Zend/Paginator.php';

/**
 * @see Zend_Paginator_Adapter_DbSelect
 */
require_once 'Zend/Paginator/Adapter/DbSelect.php';

/**
 * Simple class to expose wordpress data through AMF
 *
 * @author norm2782
 */
class Wp_Amf_Gateway
{
    /**
     * Database adapter
     *
     * @var Zend_Db_Adapter_Pdo_Mysql
     */
    private $_db = null;

    /**
     * WordPress table prefix
     *
     * @var string
     */
    private $_prefix = null;

    /**
     * Constructor
     *
     * @param array $dbConfig
     * @param string $prefix
     * @return void
     */
    public function __construct(array $dbConfig, $prefix)
    {
        $this-&gt;_db = new Zend_Db_Adapter_Pdo_Mysql($dbConfig);
        $this-&gt;_db-&gt;query('SET NAMES `utf8`');

        $this-&gt;_prefix = $prefix;
    }

    /**
     * Get paginated results for the provided query
     *
     * @param Zend_Db_Select $select
     * @param int $page
     * @param int $itemsPerPage
     * @return array
     */
    private function _getPaginated(Zend_Db_Select $select, $page, $itemsPerPage)
    {
        $paginator = new Zend_Paginator(
            new Zend_Paginator_Adapter_DbSelect($select)
        );

        $paginator-&gt;setCurrentPageNumber($page)
                  -&gt;setItemCountPerPage($itemsPerPage);

        return array(
            'info'  =&gt; $paginator-&gt;getPages(),
            'items' =&gt; $paginator-&gt;getCurrentItems()
        );
    }

    /**
     * Get the comments for the specified post ID
     *
     * @param int $postId
     * @param int $page
     * @param int $itemsPerPage
     * @return array
     */
    public function getCommentsForPost($postId, $page = 1, $itemsPerPage = 10)
    {
        $select = $this-&gt;_db-&gt;select()-&gt;from($this-&gt;_prefix . 'comments')
                                      -&gt;where('comment_post_ID = ?', $postId);

        return $this-&gt;_getPaginated($select, $page, $itemsPerPage);
    }

    /**
     * Get the meta data for the specified post ID
     *
     * @param $postId
     * @return unknown_type
     */
    public function getMetaForPost($postId)
    {
        $select = $this-&gt;_db-&gt;select()-&gt;from($this-&gt;_prefix . 'postmeta')
                                      -&gt;where('post_id = ?', $postId);

        return $this-&gt;_db-&gt;fetchAll($select);
    }

    /**
     * Get a post by specifying its ID
     *
     * @param int $postId
     * @return array
     */
    public function getPost($postId)
    {
        $select = $this-&gt;_db-&gt;select()-&gt;from($this-&gt;_prefix . 'posts')
                                      -&gt;where('ID = ?', $postId);

        return $this-&gt;_db-&gt;fetchOne($select);
    }

    /**
     * Get posts per page
     *
     * @param int $page
     * @param int $itemsPerPage
     * @return array
     */
    public function getPosts($page = 1, $itemsPerPage = 10)
    {
        $select = $this-&gt;_db-&gt;select()-&gt;from($this-&gt;_prefix . 'posts');

        return $this-&gt;_getPaginated($select, $page, $itemsPerPage);
    }
}

/**
 * Pass the values from wp-config.php to the Wp_Amf_Gateway class.
 */
$gateway = new Wp_Amf_Gateway(
    array(
        'host'     =&gt; DB_HOST,
        'username' =&gt; DB_USER,
        'password' =&gt; DB_PASSWORD,
        'dbname'   =&gt; DB_NAME
    ),
    $table_prefix
);

$server = new Zend_Amf_Server();
$server-&gt;setProduction($production)
       -&gt;setClass($gateway)
       -&gt;handle();
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.norm2782.com/2009/01/amf-server-class-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Flex frontend</title>
		<link>http://www.norm2782.com/2009/01/flex-frontend/</link>
		<comments>http://www.norm2782.com/2009/01/flex-frontend/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 23:29:35 +0000</pubDate>
		<dc:creator>norm2782</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.norm2782.com/?p=22</guid>
		<description><![CDATA[I was planning on writing a quick Flex frontend for this blog, but it appears WordPress only offers the posts themselves as RSS feed. If I get real bored (which I doubt, unfortunately) I&#8217;ll have a look and see if I can create a Zend_AMF plugin for WordPress that allows me to retrieve virtually all [...]]]></description>
			<content:encoded><![CDATA[<p>I was planning on writing a quick Flex frontend for this blog, but it appears WordPress only offers the posts themselves as RSS feed. If I get real bored (which I doubt,  unfortunately) I&#8217;ll have a look and see if I can create a Zend_AMF plugin for WordPress that allows me to retrieve virtually all data from my WordPress install. Would be cool <img src='http://www.norm2782.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.norm2782.com/2009/01/flex-frontend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Properties in PHP</title>
		<link>http://www.norm2782.com/2009/01/properties-in-php/</link>
		<comments>http://www.norm2782.com/2009/01/properties-in-php/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 23:02:54 +0000</pubDate>
		<dc:creator>norm2782</dc:creator>
				<category><![CDATA[Daydreaming]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.norm2782.com/?p=8</guid>
		<description><![CDATA[A while ago Dynom from #php_bnl pointed me to an interesting entry on the PHP 5.3 wiki page. In the &#8220;Future PHP releases&#8221; sections there&#8217;s an entry called &#8220;29. “real” properties with attached getters and setters&#8221;. Personally I can&#8217;t wait for this. Hopefully it will look something like ActionScript 3&#8242;s properties: &#60;?php class Bar { [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago Dynom from #php_bnl pointed me to an interesting entry on the <a title="PHP 5.3 wiki page" href="http://wiki.php.net/todo/php53">PHP 5.3 wiki page</a>. In the &#8220;Future PHP releases&#8221; sections there&#8217;s an entry called &#8220;29. “real” properties with attached getters and setters&#8221;. Personally I can&#8217;t wait for this. Hopefully it will look something like ActionScript 3&#8242;s properties:</p>
<pre name="code" class="php:nogutter">
&lt;?php
class Bar
{
    private $_foo = 'foo';

    public function get foo()
    {
        return $this->_foo;
    }

    public function set foo($fooString)
    {
        $this->_foo = $fooString;
    }
}

$bar = new Bar();
$bar->foo = 'baz';
echo $bar->foo; // prints baz
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.norm2782.com/2009/01/properties-in-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
