<?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>PHP in Action &#187; Object-Oriented</title>
	<atom:link href="http://blog.agilephp.com/tag/object-oriented/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.agilephp.com</link>
	<description>Dagfinn Reiersøl on PHP, agile development, Ruby and other addictive substances</description>
	<lastBuildDate>Mon, 28 Sep 2009 14:35:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Real programming with PHP 5.3 (part 4): A more realistic example</title>
		<link>http://blog.agilephp.com/2009/06/02/real-programming-with-php-53-part-4-a-more-realistic-example/</link>
		<comments>http://blog.agilephp.com/2009/06/02/real-programming-with-php-53-part-4-a-more-realistic-example/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 21:12:54 +0000</pubDate>
		<dc:creator>dagfinn</dc:creator>
				<category><![CDATA[JavaScript/Ajax]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP 5.3]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Object-Oriented]]></category>

		<guid isPermaLink="false">http://blog.agilephp.com/?p=1580</guid>
		<description><![CDATA[



Image by hartboy via Flickr



My previous example in part 2 was just &#8220;hello world&#8221;, so I&#8217;m going to try for something more like the real world. You may find this example unusual, but it does work. I took the PageRange class I used in my July 2007 php&#124;architect article and converted it to the JavaScript [...]]]></description>
			<content:encoded><![CDATA[<div class="zemanta-img" style="margin: 1em; display: block;">
<div>
<dl class="wp-caption alignleft">
<dt class="wp-caption-dt"><a href="http://www.flickr.com/photos/26013750@N00/2801578749"><img src="http://farm4.static.flickr.com/3162/2801578749_4768ccc57f_m.jpg" alt="Let's be realistic" title="Let's be realistic"></a></dt>
<dd class="wp-caption-dd zemanta-img-attribution" style="font-size: 0.8em;">Image by <a href="http://www.flickr.com/photos/26013750@N00/2801578749">hartboy</a> via Flickr</dd>
</dl>
</div>
</div>
<p>My previous example in <a href="http://blog.agilephp.com/2009/03/31/real-programming-with-php-53-part-2-javascript-style-classes/">part 2</a> was just &#8220;hello world&#8221;, so I&#8217;m going to try for something more like the real world. You may find this example unusual, but it does work. I took the PageRange class I used in my <a href="http://phparch.com/c/magazine/issue/56">July 2007 php|architect</a> article and converted it to the JavaScript style. The class is a variation on Martin Fowler&#8217;s Range pattern, and is the hub of a re-implementation of the main functionality of PEAR Pager, using a more object-oriented style.</p>
<p>A Range object is defined by just two values (three in my variation), so it might seem like too much to have an object just to keep these values, but as you can see from the example, a Range class can have behaviors to change and compare ranges.</p>
<p>As before, I&#8217;m defining most of the methods inside the constructor.</p>
<pre class="brush: php">
&lt;?php
class PageRange {
    public $start;
    public $end;
    public $length;

    private $moveToStartAt;
    private $moveToEndAt;
    private $changeLengthToEndAt;
    private $includes;
    private $isInside;
    private $extendsBeyondStartOf;
    private $extendsBeyondEndOf;
    private $truncateToFitInside;
    private $moveToFitInside;
    private $asArray;

    public function __construct($start,$end,$length) {
        $self = $this;
        $this-&gt;start = $start;
        $this-&gt;end = $end;
        $this-&gt;length = $length;

        $this-&gt;moveToStartAt = function($start) use ($self) {
            return PageRange::withStartAndLength(
                $start,$self-&gt;length);
        };

        $this-&gt;moveToEndAt = function($end) use ($self) {
            return PageRange::withEndAndLength($end,$self-&gt;length);
        };

        $this-&gt;changeLengthToEndAt = function($end) use ($self) {
            return PageRange::withStartAndEnd($self-&gt;start,$end);
        };

        // Comparisons

        $this-&gt;includes = function($page) use ($self) {
            return $page &gt;= $self-&gt;start
                &amp;&amp; $page &lt;= $self-&gt;end;
        };

        $this-&gt;isInside = function($range) use ($self) {
            return $range-&gt;includes($self-&gt;getStart())
                &amp;&amp; $range-&gt;includes($self-&gt;getEnd());
        };

        $this-&gt;extendsBeyondStartOf = function(PageRange $range) use ($self) {
            return ($self-&gt;getStart() &lt; $range-&gt;getStart());
        };

        $this-&gt;extendsBeyondEndOf = function(PageRange $range) use ($self) {
            return ($self-&gt;getEnd() &gt; $range-&gt;getEnd());
        };

        // Changes

        $this-&gt;truncateToFitInside = function(PageRange $larger) use ($self) {
            if ($self-&gt;isInside($larger)) return clone $self;
            return $self-&gt;changeLengthToEndAt(
                $larger-&gt;getEnd());
        };

        $this-&gt;moveToFitInside = function(PageRange $larger) use ($self) {
            if ($self-&gt;isInside($larger)) return clone $self;
            if ($self-&gt;extendsBeyondEndOf($larger))
                return $self-&gt;moveToEndAt($larger-&gt;getEnd());
            if ($self-&gt;extendsBeyondStartOf($larger))
                return $self-&gt;moveToStartAt(
                    $larger-&gt;getStart());
        };

        // Convert to array

        $this-&gt;asArray = function() use ($self) {
            return range($self-&gt;start,$self-&gt;end);
        };

    }
</pre>
<p>I&#8217;ve defined the static methods in the usual way, non-JavaScript style. And there is, of course, the mandatory __call() method.</p>
<pre class="brush: php">
class PageRange...

    public function __call($method,$args) {
        return call_user_func_array($this-&gt;$method,$args);
    }

    public function getStart() { return $this-&gt;start; }

    public function getEnd() { return $this-&gt;end; }

    public function getLength() { return $this-&gt;length; }

    private static function calculateEnd($start,$length) {
        return $start + $length - 1;
    }

    private static function calculateStart($end,$length) {
        return $end - $length + 1;
    }

    private static function calculateLength($start,$end) {
        return $end - $start + 1;
    }

    public static function withStartAndLength(
        $start,$length)
    {
        return new self(
            $start,
            self::calculateEnd($start,$length),
            $length
        );
    }

    public static function withEndAndLength($end,$length) {
        return new self(
            self::calculateStart($end,$length),
            $end,
            $length
        );
    }

    public static function withStartAndEnd($start,$end) {
        return new self(
            $start,
            $end,
            self::calculateLength($start,$end)
        );
    }

}
</pre>
<p>An interesting aspect of this class is the fact that the constructor is private, so you have to use one of the creation methods. That&#8217;s part of my variation on the range pattern.</p>
<p class="addtoany_share_save_container">
    <a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?sitename=PHP%20in%20Action&amp;siteurl=http%3A%2F%2Fblog.agilephp.com%2F&amp;linkname=Real%20programming%20with%20PHP%205.3%20%28part%204%29%3A%20A%20more%20realistic%20example&amp;linkurl=http%3A%2F%2Fblog.agilephp.com%2F2009%2F06%2F02%2Freal-programming-with-php-53-part-4-a-more-realistic-example%2F"><img src="http://blog.agilephp.com/wp-content/plugins/add-to-any/share_save_256_24.png" width="256" height="24" alt="Share/Save/Bookmark"/></a>

	</p>]]></content:encoded>
			<wfw:commentRss>http://blog.agilephp.com/2009/06/02/real-programming-with-php-53-part-4-a-more-realistic-example/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
