<?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>Syntactic sugar &#187; OOP</title>
	<atom:link href="http://syntacticsugar.nl/category/oop/feed/" rel="self" type="application/rss+xml" />
	<link>http://syntacticsugar.nl</link>
	<description>Random ramblings of another web-techy</description>
	<lastBuildDate>Sat, 09 Jan 2010 21:24:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Finally : a new Crudder-release!</title>
		<link>http://syntacticsugar.nl/2009/11/28/finally-a-new-crudder-release/</link>
		<comments>http://syntacticsugar.nl/2009/11/28/finally-a-new-crudder-release/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 12:02:06 +0000</pubDate>
		<dc:creator>buTTon</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[CRUD]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[PHP-Scaffold]]></category>
		<category><![CDATA[Scaffold]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://syntacticsugar.nl/?p=296</guid>
		<description><![CDATA[It took a while.. a long while actually.. but I finally made a new release of Crudder. This new release 0.50 has a lot of new features and bugfixes, to name a few;

New Field-type: HTML-editor
New Field-type: File-upload
New Field-type: Enum
Export to CSV
Adding records from the many-2-many-editor
Bugfixes; language-support works better, datefield has been fixed, the many-2-many-editor should [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_297" class="wp-caption alignright" style="width: 160px"><a href="http://syntacticsugar.nl/wp-content/uploads/2009/11/screenshot_001.png"><img class="size-thumbnail wp-image-297" title="screenshot_001" src="http://syntacticsugar.nl/wp-content/uploads/2009/11/screenshot_001-150x150.png" alt="Crudder in action" width="150" height="150" /></a><p class="wp-caption-text">Crudder in action</p></div>
<p>It took a while.. a long while actually.. but I finally made a new release of <a href="http://syntacticsugar.nl/crudder/">Crudder</a>. This new release 0.50 has a lot of new features and bugfixes, to name a few;</p>
<ul>
<li>New Field-type: HTML-editor</li>
<li>New Field-type: File-upload</li>
<li>New Field-type: Enum</li>
<li>Export to CSV</li>
<li>Adding records from the many-2-many-editor</li>
<li>Bugfixes; language-support works better, datefield has been fixed, the many-2-many-editor should work better</li>
</ul>
<p><a href="http://www.crudder.net/demo.php" target="_blank">Check out the DEMO</a> or <a href="http://syntacticsugar.nl/crudder/">read more</a></p>
]]></content:encoded>
			<wfw:commentRss>http://syntacticsugar.nl/2009/11/28/finally-a-new-crudder-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Launched a new WPS-Demo website</title>
		<link>http://syntacticsugar.nl/2009/10/17/launched-a-new-wps-demo-website/</link>
		<comments>http://syntacticsugar.nl/2009/10/17/launched-a-new-wps-demo-website/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 16:12:05 +0000</pubDate>
		<dc:creator>buTTon</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[Content Publishing]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WPS]]></category>
		<category><![CDATA[Content Management]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[Joomla]]></category>
		<category><![CDATA[Website Publication]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://syntacticsugar.nl/?p=266</guid>
		<description><![CDATA[For the dutchies , english folks check this page;
Op http://wps.i-v-o.nl/ staat sinds vandaag een vernieuwde demo-website van WPS.  Met deze demo-website kan je lezen over wat WPS is, wat het kan, hoe het werkt en je kan spelen met het systeem.
Wat is WPS
WPS staat voor Web Publishing System. Geen spannende afkorting, maar het dekt de [...]]]></description>
			<content:encoded><![CDATA[<p>For the dutchies , english folks check <a href="http://syntacticsugar.nl/wps/">this page</a>;</p>
<p>Op <a title="WPS demo website" href="http://demo.i-v-o.nl" target="_blank">http://wps.i-v-o.nl/</a> staat sinds vandaag een vernieuwde demo-website van WPS.  Met deze demo-website kan je lezen over wat WPS is, wat het kan, hoe het werkt en je kan spelen met het systeem.</p>
<h2>Wat is WPS</h2>
<p>WPS staat voor Web Publishing System. Geen spannende afkorting, maar het dekt de lading wel goed. WPS is namelijk geen klassiek Content Management Systeem (CMS) maar veel meer. Een klassiek CMS zorgt er eigenlijk alleen maar voor dat je de inhoud van je website kunt bewerken, dat doe je dan eigenlijk altijd op een aparte website (ook wel backend genoemd). Zo&#8217;n CMS is harstikke mooi, maar er moet ook een &#8216;voorkant&#8217;, je website, geprogrammeerd worden, en dat kan best een tijdrovende klus worden. WPS is een <em>publicatiesysteem</em> en zorgt dus niet alleen voor de CMS functie, maar ook voor het publiceren; de voorkant van je website.</p>
<p><span id="more-266"></span></p>
<h2>Publicatie-systeem</h2>
<p>Er zijn gerust wel andere publicatie-systemen, bijvoorbeeld Joomla of Wordpress, maar toch heeft I-V-O de keuze gemaakt om een heel nieuw systeem te ontwikkelen. Waarom? <strong>Flexibiliteit</strong>.<br />
De meeste andere systemen zijn nogal rigide in functionaliteit of opmaak, en dan nog maar niet te spreken over veiligheid. WPS is extreem flexibel door het gebruik van XML. Alle gegevens die in WPS rondgaan worden omgezet in XML en komen in 1 groot document samen; het WPSDoc. XML is een speciale manier van gegevens opmaak die zich uitermate goed leent tot &#8216;translaties&#8217;. Stel je voor dat je een tekst hebt ingevoerd en je wilt daar een deel van dikgedrukt maken; normaliter wordt dat in html aangegeven met de b-tag. In WPS wordt dit de bold-tag, niet &#8220;b&#8221;, en bij het publiceren van de pagina kan de programmeur dit transleren/vertalen naar de standaard &#8220;b&#8221;-tag, maar ook naar iets heel anders, bijvoorbeeld &#8220;strong&#8221; of &#8220;h1&#8243;.<br />
De taal die gebruikt wordt voor dit vertalen heet XSL-t, een soort HTML, maar dan met logica; je kan als programmeur o.a if-then-else, loops, en variabelen gebruiken. Hierdoor wordt de XML een stuk slimmer, en je site dus ook!</p>
<h2>Bewerken en beheren</h2>
<p>Wat WPS nog meer bijzonder maakt is de manier waarop je de teksten in je website kunt beheren; dit doe je namelijk gewoon <em>in</em> je site en niet op een aparte website of backend. Hierdoor zie je veel beter wat en waar je wat doet. Dit is veel gebruiksvriendelijker dan de standaard CMS&#8217;en en geeft veel beter weer wat de cohesie is tussen website en content.</p>
<h2>Plugins</h2>
<p>Een standaard WPS-site kan al heel veel;</p>
<ul>
<li>Pagina&#8217;s aanmaken, teksten maken en aanpassen</li>
<li>Meta-tags (voor zoekmachines) beheren</li>
<li>Linkjes in je teksten controleren of ze nog goed zijn</li>
<li>Bestanden (pdf&#8217;s, Word-documenten, plaatjes) uploaden</li>
<li>Een site in meerdere talen publiceren (en dat doet WPS heel slim want als je een pagina in het nederlands naar bijvoorbeeld het engels hebt vertaald dan weet WPS welke pagina&#8217;s bij elkaar horen, als een engels-sprekende op een nederlandse pagina komt kan hij/zij met 1 klik naar de engelse versie zonder de pagina opnieuw te moeten zoeken)</li>
<li>Rechten instellen per pagina</li>
</ul>
<p>Verder zijn er heel veel extra functies gemaakt in de vorm van &#8216;plugins&#8217;, een greep uit de collectie;</p>
<ul>
<li>Nieuws-plugin: zorgt voor het beheer en publicatie van nieuws-berichten (ook naar RSS!)</li>
<li>Poll-plugin: maak zelf een poll en zorg dat je bezoekers kunnen stemmen</li>
<li>Search-plugin : zorgt ervoor dat bezoekers kunnen zoeken in je website</li>
<li>Shop-plugin: volledige webwinkel, met betalingsmodule voor IDEAL en Mollie (micropayments)</li>
<li>Enquete-plugin: zeer uitgebreide plugin voor het maken van grote enquetes, compleet met uitnodigings-email-functie, toegangscodes en export-functies.</li>
<li>Catalogus/Portofolio-plugin: laat je bezoekers zien wat je verkoopt of wat je hebt gemaakt.</li>
<li>Download-beveiliging voor Audio: als je bijvoorbeeld muziek wilt laten horen vanaf je website via een zg. FlashPlayer dan zorgt WPS ervoor dat bezoekers niet stiekem de bestanden kunnen downloaden.</li>
<li>Google-Maps-plugin: zorgt ervoor dat je bezoekers op een kaartje kunnen zien waar je bedrijf is gevestigd</li>
<li>Reactie-plugin: geeft je bezoekers de mogelijkheid om korte reacties op je website te plaatsen (en ze kunnen ook op elkaar reageren)</li>
<li>PDF-output; maakt automatisch PDF-bestanden van de tekst op een pagina die bezoekers kunnen downloaden</li>
<li>Blog-Plugin: samenvoeging van de nieuws-plugin en de reactie-plugin</li>
<li>Gallery-plugin: maakt automatisch een mooie foto-gallery van foto&#8217;s</li>
<li>En in ontwikkeling; Google WAVE-integratie; een mogelijkheid om bezoekers via Google Wave te laten reageren op nieuws-berichten.</li>
</ul>
<p>Verder maakt WPS gebruik van slimme caching; je site zal altijd rete-snel blijven omdat alle veel gebruikte informatie in het geheugen van de webserver bewaard blijven, zodat ze snel weer voor handen zijn als het nodig is.</p>
<p>Voor meer informatie over WPS, <a title="WPS demo website" href="http://wps.i-v-o.nl" target="_blank">klikkerdeklik!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://syntacticsugar.nl/2009/10/17/launched-a-new-wps-demo-website/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Putting the Singleton-pattern to good use</title>
		<link>http://syntacticsugar.nl/2009/05/03/putting-the-singleton-pattern-to-good-use/</link>
		<comments>http://syntacticsugar.nl/2009/05/03/putting-the-singleton-pattern-to-good-use/#comments</comments>
		<pubDate>Sun, 03 May 2009 06:35:16 +0000</pubDate>
		<dc:creator>buTTon</dc:creator>
				<category><![CDATA[OOP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Registry]]></category>
		<category><![CDATA[Singleton]]></category>

		<guid isPermaLink="false">http://syntacticsugar.nl/?p=167</guid>
		<description><![CDATA[I like the Singleton-pattern, it saves a lot of trouble on creating objects that you need throughout your code and need to keep their state. Though it&#8217;s very tempting, do not use the singleton too much; see here why.
There are some pretty good uses for a Singleton though; a registry and the database-connection;
Download example code [...]]]></description>
			<content:encoded><![CDATA[<p>I like the <a href="http://en.wikipedia.org/wiki/Singleton_pattern" target="_blank">Singleton-pattern</a>, it saves a lot of trouble on creating objects that you need throughout your code and need to keep their state. Though it&#8217;s very tempting, do not use the singleton too much; see <a href="http://www.sitepoint.com/blogs/2008/02/13/whats-so-bad-about-the-singleton/" target="_blank">here</a> why.</p>
<p>There are some pretty good uses for a Singleton though; a registry and the database-connection;</p>
<p><span id="more-167"></span><a href="http://syntacticsugar.nl/upload/singletons.zip">Download example code here</a></p>
<p><strong>Database-connection</strong></p>
<p>I use <a href="http://adodb.sourceforge.net/" target="_self">ADODB</a> to access databases, don&#8217;t ask me why, I just do. ADODB uses a DSN to connect to a database, which looks something like:</p>
<pre><code>mysql://dbUser:dbPass@localhost/someDb</code></pre>
<p>Normally you&#8217;d use <em>$connection = &amp;ADONewConnection($DSN)</em> to connect to the database and run your query (<em>$rs = $connection-&gt;execute($sqlQuery) </em>). The problem here; you keep creating new connections anywhere you run a query, you need to pass the value for $DSN into your objects,  you&#8217;ve made your class depend on ADODB and it take 2 lines of code <img src='http://syntacticsugar.nl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />   You can bypass these &#8216;problems&#8217; by using a Singleton to connect to your database and run a query:</p>
<pre><code>$rs = basicDBConn::getConnection()-&gt;execute($sqlQuery);</code></pre>
<p>Now, what is wrong here? Did you see $DSN anywhere?<br />
Nope&#8230; This statement assumes you&#8217;ve passed $DSN already somewhere before, in fact the <em>first</em> time you call <em>getConnection()</em> from this singleton you must pass $DSN as argument in getConnection(). The first time you call getConnection() is the moment the singleton creates an instance of itself, and uses $DSN to connect to the database (<em>&amp;ADONewConnection($DSN)). </em>After this initialization the connection is kept within the Singleton, and $DSN isn&#8217;t needed anymore. Take a look at the files, basicDBConn.php in particular to get an idea of how the Singleton creates an instance of itself and the database-connection.</p>
<p><strong>Registry</strong></p>
<p>Another good use for Singletons is a Registry-object; A registry-object is used for configuration; global settings that you might need in your code (path&#8217;s, DB-configuration etc.). Since I&#8217;m infected by the XML-virus my configuration-files always are XML :</p>
<pre><code>&lt;config&gt;
    &lt;item index="DSN"&gt;mysql://dbUser:dbPass@localhost/singletondemo&lt;/item&gt;
    &lt;item index="someKey"&gt;someValue&lt;/item&gt;
&lt;/config&gt;
</code></pre>
<p>There is a drawback though; these XML-files are <span style="text-decoration: underline;">not</span> protected by Apache by default, anyone can open them from a browser (if they are somewhere in the public root of the website). There are 2 solutions for this; prefix the file with <em>.hta</em> (in which case Apache will protect them just as .htaccess files are protected) or add the following lines to your Apache-configuration :</p>
<pre><code>&lt;Files ~ "configuration_filename.xml"&gt;
   Order allow,deny
   Deny from all
&lt;/Files&gt;</code></pre>
<p>The registry-object works the same as the Database-object; it needs a reference to a XML-file <em>the first time</em> you call it, after that it&#8217;s fully initialized and doesn&#8217;t need that reference anymore.</p>
<p>The first call to a registry object (and get the value for &#8217;some_key&#8217;):</p>
<pre><code>$someValue = basicRegistry::getInstance('/path/to/configuration/file.xml')-&gt;get("some_key");</code></pre>
<p>Any call after that:</p>
<pre><code>$someValue = basicRegistry::getInstance()-&gt;get("some_key");</code></pre>
<p><strong>Why is a singleton a good thing?</strong><br />
Getting configuration-values or a $DSN-string from within objects should be simple, you do not want to pass the path and filename to your configuration file or $DSN to a database every time you create an instance of an object. It will create dependencies and spaghetti in your code. If you make sure the registry and/or database-object are created <em>before</em> your other objects start doing something you do not need to worry about file-names and/or $DSN&#8217;s. They have been safely put away in a singleton.</p>
<p>Another very nice side-effect ; you&#8217;ve decoupled database-connections and configuration-settings. In my examples I use XML to setup the values in the registry, if you want to use some other method of keeping key-value-pairs, just modify the inner workings of the Registry-singleton, the objects using the registry won&#8217;t notice and work just as well. I usually keep session-variables in the registry, if I can&#8217;t use PHP&#8217;s $_SESSION, I can fall back onto Cookies, my classes won&#8217;t notice.</p>
<p><a href="http://syntacticsugar.nl/upload/singletons.zip">Download example code here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://syntacticsugar.nl/2009/05/03/putting-the-singleton-pattern-to-good-use/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating your own RPC-interface in PHP</title>
		<link>http://syntacticsugar.nl/2009/04/17/creating-your-own-rpc-interface-in-php/</link>
		<comments>http://syntacticsugar.nl/2009/04/17/creating-your-own-rpc-interface-in-php/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 17:53:48 +0000</pubDate>
		<dc:creator>buTTon</dc:creator>
				<category><![CDATA[OOP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[DIY]]></category>
		<category><![CDATA[RPC]]></category>
		<category><![CDATA[RPC-Client]]></category>
		<category><![CDATA[RPC-server]]></category>

		<guid isPermaLink="false">http://syntacticsugar.nl/?p=142</guid>
		<description><![CDATA[Last week I got a request to create some kind of RPC-server-client in PHP.  The assignment was to create a flexible solution to allow remote updating several properties in a database. I&#8217;ve created interfaces like this before, but specifically for AJAX-calls to PHP-objects, not really for server-to-server-calls. This particular assignment also involved a PHP-client-object [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I got a request to create some kind of RPC-server-client in PHP.  The assignment was to create a flexible solution to allow remote updating several properties in a database. I&#8217;ve created interfaces like this before, but specifically for AJAX-calls to PHP-objects, not really for server-to-server-calls. This particular assignment also involved a PHP-client-object for other developers to implement in their website. The RPC-interface actually doesn&#8217;t really care if it&#8217;s used for real server-to-server calls or AJAX-calls. However; in this article I&#8217;ll focus on server-to-server communication, if designed well it shouldn&#8217;t take too much effort to make it AJAX-compatible.</p>
<p><span id="more-142"></span><br />
<a href="http://syntacticsugar.nl/upload/rpc.zip">[download code]</a></p>
<p>This is how these RPC-calls are done:</p>
<p><img class="aligncenter size-full wp-image-147" title="RPC-interface structure" src="http://syntacticsugar.nl/wp-content/uploads/2009/04/diagram11.png" alt="RPC-interface structure" width="650" height="613" /></p>
<p>Since I like XML a lot, I wanted to use XML as transport mechanism for doing requests to the RPC-interface. Because I use XML I was also able to group RPC-calls into one single request. A simple method of authenticating these RPC-calls is something to consider if you&#8217;re not running a public service, but that&#8217;s beyond the scope of this article</p>
<p>A typical call would look like this:</p>
<pre><code>&lt;command&gt;
	&lt;method name=”remote_method” object=”some_object”&gt;
		&lt;arg key=”some_argument”&gt;value_of_some_argument&lt;/arg&gt;
		&lt;arg key=”another_argument”&gt;value_of_another_argument&lt;/arg&gt;
	&lt;/method&gt;
	&lt;method name=”another_remote_method” object=”another_object”&gt;
		&lt;arg key=”some_argument”&gt;value_of_some_argument&lt;/arg&gt;
		&lt;arg key=”another_argument”&gt;value_of_another_argument&lt;/arg&gt;
	&lt;/method&gt;
&lt;/command&gt;</code></pre>
<p>Now, what does this XML actually mean?</p>
<p>First of all; the methods need to be nested into a single node: &lt;command&gt;, the XML would not be valid otherwise. Each method-node has an name-attribute and object-attribute, the object-attribute defines the remote PHP-object which contains the method you&#8217;d like to call, the method is defined in the name-attribute.</p>
<p>Each method-node contains one or more arg-nodes, these nodes are passed to the method as a hashed-array and used as arguments for the method. Attribute “key” will be the key or name in the arguments-array, the node-value will become the value.</p>
<p>The example above will eventually call 2 methods,</p>
<ol>
<li>the first method, “remote_method” 	 is part of object “some_object”, and receives 2 arguments;
<ul>
<li>“some_argument” with value 	“value_of_some_argument”</li>
<li>“another_argument” with value 	“value_of_another_argument”</li>
</ul>
</li>
<li>the second method, “another_remote_method”  is part of 	object “another_object”, and also receives 2 arguments;
<ul>
<li>“some_argument” with value 	“value_of_some_argument”</li>
<li>“another_argument” with value 	“value_of_another_argument”</li>
</ul>
</li>
</ol>
<p>Now, let get some coding done, let&#8217;s focus on the RPC-server first, download <a href="http://syntacticsugar.nl/upload/rpc.zip">this</a> code-snippet and unpack it in a fresh webroot (it contains all the files described in this article, also the RPC-client).</p>
<p>First take a look at /include/classes:</p>
<ul>
<li>tools.php : contains static 	“helper” methods, I hate procedural spaghetti-code and I always 	put methods which are not part of a larger object-model into several 	helper-classes. In this particular example a single helper-class is 	enough. All methods in this class are static and can be called 	without first creating an object.</li>
<li>abstract_object.php : this is 	important and can be confusing if you&#8217;re not used to an object 	oriented approach. This class contains methods which are inherited 	into child-classes, but you cannot create an object-instance of this 	class, because it&#8217;s abstract. Why is it abstract? It&#8217;s arguable to 	just let it be a normal class in this particular example, however; 	using abstract classes in larger projects really keeps your code 	clean and separates the implementation of your object-design from the 	structure you&#8217;re using.</li>
<li>some_object.php : inherited from 	abstract_class.php; example implementation.</li>
<li>another_object.php : inherited 	from abstract_class.php; another example implementation.</li>
</ul>
<p>The actual object available for the RPC-interface are some_object and another_object. Now let&#8217;s take a look at rpc.php, which is in the root. The only really interesting part is from line 56</p>
<pre><code>

	// gather 'method' nodes and execute them;
	$methods = $dom-&gt;getElementsByTagName('method');

	for ($i=0;$i&lt;$methods-&gt;length;$i++){
		$methodNode = $methods-&gt;item($i);
		$method = $methodNode-&gt;getAttribute('name');
		$obj = $methodNode-&gt;getAttribute('object');
		$obj = new $obj();
		$arguments = tools::getArgumentsAsArray($methodNode);
		$obj-&gt;$method($arguments);
		$messages .= $obj-&gt;getMessages();
	}

	echo tools::wrapMessages($messages);
</code></pre>
<p>So, what&#8217;s really happening here?</p>
<p>The first statement; <em>$methods = $dom-&gt;getElementsByTagName(&#8216;method&#8217;);</em> will retrieve all method-nodes from the request. PHP-DOM (or any other DOM-implementation for that matter) will always return the nodes in a nodeset, even if it&#8217;s only one method-node, but not if there aren&#8217;t any nodes found.<br />
This nodeset is used to loop upon, the classic for-next statement on the next line.</p>
<p>In each loop the method-node is examined; the attribute-values for object and method are determined (<em>$method = $methodNode-&gt;getAttribute(&#8216;name&#8217;)</em> and <em>$obj = $methodNode-&gt;getAttribute(&#8216;object&#8217;)</em>) and  using a static function from the tools-class the arguments are converted into a PHP-array (<em>$arguments = tools::getArgumentsAsArray($methodNode)</em> ).</p>
<p>Now we&#8217;re ready gathering all the values needed to really create the object ( <em>$obj = new $obj()</em> ) and execute the requested method ( <em>$obj-&gt;$method($arguments) </em>).</p>
<p>The method should not return anything, instead it&#8217;s return-values are stored into a protected variable (defined in abstract_object). To get these values, use  <em>$obj-&gt;getMessages()</em>. This method doesn&#8217;t seem to be available in the class of <em>$obj</em>, it&#8217;s defined in <em>abstract_object</em>.</p>
<p>After the loop has finished the $message-string should be wrapped into a node to make sure the XML is valid, this is done with the tools&#8217; class <em>wrapMessages</em>-method.</p>
<p>Ok, the RPC-interface is ready, let&#8217;s test it! Enter the following URL into a browser (assuming you&#8217;re running PHP on localhost, in a folder called rpc:</p>
<pre><code>http://localhost/rpc.php?req=&lt;command&gt;&lt;method name="remote_method" object="some_object"&gt; &lt;arg key="some_argument"&gt;value_of_some_argument&lt;/arg&gt;&lt;arg key="another_argument"&gt;value_of_another_argument&lt;/arg&gt; &lt;/method&gt;&lt;method name="another_remote_method" object="another_object"&gt; &lt;arg key="some_argument"&gt;value_of_some_argument&lt;/arg&gt;&lt;arg key="another_argument"&gt;value_of_another_argument&lt;/arg&gt; &lt;/method&gt;&lt;/command&gt;</code></pre>
<p>You&#8217;ve just called a 2 functions from your RPC-interface! The output should look like this:</p>
<pre><code>&lt;servermessages&gt;
    &lt;message object="some_object" method="remote_method" code="200"&gt;remote_method was executed
        succesfully with arguments : value_of_some_argument, value_of_another_argument &lt;/message&gt;
    &lt;message object="another_object" method="another_remote_method" code="200"&gt;another_remote_method
        was executed succesfully with arguments : value_of_some_argument, value_of_another_argument
    &lt;/message&gt;
&lt;/servermessages&gt;</code>
</pre>
<p>Now let&#8217;s move on to the RPC-client: take a look at rpcClient.php in the root. It&#8217;s quite large, and I will not go into all the details (the comments in the file should be enough). Most of the functions in rpcClient take care of constructing the XML needed to execute the RPC-call, absolutely no rocket-science.  However; I do want to highlight the actual &#8220;executing&#8221; of the RPC-call, take a look at the private function sendToHost:</p>
<pre><code>
 private function sendToHost($data) {
	$postdata = http_build_query(
	    array(
	        'req' =&gt; $data
	    )
	);
	$opts = array('http' =&gt;
	    array(
	        'method'  =&gt; 'POST',
	        'header'  =&gt; 'Content-type: application/x-www-form-urlencoded',
	        'content' =&gt; $postdata
	    )
	);
	$context  = stream_context_create($opts);
	$this-&gt;result = file_get_contents($this-&gt;rpcURI, false, $context);
}</code></pre>
<p>This method uses <em>file_get_contents</em>, <em>http_build_query</em> and <em>stream_context_create</em> to POST the constructed XML to the RPC-server and stores the reply in a local variable ($result). I&#8217;ve tried using fopen like this:</p>
<pre>
<code>function sendToHost($host,$path,$data) {
	$fp  = @fsockopen($host,80);
	$buf = '';
	if ($fp) {
		@fputs($fp, "POST $path HTTP/1.0\n");
		@fputs($fp, "Host: $host\n");
		@fputs($fp, "Content-type: application/x-www-form-urlencoded\n");
		@fputs($fp, "Content-length: " . strlen($data) . "\n");
		@fputs($fp, "Connection: close\n\n");
		@fputs($fp, $data);
		while (!feof($fp)) {
		  $buf .= fgets($fp,128);
		}
		fclose($fp);
	}
	return $buf;
}</code>
</pre>
<p>This method failed. I kept getting weird responses from my RPC-server (command not understood etc.). And honestly;  I like the clean call using <em>file_get_contents</em>, <em>http_build_query</em> and <em>stream_context_create</em> much better.</p>
<p>Ok; we have a nice object-structure, a RPC-server and a RPC-Client. What&#8217;s left is a real world implementation of the client. Take a look at example.php:</p>
<pre><code> include('rpcClient.php');

 $hsClient = new rpcClient();
 $hsClient-&gt;createCall('some_object', 'remote_method', array('some_argument'=&gt;'some_value', 'another_argument'=&gt;'another_value'));
 $hsClient-&gt;createCall('another_object', 'another_remote_method', array('some_argument'=&gt;'some_value', 'another_argument'=&gt;'another_value'));
 $hsClient-&gt;execute();
 $str = $hsClient-&gt;getXMLResponse();
 echo "&lt;pre&gt;";
 echo $str;
 echo "&lt;/pre&gt;"; </code>
</pre>
<p>If you&#8217;d leave out the debugging-statement at the end you end up using 4 lines of code to create, execute and retrieve a RPC-call (ok; 5 lines if you consider I&#8217;ve made 2 RPC calls). First you create an instance of the RPC-client, secondly you create a call using createCall and last but not least; you execute the call and intepret the response. If you&#8217;d enter the URL to example.php into your browser you&#8217;ll get:</p>
<pre>
remote_method was executed succesfully with arguments : some_value, another_value
another_remote_method was executed succesfully with arguments : some_value, another_value
</pre>
<p>That&#8217;s it! You have a RPC-server, RPC-client and a working implementation! You should take care of authenticating your RPC-calls, and design a nice Object-structure to implement &#8216;behind&#8217;  the RPC-server, this all depends on the kind of logic you need. I&#8217;ve used this method of RPC-ing to allow 3rd-parties to update certain values in a shop-database, and with a little effort you could make your RPC-server handle AJAX-requests and return JSON to clients. But that something for the next article.</p>
<p><a href="http://syntacticsugar.nl/upload/rpc.zip">[download code]</a></p>
]]></content:encoded>
			<wfw:commentRss>http://syntacticsugar.nl/2009/04/17/creating-your-own-rpc-interface-in-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>AJP : Authenticated JSON Proxy</title>
		<link>http://syntacticsugar.nl/2009/03/20/ajp-authenticated-json-proxy/</link>
		<comments>http://syntacticsugar.nl/2009/03/20/ajp-authenticated-json-proxy/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 16:01:14 +0000</pubDate>
		<dc:creator>buTTon</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WPS]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Cross-domain]]></category>
		<category><![CDATA[Prototype.js]]></category>
		<category><![CDATA[SOP]]></category>

		<guid isPermaLink="false">http://syntacticsugar.nl/?p=100</guid>
		<description><![CDATA[Authenticated what?
The first hurdle most developers have to take when introduced to AJAX is S.O.P.
S.O.P stands for Same Origin Policy and basically means that you can only do AJAX-requests to the (sub)-domain the client is currently on.  First thing I thought when I read about AJAX couple of years ago; &#8216;wow! cool!  I [...]]]></description>
			<content:encoded><![CDATA[<p><em>Authenticated what?</em></p>
<p>The first hurdle most developers have to take when introduced to AJAX is <a href="http://en.wikipedia.org/wiki/SOP" target="_blank">S.O.P</a>.<br />
S.O.P stands for Same Origin Policy and basically means that you can only do AJAX-requests to the (sub)-domain the client is currently on.  First thing I thought when I read about AJAX couple of years ago; &#8216;wow! cool!  I can strip content from other sites and incorporate them in my websites&#8217; .. and immediately I started hammering away on a RSS-reader which was supposed to grab news from a RSS-feed directly. My efforts failed. The RSS-feed was on another domain and S.O.P kicked in spoiling all the fun.<br />
<span id="more-100"></span><br />
There are ways to get around this, you could create a server-side script which retrieves content from another domain and proxy it to your AJAX-request. However; you will need a server that has either PHP, ASP(.net), CGI, Rails, or at least something more intelligent than a plain HTML-only environment. This is OK for most people, and proxying content from other domains to AJAX-request is used a lot. But what if you&#8217;d like to create something, like a widget, which needs to grab content from any domain, and which people can use without having a PHP/ASP/CGI or Ruby-server? You wouldn&#8217;t be able to get around S.O.P, right?<br />
How can you bypass S.O.P, while still maintain a certain level of security?</p>
<p><strong>TimeLiner</strong><br />
I ran into this problem when I created <a href="http://www.tliner.com" target="_blank">TimeLiner</a>. TimeLiner retrieves and displays messages linked to a flashmovie or mp3-file.  These messages are stored on one of my servers and TimeLiner could be running anywhere. Retrieving those messages should be done by AJAX-like requests but I didn&#8217;t want users to install all kinds of server-side scripts on their server for proxying the messages from my server to overcome SOP. I wanted TimeLiner to be able to run from HTML-only-websites, or as a widget from social networking websites. But with SOP this wouldn&#8217;t be possible.<br />
With this in mind I started experimenting. I started off by creating script-tags and insert those tags into the DOM on the fly and see if variables in the referenced js file were actually available. Expecting limitations due to security measures within browsers the results actually suprised me; the variables were globally available!  I started on designing a proof of concept and tried to take this idea to the next level. At the end of the day I got a working prototype and called it AJP; the Authenticated JSON Proxy.</p>
<p><strong>RPC, AJAX, Objects</strong><br />
First a bit of history. The past few years I&#8217;ve been busy writing WPS; a publishing system much like Joomla (only much better;). It&#8217;s written in PHP5, object orientated, follows a observer-pattern(plugins) and runs entirely on XML/XSL-translations. If you&#8217;d like a shop-plugin on your WPS-driven-website you only need to include the shop-object and you&#8217;re ready to sell your stuff.</p>
<p>Because all data within WPS is actually XML it really doesn&#8217;t matter what you want to do with with it; you could translate it to HTML by using XSL-t and write it to the browser or you can pickup this data by using AJAX-calls. <a href="http://en.wikipedia.org/wiki/KISS_principle" target="_blank">KISS</a> at work <img src='http://syntacticsugar.nl/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>WPS uses its own RPC-interface for AJAX-requests. You can create a request by defining which WPS-object you&#8217;d like to call, which method within the choosen object must be executed and the arguments that need to be passed to the method. This WPSRPC-interface consists of two parts; the server-side pickup and dispatch, and a javascript-class that simplifies the actual RPC-calls.<br />
A typical WPSRPC-request would look like this:</p>
<p>Javascript:</p>
<pre><code>var wpsRPC = new wps.rpc;
wpsRPC.createCall('shop', this.setSaved.bind(this));
wpsRPC.call('storeItemToBasket', {id:itemID, uid:someUID});</code></pre>
<p>Line 1: create a RPC-object<br />
Line 2: define the PHP-object you&#8217;d like to call (in this example; the <em>shop</em>-object) and define the callback-method (in this example; the method <em>setSaved</em> from the same object-instance, hence the <em>.bind(this)</em>-statement )<br />
Line 3 : define the method which needs to executed remotely, define the arguments that need to be passed and execute the request.</p>
<p>On the server-side (PHP) the request is handled by the WPS-controller. WPS uses <em>_autoload</em> to include the requested class, instantiates the requested object (in this case the <em>Shop</em>-object) executes the requested method (<em>storeItemToBasket</em>) and passes the arguments to that method (<em>id</em> &amp; <em>uid</em>). The output of the requested method should be XML or JSON which will be returned to the javascript-callback (<em>setSaved</em>) for further handling by the browser.<br />
This proofed to be a powerful method of remotely executing stuff; it&#8217;s clean, quick and flexible and I&#8217;ve used this structure for 5 years without any problems whatsoever.</p>
<p>Now; why this elaboration about WPS?<br />
AJP uses exactly the same structure, a Javascript object that contains methods for doing RPC-calls, and a server-side RPC-interface to handle those requests, but there is a slight difference; the calls can be done across domains!</p>
<p><strong>Back to AJP: how does it work?<br />
</strong>I&#8217;ll use the example of the WPS-shop-object and explain each step; let&#8217;s assume a user is visiting your webshop and clicks &#8220;add to basket&#8221;, what will happen?</p>
<p>By clicking an event is triggered, this event will create an AJP-object:</p>
<pre><code>var ajpObject = new ajp;
ajpObject.createCall('shop', this.setSaved.bind(this));
ajpObject.call('storeItemToBasket', {id:itemID, uid:someUID});</code></pre>
<p>Internally the AJP-object creates a random ID and prepends &#8220;jsonProxy&#8221;, let&#8217;s say this variable is called <em>jsonProxy12345</em>. This variable is used to identify the request. Next step is to create a script-tag and insert it into the head of your HTML-document. The src-attribute of the script-tag points to the URI where a RPC-interface is waiting for requests. This is not a .js file, but a .php-file; which allows you to use http-requests (<em>$_REQUEST</em> in PHP) to pass along variables.<br />
A script-tag from this example would look like this;</p>
<pre><code>&lt;script src="http://www.yourdomain.com/
rpc.php?jsonProxy=12345&amp;object=shop&amp;method=storeItemToBasket&amp;id=1&amp;uid=12" &gt;
&lt;/script&gt;</code></pre>
<p>The server-side pretty much works the same as the WPS-example above; the <em>$_REQUEST</em> is mapped to an object, a method and the arguments and is executed. There&#8217;s a small difference; the output can only be JSON, and put into a variable called <em>jsonProxy12345</em>.</p>
<p>Ok, let&#8217;s assume the RPC-call executed OK and the ID of the inserted row should be returned to javascript. How does AJP know there&#8217;s output, and how does AJP actually use the output?<br />
In &#8216;real&#8217; AJAX you can use an event to notify Javascript the RPC-call returned something, but AJP is not &#8216;real&#8217; AJAX&#8230; This is where the <em>jsonProxy12345</em> comes in: the moment the script-tag is inserted into the DOM a timer is started  which keeps checking for the variable <em>jsonProxy12345</em>. If the variable exists the value is picked up and passed to the callback-function, otherwise the timer keeps running until it encounters the variable (there&#8217;s a timeout to catch errors). This effectively mimics the events used in real AJAX, which we want.</p>
<p><strong>Now for some security</strong><br />
If you use this kind of RPC you really do not want to expose your PHP-objects to the world. If you created a populair service your server would run out of resources if anyone can do RPC-calls to it. To overcome this you need to authenticate the requests, but how?<br />
It&#8217;s really quite simple; before actually doing a request, <em>ask</em> the server if you may do a request!<br />
I&#8217;ve done this before with traditional forms; before posting a form an AJAX-call retrieves a unique ID from the server (a mysql GUID), this GUID is appended to the form in a hidden field and the form is posted. The server checks if the GUID is valid, and if that&#8217;s the case the form is handled.<br />
But how does the server know the GUID is valid? The moment the server creates the GUID it&#8217;s stored into a database, along with the originating IP-address, the browser-string and the time it&#8217;s requested. If the form is actually posted the server checks if the GUID is available, if it&#8217;s from the same IP, with the same browserstring and within 5 seconds after it&#8217;s been requested. Only if all conditions are met the form is handled and the GUID is removed from the database.</p>
<p>This principle can also be used to authenticate AJP-requests, and AJP can use itself to request a GUID by being clever in it&#8217;s design and inheritance-scheme.<br />
I realize it&#8217;s quite easy to mimic the requesting of GUID&#8217;s, but it&#8217;s a barrier, and AJP does something else to tighten up security even more; whenever AJP receives a result the script-tag will be removed immediately. It removes any evidence of requests, making it harder to find out what happened.</p>
<p>AJP is certainly not rocket-science, I&#8217;ve seen a lot of scripts using this kind of technique. I do believe the structure of AJP itself works great and allows developers to extend upon. As a bonus; this also works great on very old browsers; i&#8217;ve tested it on MSIE 4, and AJP works fine!</p>
<p>I&#8217;ve compiled a small (LGPL&#8217;ed) <a href="http://syntacticsugar.nl/upload/ajp.zip">download</a> which contains all the files for using AJP, it&#8217;s not a full implementation, but enough to get you going.</p>
]]></content:encoded>
			<wfw:commentRss>http://syntacticsugar.nl/2009/03/20/ajp-authenticated-json-proxy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Javascript Classes and Object Inheritance with Prototype.js</title>
		<link>http://syntacticsugar.nl/2009/03/15/javascript-object-inheritance-with-prototypejs/</link>
		<comments>http://syntacticsugar.nl/2009/03/15/javascript-object-inheritance-with-prototypejs/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 10:45:20 +0000</pubDate>
		<dc:creator>buTTon</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[object inheritance]]></category>
		<category><![CDATA[Prototype.js]]></category>

		<guid isPermaLink="false">http://syntacticsugar.nl/?p=80</guid>
		<description><![CDATA[If you&#8217;re used to writing Object Oriented PHP switching to Javascript could be confusing, it takes a lot of effort and ugly code to actually write pure classes. You won&#8217;t be able to create abstract-classes or use interfaces. On the other hand; being a prototyped language Javascript offers a lot of possibilities that you won&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re used to writing Object Oriented PHP switching to Javascript could be confusing, it takes a lot of effort and ugly code to actually write pure classes. You won&#8217;t be able to create abstract-classes or use interfaces. On the other hand; being a prototyped language Javascript offers a lot of possibilities that you won&#8217;t find in PHP. If you&#8217;re used to the way of thinking of OOP in PHP, why not use this knowledge to write Javascript-classes? This is where <a href="http://prototypejs.org/" target="_blank">Prototype.js</a> comes in.</p>
<p><span id="more-80"></span></p>
<p>I love <a href="http://prototypejs.org/" target="_blank">prototype.js</a>; it&#8217;s lightweight, saves you a lot of code and best of all; it enables you to write your code in syntactic sugar-style. Object-inheritance in Prototype.js makes writing javascript-classes a breeze, check out the following example:</p>
<pre><code>// the base-class
var myFirstClass = Class.create({
    initialize:function(){
		// Constructor
	},

	somefunction : function(){
		alert("Executing somefunction in an instance of myFirstClass");
	},

	anotherfunction : function(){
		alert("Executing anotherfunction in an instance of myFirstClass");
	},

	yetanotherfunction:function(){
		alert("Executing yetanotherfunction in an instance of myFirstClass");
	}
})

// base-class, extended
var anExtendedClass = Class.create(myFirstClass, {
	initialize:function(){
	},

	somefunction : function(){
		alert("Executing somefunction in an instance of anExtendedClass");
	},

	anotherfunction : function($super){
		$super();
		alert("Executing anotherfunction in an instance of anExtendedClass");
	}
})</code></pre>
<p>Now, create an instance of <em>myFirstClass</em>, and call the function <em>somefunction</em> :</p>
<pre><code>var firstInstance = new myFirstClass();
firstInstance.somefunction();</code></pre>
<p>You should get an alert, saying &#8221; Executing somefunction in an instance of myFirstClass &#8220;. Nothing really special here, now try the same for an instance of <em>anExtendedClass</em>:</p>
<pre><code>var secondInstance = new anExtendedClass();
secondInstance.somefunction();</code></pre>
<p>You should get another alert,  &#8220;Executing somefunction in an instance of anExtendedClass&#8221; which is executed from <em>anExtendedClass</em>.<br />
<em>somefunction</em> Has basically been overridden by <em>anExtendedClass</em>, and honestly; you won&#8217;t need Prototype.js to do this, though the code itself looks a lot cleaner.</p>
<p>But now the next step; extending a function/method while you still want to run the function in the base-class. Normally you&#8217;d copy the contents of the function in your base class, resulting in a mess and unmaintainable code. This is were Prototype.js really comes in; the function <em>$super()</em>.<br />
$super() Should be passed as an argument in the extended class and is a reference to the same function in the base-class, take a look at <em>anExtendedClass.anotherfunction</em> to see how $super() is used.<br />
Let&#8217;s put $super into action; create an instance of <em>anExtendedClass</em> and call the method <em>anotherfunction()</em>:</p>
<pre><code>var anotherInstance = new anExtendedClass();
anotherInstance.anotherfunction();</code></pre>
<p>You should get 2 alerts; the first one saying &#8220;Executing anotherfunction in an instance of myFirstClass&#8221;, which is the alert in <em>myFirstClass.anotherfunction(),</em> and called from $super(). The second alert should say &#8220;Executing anotherfunction in an instance of anExtendedClass&#8221;.<br />
So.. what happened here?</p>
<p>The instance of <em>anExtendedClass</em> is extended from <em>myFirstClass</em>, and they both have the method <em>anotherfunction</em>. However; method <em>anotherfunction</em> in <em>anExtendedClass</em> has a reference to it&#8217;s ancestor in <em>myFirstClass</em>; the method $super(). The moment you call $super() the first alert is shown and right after that the implementation of <em>anotherfunction</em> in <em>anExtendedClass</em> is executed; resulting in the next alert.<br />
Do not get confused with the scope in which <em>anotherfunction</em> is running. The fact that you execute <em>anotherfunction</em> in the base-class from an inherited class does not imply that <em>anotherfunction</em> can use variables set in the base-class. Let&#8217;s put that to the test :</p>
<p><strong>Instance-Id&#8217;s </strong><br />
It&#8217;s quite difficult to recognize the scope of an object in javascript, especially when you use events and object-inheritance. To make this a little easier I always create an instance-ID in al my javascript-classes. Check out the following example;</p>
<pre><code>
// the base-class
var myFirstClass = Class.create({
    initialize:function(){
		this.instID = 'myFirstClass.' + parseInt(Math.random()*1000000);
		// Constructor
	},

	somefunction : function(){
		alert("Executing somefunction in an instance of myFirstClass " +this.instID );
	},

	anotherfunction : function(){
		alert("Executing anotherfunction in an instance of myFirstClass " +this.instID);
	},

	yetanotherfunction:function(){
		alert("Executing yetanotherfunction in an instance of myFirstClass " +this.instID);
	}
})

// base-class, extended
var anExtendedClass = Class.create(myFirstClass, {
	initialize:function(){
		this.instID = 'anExtendedClass.' + parseInt(Math.random()*1000000);
	},

	somefunction : function(){
		alert("Executing somefunction in an instance of anExtendedClass " +this.instID);
	},

	anotherfunction : function($super){
		$super();
		alert("Executing anotherfunction in an instance of anExtendedClass " +this.instID);
	}
})</code></pre>
<p>Prototype.js provides a class-constructor (in fact; prototype.js demands a constructor): the function <em>initialize</em>().<br />
<em>Initialize</em>() creates a variable <em>instID</em> which contains the name of the class and a large random number, this variable can be used to identify the object. Now let&#8217;s check out the scope of <em>anotherfunction</em>:</p>
<pre><code>var anotherInstance = new anExtendedClass();
anotherInstance.anotherfunction();</code></pre>
<p>You should get 2 alerts; the same as the example above, <strong>but both alerts have the same instID.</strong> This proves that the scope in which $super() executes the alert is the same as the second alert. Pretty neat huh?<br />
<em>this.instID</em> can be put to good use in another scenario; if you create elements from your objects that need to be unique you can use the <em>instID</em> to make it unique;</p>
<pre><code>somefunction : function(){
       var someElement = new Element('div', {id:"someElement_" + this.instID});
}</code></pre>
<p>Now; let&#8217;s get back to inheritance, there&#8217;s still a method we didn&#8217;t give any attention; <em>yetanotherfunction</em>.</p>
<pre><code>var anotherInstance = new anExtendedClass();
anotherInstance.yetanotherfunction();</code></pre>
<p>If you look at <em>anExtendedClass</em> you&#8217;d notice the method <em>yetanotherfunction</em> has not been defined, but you didn&#8217;t get an error, you got an alert right? Why?  <em>yetanotherfunction</em> Has been defined in the base-class, and <em>anExtendedClass</em> inherits the method completely, but stays in the scope of <em>anExtendedClass</em>.</p>
<p>It took me a while to get a grasp of pure classes in Javascript, i&#8217;ve tried different methods of extending objects and they seemed to work great, but in the end I noticed I kept writing a lot of code twice and the code itself got bloated. By using prototype.js your Javascript classes stay clean, small and easy to maintain.<br />
Next time I&#8217;ll discuss how to put this knowledge to good use by creating a widget-framework in Javascript by using abstract classes, an interface and the MVC-model.</p>
<p><a href="/upload/javascript_object_inheritance.zip">Download the code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://syntacticsugar.nl/2009/03/15/javascript-object-inheritance-with-prototypejs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
