<?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>Terminus a Quo &#187; CakePHP</title>
	<atom:link href="http://abing.gotdns.com/posts/category/code-and-consequences/php/cakephp/feed/" rel="self" type="application/rss+xml" />
	<link>http://abing.gotdns.com</link>
	<description>Because you can never have too many blogs on the Internet...</description>
	<lastBuildDate>Tue, 19 May 2009 00:23:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>I Am No Longer Tracking CakePHP</title>
		<link>http://abing.gotdns.com/posts/2007/i-am-no-longer-tracking-cakephp-and-new-projects/</link>
		<comments>http://abing.gotdns.com/posts/2007/i-am-no-longer-tracking-cakephp-and-new-projects/#comments</comments>
		<pubDate>Wed, 11 Jul 2007 07:25:09 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Yes, I do have a Life.]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/posts/2007/i-am-no-longer-tracking-cakephp-and-new-projects/</guid>
		<description><![CDATA[Title says it all. I am no longer tracking the CakePHP project and therefore my CakePHP modifications project is now officially dead. This is mostly due to time constraints but there are other reasons as well. I will not go into the details for the other reasons but those who know me already know what [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>Title says it all. I am no longer tracking the CakePHP project and therefore my CakePHP modifications project is now <strong>officially dead</strong>. This is mostly due to time constraints but there are other reasons as well. I will not go into the details for the other reasons but those who know me already know what those reasons are.</p>

<p>Of course, hosting for these patches continues as well as my ThemeableView class which some CakePHP users out there found useful. If anyone else is interested in taking the reins for this class, please feel free to do so. No need to contact me or anything, but a trackback to this post would be nice so that I will know who is currently maintaining this class. This will allow me to direct them to you for any updates that you may post.</p>

<p>On another note, the project that has been taking much of my time lately is a new website for posting <a href="http://www.preownedcar.com/" title="Free online classified ads for cars, trucks, and bikes">free online classified ads for cars, trucks, and bikes</a>. This website is currently US-centric. We have plans to extend worldwide if all goes well with the current setup. So, if you&#8217;re in the US and you wish to sell your vehicle, or if you&#8217;re looking to buy a preowned car, truck, or bike check out <a href="" title="Free online classified ads for cars, trucks, and bikes">PreOwnedCar.com</a>. If you know someone with the same needs, please tell them about this site.</p>

<p>We are also currently in the final design phases for PhilWeavers Version 4. I am currently divided between doing this new version using Django as a base or simply going back to the drawing board and creating a new PHP5-based framework. We&#8217;ll see how this pans out in the later stages of development.</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2007/i-am-no-longer-tracking-cakephp-and-new-projects/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Two Months Working With Django&#8230; Wishing CakePHP had a Better ORM</title>
		<link>http://abing.gotdns.com/posts/2007/two-months-working-with-django-wishing-cakephp-had-a-better-orm/</link>
		<comments>http://abing.gotdns.com/posts/2007/two-months-working-with-django-wishing-cakephp-had-a-better-orm/#comments</comments>
		<pubDate>Thu, 08 Mar 2007 04:03:13 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/posts/2007/two-months-working-with-django-wishing-cakephp-had-a-better-orm/</guid>
		<description><![CDATA[I have been working with the Django Web framework for close to two months now and I&#8217;m loving it. Not so much for the free admin interface, but for the sheer ease of development that it provides. For the first time, I cared more about how my models are designed and not how they are [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>I have been working with the <a href="http://www.djangoproject.com/" title="Django Web framework">Django Web framework</a> for close to two months now and I&#8217;m loving it. Not so much for the <a href="http://www.djangoproject.com/documentation/overview/#a-dynamic-admin-interface-it-s-not-just-scaffolding-it-s-the-whole-house" title="A dynamic admin interface: It's not just scaffolding -- it's the whole house">free admin interface</a>, but for the sheer ease of development that it provides. For the first time, I cared more about how my models are designed and not how they are laid out and implemented in the database. For the two projects that I am working on, I have yet to write a custom SQL statement under Django.</p>

<p>It makes me wish CakePHP offered more when it comes to object-relational mapping. How I wish it was as simple as defining your models and running <code>php cake/scripts/bake.php syncdb</code>. CakePHP does it the other way around: you create the database first and then use <code>cake/scripts/bake.php</code> to create your models and views.</p>

<p><span id="more-81"></span></p>

<p>I found that Django&#8217;s way of doing ORM is significantly faster. You specify your models as Python classes using Django&#8217;s modeling API. You run <code>python manage.py syncdb</code> and Django takes care of generating the correct SQL for your database backend. It takes model relationships into account and also generates the correct foreign key constraints. Beautiful!</p>

<p>A similar system should also be possible to implement in CakePHP. I&#8217;ve been having a few ideas of how to go about it and hopefully, I can find the time to do them as an add-on to CakePHP 1.2.x (and hopefully, someone else is already working on the same thing).</p>

<p>Here is what I imagine it would look like:</p>

<pre><code>class User extends MetaModel {
    var $username;
    var $password;
    var $lastname;
    var $firstname;
    var $is_active;
    var $is_staff;
    var $is_admin;
    var $created;
    var $updated;

    function __construct() {
        $this-&gt;username = FieldFactory::CharField(&amp;#8217;Username&amp;#8217;, 32, IS_PK, IS_REQUIRED, NOT_NULL);
        $this-&gt;password = FieldFactory::CharField(&amp;#8217;Password&amp;#8217;, 64, NO_INDEX, IS_REQUIRED, NOT_NULL);
        $this-&gt;lastname = FieldFactory::CharField(&amp;#8217;Last Name&amp;#8217;, 64, INDEX, IS_OPTIONAL, NOT_NULL);
        $this-&gt;firstname = FieldFactory::CharField(&amp;#8217;First Name&amp;#8217;, 64, INDEX, IS_OPTIONAL, NOT_NULL);
        $this-&gt;is_active = FieldFactory::BooleanField(&amp;#8217;Active&amp;#8217;, IS_REQUIRED, NOT_NULL, false);
        $this-&gt;is_staff = FieldFactory::BooleanField(&amp;#8217;Staff&amp;#8217;, IS_REQUIRED, NOT_NULL, false);
        $this-&gt;is_admin = FieldFactory::BooleanField(&amp;#8217;Admin&amp;#8217;, IS_REQUIRED, NOT_NULL, false);
        $this-&gt;created = FieldFactory::DateTimeField(&amp;#8217;Created&amp;#8217;, NO_INDEX, IS_REQUIRED, NOT_NULL);
        $this-&gt;updated = FieldFactory::DateTimeField(&amp;#8217;Updated&amp;#8217;, NO_INDEX, IS_REQUIRED, NOT_NULL);
    }
}
</code></pre>

<p><code>FieldFactory</code> would have static methods for instantiating the correct field objects for each type. It would also have methods for generating constraints for implementing many-to-one and many-to-many relationships. I think a new model class is required to be able to do the additional magic without changing the current API.</p>

<p>I haven&#8217;t thought about how to implement the analogs of Admin and Meta inner-classes yet. I think those can be done as fields in the model, maybe <code>$this->__meta</code> and <code>$this->__admin</code>. As for QuerySets, Q objects and other classes in the Django DB API those are pretty much doable under PHP.</p>

<p>For SQL generation using the models, I imagine the backend will first load all the model classes found. Then models extending the MetaModel base class are instantiated and introspected to generate the correct DDL statements in database-specific SQL.</p>

<p>This is not a trivial undertaking and will take a lot of planning and thought. Model introspection and ORM should use as much of the existing CakePHP API as possible.</p>

<p>One last thing, if you are working on a similar system for CakePHP leave comments below. Remember: DRY.</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2007/two-months-working-with-django-wishing-cakephp-had-a-better-orm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP Modifications is on Temporary Hiatus</title>
		<link>http://abing.gotdns.com/posts/2007/cakephp-modifications-is-on-temporary-hiatus/</link>
		<comments>http://abing.gotdns.com/posts/2007/cakephp-modifications-is-on-temporary-hiatus/#comments</comments>
		<pubDate>Wed, 03 Jan 2007 02:15:36 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/posts/2007/cakephp-modifications-is-on-temporary-hiatus/</guid>
		<description><![CDATA[I&#8217;m going to take a break from my CakePHP modifications project. I am currently working on a project using the Python-powered framework, [Django][django]. Needless to say, just like CakePHP it&#8217;s been improving with each and every iteration. Though it&#8217;s not even in &#8220;1.0&#8243; yet, the features it currently sports are very impressive and, dare I [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to take a break from my CakePHP modifications project. I am currently working on a project using the Python-powered framework, [Django][django]. Needless to say, just like CakePHP it&#8217;s been improving with each and every iteration. Though it&#8217;s not even in &#8220;1.0&#8243; yet, the features it currently sports are very impressive and, dare I say, inspiring! However, PHP has been my bread and butter for close to 3 years now. Though I have so many gripes with PHP as a language, I still find it useful and it still gets the job done.</p>

<p>CakePHP modifications will continue once I finish my current project and once CakePHP 1.2.x.x gets sorted out.</p>

<p><span id="more-76"></span></p>

<p>It&#8217;s interesting to see the direction that CakePHP 1.2.x.x is currently taking. It seems that most of the functionality I&#8217;m am currently working on with my modifications for 1.1.x.x is in the works for 1.2.x.x. Here&#8217;s the short list of features that I really need:</p>

<ul>
<li><p>Lazy-loaded models (already backported into 1.1.x.x) &#8212; This was one of the major gripes that I had with CakePHP as it loads class files for models that you do not even use. This feature increases performance and reduces memory footprint for very large applications with a large number of models.</p></li>
<li><p>Validator classes &#8212; This new feature allows for more complex data validation while maintaining the DRY principle. I never liked the idea of using simple regex strings for data validators. What if I wanted to do more complex data validation? (e.g. query a user database if a username already exists) In my old framework, I used validator classes when handling form data. Each form field has its own validator chain and can include as many validator objects as it needs.</p></li>
<li><p>i18n and l10n &#8212; Because it&#8217;s a big world out there and not everyone speaks English. There is now the beginnings of an internationalization and localization API in the framework.</p></li>
<li><p>User Authentication &#8212; Although it&#8217;s not clear yet where this is going, I expect that there would be an extensible authentication framework with support for both simple authentication (username+password) and challenge-response authentication (username+password+challenge token).</p></li>
</ul>

<p>Now, if only they could throw in a &#8220;standard&#8221; regression and unit testing framework and add a generous smattering of metaprogramming constructs into the mix&#8230;</p>

<p>I have also been following a very interesting discussion with regards to [using the built-in system ACL in limiting user access to data][acl]. The current ACL system built into CakePHP uses what&#8217;s called MPTT or Modified Pre-ordered Tree Traversal to navigate through a network of ACO&#8217;s and ARO&#8217;s. I have made my own MPTT implementation for the object system in my new CMS.The code for this is not for the faint of heart. Yet, the flexibility that you end up with is well worth the effort.</p>

<p>The current discussion on the list about ACL&#8217;s made me look deeper into my MPTT implementation. From what I can gather, it will not scale very well as the number of objects increase as it uses a recursive algorithm when reordering the tree traversal data. So now I&#8217;m off to look for a better implementation&#8230;</p>

<p>[django]: http://www.djangoproject.com/ &#8220;Django Project Home&#8221;
[acl]: http://groups-beta.google.com/group/cake-php/browse_thread/thread/263d3ffd6fb7533d &#8220;Using ACL to limit access to data&#8221;</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2007/cakephp-modifications-is-on-temporary-hiatus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lazy Loaded Models for CakePHP</title>
		<link>http://abing.gotdns.com/posts/2006/lazy-loaded-models-for-cakephp/</link>
		<comments>http://abing.gotdns.com/posts/2006/lazy-loaded-models-for-cakephp/#comments</comments>
		<pubDate>Sun, 05 Nov 2006 16:02:38 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/posts/2006/lazy-loaded-models-for-cakephp/</guid>
		<description><![CDATA[I have been doing some recent profiling on CakePHP, the results look good despite the large amount of bootstrap code that it has to run with each request. However, I have observed one thing about the framework that could pose problems on servers with heavy traffic: the bootstrap process loads model class files even if [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>I have been doing some recent profiling on CakePHP, the results look good despite the large amount of bootstrap code that it has to run with each request. However, I have observed one thing about the framework that could pose problems on servers with heavy traffic: <em>the bootstrap process loads model class files even if the models are not used in the duration of the request.</em></p>

<p><span id="more-68"></span></p>

<p>Why would this be a problem? Depending on the PHP setup, either CGI binary or Apache module, the server could end up exhausting file handles under heavy traffic. This issue is even worse on a virtual hosting setup. Virtual hosting allows one to run a website for cheap by sharing a server with several other websites. Because of this shared environments, there is the increased risk of file handle exhaustion leading to failed requests not only for the CakePHP-based website, but for the other hosted websites as well.</p>

<p>CakePHP, by default, loads everything it finds in the <code>app/models</code> directory into memory: even if it&#8217;s not used for the duration of the request. The only reason I see why this is done is to ensure that associations work automagically. However, simply loading everything into memory can be wasteful. It wastes memory and processing time because the PHP engine has to load and parse all those files, even if most of it is &#8220;dead code&#8221; anyway. While this is not a problem in most setups, I have seen hosting services where they do &#8220;CPU utilization capping&#8221;.</p>

<p>As part of my ongoing project to improve on CakePHP to allow for porting of my old framework, I have decided to implement a modification that allows for lazy-loaded models in CakePHP. The modification has two goals in mind:</p>

<ol>
<li>Allow client code that depends on the mainstream CakePHP to work without problems;</li>
<li>Consequently, this allows the programmer to decide what gets to be loaded on each and <em>every</em> request and what gets to be lazy-loaded.</li>
</ol>

<p>To allow for goal number 1, I had to leave the bootstrap code alone. For number 2, I had to modify the way CakePHP models are instantiated from both the controller and the models themselves. The controller instantiates the appropriate model at runtime. A model <em>may</em> instantiate one or more models from its associations model. But how do you do lazy-loading and still allow for the old model loading behavior?</p>

<p>My solution is to create a new directory under the <code>app/models</code> directory called <code>lazy_load</code>. All models to be lazy_loaded will be placed here. Everything else can stays in <code>app/models</code>.</p>

<p>A new function had to be created to perform the task of lazy loading. The <code>lazyLoadModel()</code> function in the <code>basics.php</code> file takes care of the task. It behaves a fashion similar to <code>loadModel()</code> by loading models from the <code>lazy_loaded</code> directory found in the <code>modelPaths</code>.</p>

<h3>Show Me The Code</h3>

<p>The changeset for this modification can be found [here][cs-1]. This should apply cleanly to CakePHP version 1.1.8.3544. It should also apply cleanly to version 1.1.10.3825. If you are still using 1.1.8.3544, then you should upgrade to 1.1.10.3825 <em>before</em> applying this patch. Otherwise, you will end up having to manually resolve conflicts. Of course, if you apply this modification, you will end up having to re-apply it with each new version of CakePHP.</p>

<h3>Does it work?</h3>

<p>I have done a bit of profiling on an example app based on the [Blog tutorial][cake-blog-tut] from the CakePHP Manual as well as tests using [Siege][joedog-siege]. For this test, I created 10 dummy model class files and placed them under the <code>app/models</code> directory as usual and then I ran the profiler from my demo version of Zend IDE. As expected, CakePHP loads everything it can find under the <code>app/models</code> directory and chews up processing time, memory and file handles. The Zend IDE profiler reports that it had to open at least 50 files for the blog app home page.</p>

<p>With Siege, with 100 concurrent requests and with 10000 reps per connection (resulting in 1,000,000 hits total), the server began to cave after the first 4,000 hits and continued to slowdown to at most 40 to 70 seconds on a lot of requests. I was not sure if there were any file handle exhaustion errors since Siege is not able to display the actual page that it requested.</p>

<p>For the second test, I moved all the dummy classes from <code>app/models</code> to <code>app/models/lazy_load</code> I also did the same for the classes that are actually used by the app (post.php and tag.php). First the Zend IDE profiler reports only 40 files are being opened for each request. With Siege, under the same settings as before, the server was able to make it through the ordeal slowing down to 10 to 20 seconds on some requests after about 700,000 hits.</p>

<p>For me, it&#8217;s a significant improvement. But you don&#8217;t have to take my word for it so go do your own tests and let me know about your results.</p>

<h3>Caveats</h3>

<p>This is a modification on the mainstream CakePHP code. Which means if anything changes on the mainstream, this modification may also be affected. If you apply the patch to future versions of CakePHP and it results in failed hunks, then you should check what went wrong and take the necessary steps to correct the problem.</p>

<p>Theoretically, the lazy loader should work for plugins too. But I have not tried it yet.</p>

<h3>Conclusion</h3>

<p>If you like this modification and use it in your production site, please leave a comment here and let me know what you think.</p>

<p>This and other modifications I am making are being made independently from the CakePHP project. As such, you should <em>never</em> report problems you encounter with my modifications to either the CakePHP mailing list or IRC channel. Please report them directly to me.</p>

<p>If you want to send bug fixes or suggestions for improvement, please send email to:</p>

<p>&#110;&#105;&#109;&#114;&#x6F;&#x64;&#x2E;&#x61;&#98;&#105;&#110;&#x67;&#43;&#x62;&#x6C;&#111;&#103;&#x40;&#103;&#109;&#97;&#105;&#x6C;&#x2E;&#x63;&#111;&#x6D;</p>

<p>Please use the subject line:</p>

<p>PATCH: CakePHP Model Lazy Loader</p>

<p>[cs-1]: http://abing.gotdns.com/cake/diffs/000010-lazy-loaded-models.diff &#8220;Changeset for lazy loaded models in CakePHP&#8221;
[cake-blog-tut]: http://manual.cakephp.org/appendix/blog_tutorial &#8220;CakePHP Blog Tutorial&#8221;
[joedog-siege]: http://www.joedog.org/JoeDog/Siege &#8220;JoeDog.org: Siege&#8221;</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2006/lazy-loaded-models-for-cakephp/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Themeable View Class for CakePHP</title>
		<link>http://abing.gotdns.com/posts/2006/themeable-view-class-for-cakephp/</link>
		<comments>http://abing.gotdns.com/posts/2006/themeable-view-class-for-cakephp/#comments</comments>
		<pubDate>Mon, 11 Sep 2006 07:02:38 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/2006/09/11/54/</guid>
		<description><![CDATA[This is my implementation of a themeable view class for CakePHP. This
class will allow your site to use themes or skins. Themes or skins are
a great feature because they allow for division of labor between the
developer and the designer (although the designer in this case has
to know a bit of PHP). They also allow the [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>This is my implementation of a themeable view class for CakePHP. This
class will allow your site to use themes or skins. Themes or skins are
a great feature because they allow for division of labor between the
developer and the designer (although the designer in this case has
to know a bit of PHP). They also allow the website owner to quickly
change the look and feel of the website.</p>

<p>The ThemeableView class here is part of the CMS that I am currently
working on.</p>

<p><em>Updated to Version 1.0.6</em></p>

<p>See this <a href="cakephp-1.2.x.x">usage notes for CakePHP 1.2.x.x</a> users.</p>

<p><span id="more-54"></span></p>

<p>Download the package here:</p>

<p><a id="p85" href="http://abing.gotdns.com/wp-content/uploads/2007/04/themeableview-106.zip">ThemeableView-1.0.6.zip</a></p>

<p><a href="#changelog" title="Internal ChangeLog">What's new in 1.0.6?</a></p>

<p>Yes, I am aware of another themeable view class for CakePHP which can
be found <a href="http://cakeforge.org/snippet/detail.php?type=snippet&#038;id=18" title="ThemeView by Larry E. Masters aka phpnut">here</a>. However there are two problems that I have
with that implementation which forced me to write my own class:</p>

<ol>
<li><p>The class file is licensed under the <a href="http://www.nextco.com/licenses/oppl/" title="Open Project Public License">OPPL</a>. As far as I can
tell, the OPPL seems to prohibit commercial use (see OPPL Section 3b
and Section 4a).</p>

<p>It is also unclear whether or not the OPPL is viral when OPPL 
licensed code is used to create a &#8220;Combined Work&#8221;. It is also unclear
how the OPPL interacts with the GPL, LGPL and other licenses.</p>

<p>I have written to Larry E. Masters about this but I have not gotten
any response from him so far.</p></li>
<li><p>Theme elements are spread out in separate directories under app/views.
This makes it less than ideal for large sites with a lot of controllers
and actions.</p></li>
</ol>

<p>For instance, if you have a theme named &#8216;MyTheme&#8217; you will have to create
the following directory structure in app/views:</p>

<pre><code>app/views/elements/MyTheme
app/views/errors/MyTheme
app/views/layouts/MyTheme
app/views/controller_name/MyTheme
</code></pre>

<p>The first three directories present very little problems. However, with
several controllers it will be taxing to have to create a MyTheme folder
for each controller. Things get even messier when you use plugins:</p>

<pre><code>app/plugins/MyPlugin/views/elements/MyTheme
app/plugins/MyPlugin/views/errors/MyTheme
app/plugins/MyPlugin/views/layouts/MyTheme
app/plugins/MyPlugin/views/controller_name/MyTheme
</code></pre>

<p>This can be a nightmare for theme maintainers since there can be a lot
of themeable elements to keep track of and they are all over the place.</p>

<p>My implementation solves problem #1 by licensing ThemeableView under the
MIT License. This is the same license used by CakePHP itself. Which means
you can do pretty much anything with this code: use it in commercial apps,
sublicense it (change the license terms), use it to bring world peace&#8230;</p>

<p>The only thing the MIT License <em>disallows</em> you to do is to remove the
copyright notice from the code.</p>

<p>If you look at the code for the class itself, you will notice that it
sort of resembles phpnut&#8217;s code. Before you go off and yell profanities
at me, you should know that I contributed to phpnut&#8217;s ThemeView as well.
Another thing is that my code is based on the View class itself, being
that ThemeView and View are written by the same person, then there <em>is</em>
bound to be similarities. This is aside from the fact that with the
way CakePHP is structured, it is very hard to produce truly unique code.</p>

<p>For problem #2, all themes are placed in a themes directory under
the app/ directory. Each theme is in its own directory. So using the
MyTheme example above:</p>

<pre><code>app/themes/MyTheme/views/elements
app/themes/MyTheme/views/errors
app/themes/MyTheme/views/layouts
app/themes/MyTheme/views/controller_name
</code></pre>

<p>Even with plugins:</p>

<pre><code>app/themes/MyTheme/plugins/MyPlugin/views/elements
app/themes/MyTheme/plugins/MyPlugin/views/errors
app/themes/MyTheme/plugins/MyPlugin/views/layouts
app/themes/MyTheme/plugins/MyPlugin/views/controller_name
</code></pre>

<p>Everything that the theme requires to render all the views in your app
is placed inside the <code>MyTheme</code> directory. In addition, you can also include
other resources with the theme such as images, icons, Javascript, and
CSS stylesheets. <em>These need to be placed in a location that is accessible
on your webserver</em>. This means you should place theme resources under
the <code>themes/MyTheme</code> directory in your webroot directory. For example, if
your webroot is under your app (as in the default setup):</p>

<pre><code>app/webroot/themes/MyTheme/css
app/webroot/themes/MyTheme/js
app/webroot/themes/MyTheme/images
app/webroot/themes/MyTheme/icons
</code></pre>

<p>Then from your templates, simply do:</p>

<pre><code>&lt;link href="&lt;? $this-&gt;getThemeablePath('css', 'mystyle.css') ?&gt;" type="text/css" rel="stylesheet" /&gt;
&lt;script language="Javascript" type="text/javascript" src="&lt;? $this-&gt;getThemeablePath('js', 'myscripts.js') ?&gt;" /&gt;
&lt;img src="&lt;? $this-/&gt;getThemeablePath('images', 'myimage.gif') ?&gt;" /&gt;
&lt;img src="&lt;? $this-/&gt;getThemeablePath('icons', 'myicon.gif') ?&gt;" /&gt;
</code></pre>

<h4>New in 1.0.4</h4>

<p><em>As of version 1.0.4, a new ThemeHelper class is available. This class
contains theme-aware versions of the css() and image() methods found
in the HtmlHelper class. You can use this instead of having to write
the tags by hand as above. See the ThemeHelper PHPDocs for details.</em></p>

<p>To use this class, place the file named themeable.php inside app/views.</p>

<p>Then, from your controller set <code>view</code> to "Themeable". Then set
the current theme as a property <code>themeName</code>:</p>

<pre><code>var $view = 'Themeable';
var $themeName = 'MyTheme';
</code></pre>

<p>Or you can create your own app_controller class and define the
<code>view</code> and <code>themeName</code> properties so that all
controllers in your application will be using them.</p>

<p>There are two constants that point to the location of your themes and
theme resources.</p>

<ul>
<li><p>THEMES - point to the absolute path on your webserver's filesystem
where your theme templates are stored.</p>

<p>Default: APP . 'themes' . DS</p></li>
<li><p>THEME_RESOURCES - point to the relative path on your website's URL
where your theme resources are stored.</p>

<p>Default: DS . 'themes' . DS</p></li>
</ul>

<p>You can define these to point elsewhere depending on your setup.</p>

<p>I hope someone finds this useful. If you have any questions or comments
please leave them on this post. My apologies for the slight inconvenience
of required registration. There has been a string of spambot activity on
my site recently.</p>

<p>If you have patches to this code, they are very much welcome. Send them to:</p>

<p>&#110;&#105;&#109;&#114;&#x6F;&#x64;&#x2E;&#x61;&#98;&#105;&#110;&#x67;&#43;&#x62;&#x6C;&#111;&#103;&#x40;&#103;&#109;&#97;&#105;&#x6C;&#x2E;&#x63;&#111;&#x6D;</p>

<p>Please use the subject line:</p>

<p>PATCH: ThemeableView class</p>

<p><a name="cakephp-1.2.x.x"></a></p>

<h3>Notes For CakePHP 1.2.x.x</h3>

<p>This one comes from PJ Hile. Some API changes have taken place in CakePHP 1.2.x.x and naturally this equates to some changes in the themable view class as well. However, at the time of this update (13 Jun 2007) CakePHP 1.2.x.x is still in Alpha stage. That pretty much means that the API is still subject to change so this may or may not work for you depending on your current 1.2.x.x snapshot. Here's the full text of the email I got from PJ:</p>

<p>On 6/13/07, PJ Hile wrote:</p>

<blockquote>
  <p>Just some updates for those using CakePHP 1.2.x.x</p>
  
  <ol>
  <li>$this->_viewVars has been changed to $this->viewVars  (lines 242 and 260)</li>
  <li>strip_plugin() has been moved to Router::stripPlugin() (line 183)</li>
  </ol>
  
  <p>Hopefully that will save some people some time.</p>
  
  <p>Regards,
  PJ</p>
</blockquote>

<p><a name="changelog"></a></p>

<h3>Internal ChangeLog</h3>

<h4>21 April 2007 - Version 1.0.6</h4>

<p>Download: <a id="p85a" href="http://abing.gotdns.com/wp-content/uploads/2007/04/themeableview-106.zip">ThemeableView-1.0.6.zip</a></p>

<ul>
<li><p>Match themeable view locations between website pages and phpdoc. (Peppe Bergqvist)</p></li>
<li><p>Fix filename mangling when falling back to 'system' theme in <code>Themeable::themeElement()</code>.
(Peppe Bergqvist)</p></li>
<li><p>Change behavior of Themeable::themeElement() to match new behavior in View::element().
Client code that relied on the old behavior should now use Themeable::_getThemeableElement()
instead.</p></li>
</ul>

<h4>19 April 2007 - Version 1.0.5</h4>

<p>Download: <a id="p84a" href="http://abing.gotdns.com/wp-content/uploads/2007/04/themeableview-105.zip">ThemeableView-1.0.5.zip</a></p>

<ul>
<li>Fixed recursive method invocation for View::element() whose behavior
was changed in revision <a href="https://trac.cakephp.org/changeset/4050/trunk/cake/1.x.x.x/cake/libs/view/view.php" title="Revision 4050">4050</a>. Special thanks to Peppe Bergqvist
for discovering, reporting and investigating this bug.</li>
</ul>

<h4>07 October 2006 - Version 1.0.4</h4>

<p>Download: <a id="p61a" href="http://abing.gotdns.com/wp-content/uploads/2006/10/themeableview-104.zip">ThemeableView-1.0.4.zip</a></p>

<ul>
<li><p>Use / instead of DS in getThemeablePath() and THEME_RESOURCES. (thanks
to Ryan Clark)</p></li>
<li><p>Fix viewPath resolution logic in _getViewFileName to include 'system'
theme.</p></li>
<li><p>Provide documentation in the PHPDoc comments.</p></li>
<li><p>Added new ThemeHelper class to provide theme-aware analogs to css() and image()
methods in HtmlHelper.</p></li>
</ul>

<h4>06 October 2006 - Version 1.0.3</h4>

<p>Download: <a id="p60a" href="http://abing.gotdns.com/wp-content/uploads/2006/10/themeableview-103.zip">ThemeableView-1.0.3.zip</a></p>

<ul>
<li><p>Fix _getLayoutFilename() logic when the view attempts to search for a
usable view layout file. (thanks to Ryan Clark)</p></li>
<li><p>Added absoluteURL() method and use it for getThemeablePath() so that
it returns the correct path to a themeable resource regardless of where
CakePHP is currently installed.</p></li>
</ul>

<h4>25 September 2006 - Version 1.0.2</h4>

<p>Download: <a id="p58" href="http://abing.gotdns.com/wp-content/uploads/2006/09/themeableview-102.zip">ThemeableView-1.0.2.zip</a></p>

<ul>
<li><p>Move theme resources to webroot to allow for setups where
the app dir is in a location that is not accessible through the webserver.</p></li>
<li><p>Conditionally define THEMES constant to allow user to define an alternate
location.</p></li>
<li><p>Add a new conditionally defined constant THEME_RESOURCES to point to
the relative URL of resources provided by the current theme.</p></li>
</ul>

<h4>15 September 2006 - Version 1.0.1</h4>

<p>Download: <a id="p57" href="http://abing.gotdns.com/wp-content/uploads/2006/09/themeableview-101.zip">ThemeableView-1.0.1.zip</a></p>

<ul>
<li><p>Fix theme fallback mechanisms. If a theme resource is not found in the
current theme, it will try to search in themes/system.</p></li>
<li><p>Fix bugs in plugin and element theme resource searching.</p></li>
</ul>

<h4>11 September 2006 - Version 1.0.0</h4>

<ul>
<li>Initial release.</li>
</ul>

<p>a</p>

<p></script></link></p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2006/themeable-view-class-for-cakephp/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>CakePHP: Delegating Actions to Separate Classes Flowchart</title>
		<link>http://abing.gotdns.com/posts/2006/cakephp-delegating-actions-to-separate-classes-flowchart/</link>
		<comments>http://abing.gotdns.com/posts/2006/cakephp-delegating-actions-to-separate-classes-flowchart/#comments</comments>
		<pubDate>Mon, 14 Aug 2006 18:37:41 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/2006/08/15/52/</guid>
		<description><![CDATA[Here is a simplified flowchart illustrating how the ActionClass-aware custom dispatcher works.

Click on the thumbnail above to view the full image.

a
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>Here is a simplified flowchart illustrating how the ActionClass-aware custom dispatcher works.</p>

<p><a class="imagelink" href="http://abing.gotdns.com/wp-content/uploads/2006/08/cake-diffs.png" title="CakePHP: Custom Dispatcher Flowchart"><img id="image51" src="http://abing.gotdns.com/wp-content/uploads/2006/08/cake-diffs.thumbnail.png" alt="CakePHP: Custom Dispatcher Flowchart" /></a></p>

<p>Click on the thumbnail above to view the full image.</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2006/cakephp-delegating-actions-to-separate-classes-flowchart/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP: Delegating Actions to Separate Classes</title>
		<link>http://abing.gotdns.com/posts/2006/cakephp-delegating-actions-to-separate-classes/</link>
		<comments>http://abing.gotdns.com/posts/2006/cakephp-delegating-actions-to-separate-classes/#comments</comments>
		<pubDate>Sun, 06 Aug 2006 19:47:27 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/2006/08/07/49/</guid>
		<description><![CDATA[I have just finished one of my most important modifications to CakePHP. In my old framework, I used a similar pattern where in a request is handled as a &#8220;mode&#8221; plus an &#8220;command&#8221; with optional parameters. This is similar in spirit to CakePHP&#8217;s controller/action way of doing things. In my implementation however, commands (analogous to [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>I have just finished one of my most important modifications to CakePHP. In my old framework, I used a similar pattern where in a request is handled as a &#8220;mode&#8221; plus an &#8220;command&#8221; with optional parameters. This is similar in spirit to CakePHP&#8217;s <code>controller/action</code> way of doing things. In my implementation however, commands (analogous to CakePHP actions) are implemented using separate classes.</p>

<p>While some may argue that this manner of implementing MVC is overkill in typical applications, in very large applications (like PhilWeavers.net) it leads to very quick turn-around when it comes to adding new actions or modifying existing ones.</p>

<p><span id="more-49"></span></p>

<p>The full ChangeLog entry pretty much sums it all up:</p>

<blockquote>
  <p>This modification allows the client code to implement actions in separate
  classes. It is comprised of two parts:</p>
  
  <ol>
  <li><p>A custom dispatcher capable of loading an Action class if action is not
  found to be in the controller&#8217;s methods.</p></li>
  <li><p>An Action base class.</p></li>
  </ol>
  
  <p>Rationale:</p>
  
  <p>Implementing actions as methods of the controller class can become unwieldy
  especially with very large applications. Most of the time, only one of
  those action methods is invoked. The PHP engine still has to parse through
  the whole controller class file.</p>
  
  <p>By moving out the actions into separate class files that are loaded on
  demand the overhead of parsing through a large file consisting mainly of
  dead code is avoided.</p>
  
  <p>Because an action class is self-contained, it is now safe to implement
  a more structured approach in implementing methods through the use of
  small helper methods in the action class.</p>
  
  <p>Full Description:</p>
  
  <p>First and foremost, the goal of this modification is to be backwards
  compatible with existing code. This will help in migration towards using
  action classes.</p>
  
  <p>Secondly, missing action classes must not disrupt the normal dispatching
  of the request. Missing action classes will not trigger a special error.
  Instead, the usual &#8220;Missing Method in Controller&#8230;&#8221; errors will be
  generated.</p>
  
  <p>Finally, plugins should be able to use action classes as well.</p>
  
  <p>How to implement an action class-based CakePHP app:</p>
  
  <ol>
  <li><p>Edit app/config/core.php and set CUSTOM_DISPATCHER to &#8216;acDispatcher&#8217;.</p></li>
  <li><p>For each controller create a folder in app/controllers/ with the same
  name as the controller following the usual CakePHP naming conventions.</p></li>
  <li><p>Override app_action.php if desired. Place your custom app_action.php
  in app/app_action.php.</p></li>
  <li><p>Create an action class file inside app/controllers/controller_name. We
  also follow the CakePHP naming conventions here.</p></li>
  <li><p>Implement the method perform() in your action class. This is the same
  as creating an action as a method in your controller. If your action
  accepts parameters, specify them as such in the parameter list for
  perform().</p></li>
  </ol>
  
  <p>For example:</p>
  
  <p>http://example.com/ctrl/index/</p>
  
  <p>Create the directory app/controllers/ctrl</p>
  
  <p>Create the file app/controllers/ctrl/index_action.php</p>
  
  <p>Define IndexAction in index_action.php defining the perform() method.</p>
  
  <p>Notes:</p>
  
  <ul>
  <li><p>You get a reference to the controller in $this->controller.</p></li>
  <li><p>All the properties of the controller can also be referenced in the
  context of the action itself. For instance, the $uses property is also
  available as a reference using $this->uses.</p></li>
  </ul>
  
  <p>For plugins, simply follow the usual conventions as above in addition to
  the CakePHP plugin conventions.</p>
</blockquote>

<p>I wish to clarify to any CakePHP users who might stumble upon this (and my other modifications) that this modification is meant to serve as a transition point for me to allow me to port my apps to CakePHP from my previous framework.</p>

<p>Also note that this is the first commit of this modification and there may be bugs. If you encounter any, please <strong>DO NOT</strong> report them to the CakePHP developers nor the CakePHP Google Group. Leave a comment here if you wish to file a bug report.</p>

<p>Lastly: <em>Experimental code. Caveat Programmor</em></p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2006/cakephp-delegating-actions-to-separate-classes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Modified CakePHP</title>
		<link>http://abing.gotdns.com/posts/2006/modified-cakephp/</link>
		<comments>http://abing.gotdns.com/posts/2006/modified-cakephp/#comments</comments>
		<pubDate>Sat, 08 Jul 2006 21:02:00 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/2006/07/09/41/</guid>
		<description><![CDATA[I have recently begun working on a series of modifications for CakePHP. The primary purpose of these modifications is to provide an easier migration path for my old web projects. I have made them available both as a series of patches and as a downloadable Darcs repository.

Updated: 6 Dec 2006

NOTE: Instructions for applying individual diffs [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>I have recently begun working on a series of modifications for CakePHP. The primary purpose of these modifications is to provide an easier migration path for my old web projects. I have made them available both as a series of patches and as a downloadable Darcs repository.</p>

<p><em>Updated: 6 Dec 2006</em></p>

<p><span id="more-41"></span></p>

<p><strong>NOTE:</strong> Instructions for applying individual diffs found here are <em>incorrect</em>. [Read this][correctinsns] if you want to apply patches individually. This article is kept mostly unedited for archive purposes.</p>

<p>First off, these modifications started out as a set of patches to make porting between my old framework and CakePHP much easier. They may not be useful for you. Another thing to note is that these patches are made against the latest Subversion version of CakePHP. With that in mind, you might be better off using the official releases of CakePHP [found here][cakephp].</p>

<p>Secondly, some of these patches <em>might</em> break compatibility with the official CakePHP. However, I have taken great care to maintain compatibility with the official releases as much as possible. If a patch introduces features or modifications that could break compatibility, it will be indicated in the patch description.</p>

<h3>Applying the Patches</h3>

<p>You have two options of applying the patches. The recommended (and easiest) way is to download them using [darcs][darcsweb]. The second way is to download CakePHP from the offical Subversion repository and then apply the patches using <code>diff</code>.</p>

<p>Since the second way requires a bit more work, I will describe how to do it first. (EDIT: I highly recommend using the prepatched version found [here][prepatched] instead of applying each patch individually or use the darcs repository.)</p>

<h4>Applying Patches with <code>diff</code></h4>

<ol>
<li><p>Download the patch set [here][diffs]. You can either individually download the patches you need. Or download the tarball all.tar.gz.</p></li>
<li><p>Download the official CakePHP from the Subversion repository. Instructions can be found [here][cakeman3] (see section 2). Make sure you get the latest revision indicated in the diffs [README.html][diffsreadme]. (EDIT: The README.html now has a table showing which patch <em>should</em> apply cleanly to which SVN revision.)</p></li>
<li><p>Using the Gnu Patch program, apply the patches.</p></li>
</ol>

<p>Assuming you have downloaded the CakePHP and you have it under the directory <code>cake</code> and the patches in the directory immediately above it, here is an example command line session (Unix):</p>

<pre><code>$ cd cake
$ patch -p1 &lt; ../&lt;name of patch&gt;.diff
</code></pre>

<p>The patches are numbered sequentially, in the order that they were committed to the darcs repository. So you should apply them in sequence since one patch might depend on another. If one patch does not apply cleanly, you should remove it (EDIT: Or resolve the conflicts manually). Otherwise, you may end up with a broken CakePHP.</p>

<h4>Using the <code>darcs</code> Repository</h4>

<p>Now for the recommended way of downloading the patches.</p>

<ol>
<li><p>Get [darcs][darcsweb]. There are binaries for many operating systems, choose one that is appropriate for you.</p></li>
<li><p>From the command line (Unix), issue the command:</p>

<pre>$ darcs get http://abing.gotdns.com/darcs/repos/cake</pre>

<p>That should pull in <em>all</em> the patches and give you an up-to-date tree. If you only want to pull in a specific patch:</p></li>
<li><p>From the command line (Unix), issue the command:</p>

<pre>$ darcs get --tag='CakePHP-v-1.1.' http://abing.gotdns.com/darcs/repos/cake</pre></li>
<li><p>Then look at the [ChangeLog][changelog] and search for the patch name that you want to pull.</p></li>
<li><p>Make sure you are in the local repository directory. From the command line (Unix), issue the command:</p>

<pre>$ darcs pull --patch='PATCH NAME'</pre></li>
</ol>

<p>Darcs will pull in the patch that matches the PATCH NAME you specified <em>along with any other patches that it depends upon</em>.</p>

<h3>A Few Thoughts About Darcs</h3>

<p>You may be wondering, CakePHP already uses version control software (Subversion), why use darcs?</p>

<p>I have been using [David's Advanced Version Control System][darcsweb] (darcs) for all of my projects for over two years now. CakePHP uses Subversion, I think only because it works well with Trac. Using darcs instead of subversion is entirely my own choice.</p>

<p>Darcs is what is known as a &#8220;Distributed SCM&#8221; which is vastly different from the way CVS (and Subversion) does things. There are a few things to note, especially for long-time CVS or Subversion users.</p>

<p>First off, you will notice that <em>there are no revision or version numbers in darcs</em>. It may come as a surprise to you, especially is you have been using CVS or Subversion for a long time. Version numbers are useless under darcs because of its &#8220;distributed&#8221; nature. Instead we use &#8220;Patch Names&#8221;. A patch name is just a short string used to identify a specific commit.</p>

<p>Secondly, your copy of the remote repository is a <em>complete repository</em>. Which means you can <code>record</code> or commit your own changes without having to connect to the remote repository. Your recorded patches remain in <em>your</em> repository, unless you <code>send</code> them to me so that I can <code>apply</code> them. This is where the &#8220;distributed&#8221; nature of darcs comes into play. It allows you to make changes in your local repository and <em>commit</em> them locally, thereby providing you with a complete record of the changes you made.</p>

<p>Lastly, darcs has a feature that reduces the burden of tracking down who made which changes. By setting your name and email address in the <code>_darcs/prefs/author</code> configuration file in your local copy, all commits made in your repository will be tagged with your name and email address. When the ChangeLog is generated, all patches that you send to me that I applied to my repository will automatically contain your name and email address.</p>

<p>Those who are familiar with darcs will probably wonder why I did not use <code>tailor.py</code> to migrate patches back and forth between the Subversion repository and my darcs repository. This is because I do not expect these patches to make it into the mainstream CakePHP code, so why bother? Most of the patches I made are necessary for my purposes, but may not be useful in the general use-cases for CakePHP.</p>

<p>I also wanted to be able to start from a single recent SVN snapshot (I don&#8217;t need the pre-1.0 stuff). This reduces the amount of space I need for the repository. I have a 300MB disk quota on the server hosting the remote repository, so every bit of space savings counts. This is also why you will only see the <code>_darcs</code> directory (without the <code>pristine</code> directory) on the server.</p>

<h3>Patch Descriptions</h3>

<p>Aside from maintaining compatibility with the mainstream CakePHP, I have made it easier to determine what a patch does based on its name. However, one can only say so much in a patch name so a longer description of the patch is necessary. I have made use of the following convention when entering patch descriptions:</p>

<p>[optional introductory text]</p>

<p>Rationale:</p>

<p>[explanation of why this patch is necessary]</p>

<p>Full Description:</p>

<p>[full documentation about what this patch does and what it affects as well API changes that it introduces]</p>

<p>[optional notes on compatibility]</p>

<h3>The Future</h3>

<p>This is just the beginning of a series of articles and patches for CakePHP as I continue to port my old projects to this new framework. Though I do not really expect these patches to make it into the mainstream CakePHP tree, it would be great if some of the patches make it.</p>

<p>You may also find that some of these patches won&#8217;t do anything useful for you. As one saying goes, &#8220;If you don&#8217;t know what it does, then you probably don&#8217;t need it.&#8221; This is most certainly true for many of the patches that you will find here. Read the description first if the patch name does not give you enough of an overview as to what a patch does.</p>

<p>[cakephp]: http://cakephp.org/ &#8220;CakePHP Official Website&#8221;
[darcsweb]: http://darcs.net/ &#8220;Darcs Website&#8221;
[cakeman3]: http://manual.cakephp.org/chapter/3 &#8220;CakePHP Manual Chapter 3&#8243;
[diffs]: http://abing.gotdns.com/cake/diffs/ &#8220;CakePHP diffs&#8221;
[diffsreadme]: http://abing.gotdns.com/cake/diffs/README.html &#8220;diffs README.html&#8221;
[changelog]: http://abing.gotdns.com/cake/diffs/changes.xml &#8220;ChangeLog for CakePHP modifications&#8221;
[correctinsns]: http://abing.gotdns.com/cake/diffs/README.html &#8220;Correct way to apply individual patches&#8221;
[prepatched]: http://abing.gotdns.com/cake/diffs/cake-diffs-latest.tar.gz &#8220;Pre-patched CakePHP&#8221;</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2006/modified-cakephp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Have some cake&#8230;</title>
		<link>http://abing.gotdns.com/posts/2006/have-some-cake/</link>
		<comments>http://abing.gotdns.com/posts/2006/have-some-cake/#comments</comments>
		<pubDate>Mon, 08 May 2006 06:48:41 +0000</pubDate>
		<dc:creator>nimrod.abing</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Code and Consequences]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://abing.gotdns.com/2006/05/08/27/</guid>
		<description><![CDATA[On May 4, 2006 one of the projects that I had been watching made the announcement that it has finally made a 1.0 release. After a long incubation period, it&#8217;s finally here&#8230; and it ROCKS!

I have been keeping close watch on the [CakePHP][cakehome] project for quite some time now. Ever since all the hype and [...]
<p>a</p>
]]></description>
			<content:encoded><![CDATA[<p>On May 4, 2006 one of the projects that I had been watching made the announcement that it has finally made a 1.0 release. After a long incubation period, it&#8217;s finally here&#8230; and it ROCKS!</p>

<p><span id="more-27"></span></p>

<p>I have been keeping close watch on the [CakePHP][cakehome] project for quite some time now. Ever since all the hype and hoopla for [Ruby on Rails][rorhome] exploded on the Internet, I wanted to see a similar framework for PHP and that&#8217;s when I discovered CakePHP (which was still in version 0.10.x). RoR is good but there are a few barriers to entry for me with this framework:</p>

<ol>
<li>Not a lot of hosting providers that support RoR out of the box, most of them offer RoR as an installable option or &#8220;uppgrade&#8221; for extra $$$.</li>
<li>Documentation for the framework is a bit dodgy in some areas, though it&#8217;s improving constantly.</li>
<li>The tutorials seem to speak of older RoR versions and focus primarily on the &#8220;scaffolding&#8221; feature of the framework. Though I think this has been revised already.</li>
<li>I have to force myself to learn Ruby, not necessarily a bad thing but I prefer to stick with what I already know for production projects.</li>
<li>I have tried installing and configuring a running server (not using webrick) and even with FastCGI, it&#8217;s still not as fast as PHP. Performance is really important to me and it seems it requires way too much work to get RoR running as fast as my current PHP-based framework (also using the MVC-pattern).</li>
</ol>

<p>With CakePHP, I get most of what RoR currently offers without having to go through extra lengths that I had to go through with RoR to &#8220;just get things working&#8221;.</p>

<p>I like the fact that the CakePHP docs are honest in admitting that the scaffolding feature, while impressive during demos, are not really meant to be used in production work. RoR seems to push the scaffolding feature as one of their main selling points, which has led some newbie users into thinking that it was suited for production apps. From the CakePHP manual:</p>

<blockquote><b>Cake&#8217;s scaffolding is pretty cool</b><br /><br />

So cool that you&#8217;ll want to use it in production apps. Now, we think its cool, too, but please realize that scaffolding is&#8230; well&#8230; just scaffolding. Its a bunch of stuff you throw up real quick during the beginning of a project in order to get started. It isn&#8217;t meant to be completely flexible. So, if you find yourself really wanting to customize your logic and your views, its time to pull your scaffolding down in order to write some code.</blockquote>

<p>I tried out the [Blog Tutorial][cakeblog] and in less than 15 minutes I was able to finish it with everything working exactly as advertised.</p>

<p>It&#8217;s interesting to see what CakePHP-based applications others will come up with in the next few months. Personally, I am planning to rework my existing CMS framework to use CakePHP. I think it will be worth the effort, as it was certainly worth the wait for the 1.0 release.</p>

<p>[cakehome]: http://www.cakephp.org/ &#8220;CakePHP Home&#8221;
[rorhome]: http://www.rubyonrails.org/ &#8220;Ruby on Rails Home&#8221;
[cakeblog]: http://manual.cakephp.org/chapter/17 &#8220;CakePHP Blog Tutorial&#8221;</p>

<p>a</p>
]]></content:encoded>
			<wfw:commentRss>http://abing.gotdns.com/posts/2006/have-some-cake/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
