Plugin loading quirks

On a daily basis I will receive emails pertaining to my Admin plugin, Utility plugin or my Forum plugin. Most of the time the problem they are having is related to plugin loading, and the failure to bootstrap or apply routes. But loading plugins is easy! One would think so, it does look pretty straight forward, but there are some weird cases where loading just does not work as you would assume.

In my documentation, I state that plugin loading should be done after CakePlugin::loadAll(), for the reasons listed below.

Using loadAll()

By default, CakePlugin::loadAll() does not include bootstrap or routes files. Passing an array with bootstrap and routes set to true will include them, but any plugin that does not have those files will throw missing errors. A setting ignoreMissing was added in CakePHP 2.3.0 to solve this. This approach works correctly, but not for versions below 2.3.0.

CakePlugin::loadAll(array(
	array('bootstrap' => true, 'routes' => true, 'ignoreMissing' => true)
));
Calling loadAll() last

One would think that calling CakePlugin::loadAll() after other plugins would work normally, but that's wrong. When called this way, previously loaded routes will be reset. This happens because loadAll() cycles through each plugin and re-loads them (even if a plugin was already loaded), and since both bootstrap and routes are false by default (point above) in loadAll(), the values get reset. Honestly, I believe this to be a bug in CakePHP, so when I have time I will track it down. Currently, this approach does not work correctly.

CakePlugin::load('Utility', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Admin', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Forum', array('bootstrap' => true, 'routes' => true));
CakePlugin::loadAll();
Calling loadAll() first

If calling it last doesn't work correctly, then calling it first will. By calling CakePlugin::loadAll() first, all the problems listed in the point above are invalid and plugin loading works correctly. Both routes and bootstrapping successfully triggers. This approach works correctly.

CakePlugin::loadAll();
CakePlugin::load('Utility', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Admin', array('bootstrap' => true, 'routes' => true));
CakePlugin::load('Forum', array('bootstrap' => true, 'routes' => true));
Passing an array to load()

Many don't know this, but an array of plugins can be passed to CakePlugin::load(). I tried many different combinations with no failures. This approach works correctly.

CakePlugin::load(array(
	'Uploader',
	'Utility' => array('bootstrap' => true, 'routes' => true),
	'Admin' => array('bootstrap' => true, 'routes' => true),
	'Forum' => array('bootstrap' => true, 'routes' => true)
));
CakePlugin::load(
	array('Utility', 'Admin', 'Forum'),
	array('bootstrap' => true, 'routes' => true)
);
How did you debug this?

It was rather easy. In Config/bootstrap.php I would attempt different variations of plugin loading to test the outcome. In my controller I had a few debug() statements that spit out Configure and Router information to verify that loading was working.

debug(App::objects('plugin'));
debug(Configure::read());
debug(Router::$routes);

Changelogs: Uploader v4.1.0

A new version of Uploader has been released, version 4.1.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.1.0
Tested On: PHP 5.4.3, CakePHP 2.3.1, Composer
Requires: PHP 5.3, CakePHP 2, Composer
Commit Hash: f2cad62f01c8aedc262692a54ea5d5ed272f4224
Changes:

  • Includes changes from 4.0.12 - 4.0.15
  • Updated Transit requirement to 1.2
  • Updated extension parsing to extract the value from the filename
  • Updated mimetype parsing to extract the value from multiple sources: file -b --mime command, then fileinfo, then $_FILES['type']
  • Fixed a bug where beforeUpload(), beforeTransform() and beforeTransport() callbacks were not being triggered for record deletions
  • Fixed a bug where $this->data is not available within callbacks

Changelogs: Forum v4.0.0

A new version of Forum has been released, version 4.0.0. Please download the new tag or view the documentation. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, report an issue on the GitHub repository.

Version: 4.0.0
Tested On: PHP 5.4.3, CakePHP 2.3.1, Composer
Requires: PHP 5.3, CakePHP 2.3, Composer
Commit Hash: bcea4ec25587acf89af064463088ba5eb981e8e3
Changes:

  • Replaced the custom ACL system with CakePHP's ACL
  • Replaced the admin system with the Admin plugin
  • Replaced the reporting system with the Admin plugin reporting system
  • Replaced the logging system with the Admin plugin logging system
  • Integrated the new Utility 1.4 features
  • Integrated the TreeBehavior where applicable
  • Rewrote the InstallShell and UpgradeShell
  • Removed the Profile model (the old fields should now be part of the users table)
  • Removed Spanish and Swedish locales (too many strings changed)
  • Removed user profiles (all user related code should be handled outside of the forum)
  • Added a ForumUser model that extends from the base User model
  • Added counter caching for topics and posts for the User model
  • Added counter caching for poll votes and options

Vhost caching issue

While I was deploying the new website, I ran into some issues where CakePHP was blowing up on missing model database tables. The weirdness was that these models were not part of my application, but were part of another application running on the same nginx box. I immediately deduced that the problem was the cache, but where was the disconnect? Since the issue was related to model caching, it had to be part of the internal CakePHP caching mechanism.

The problem was a simple one, I forgot to change the $prefix (defaults to myapp_) cache variable in Config/core.php. A small oversight, but a problematic one at that. Just a reminder to everyone else that this variable does exist and to change it when running vhosts.

Version Two

It's been 5 years since the launch of milesj.me, and 5 years of the same design. I spent my recent free time working on a new design. The new design, aptly named version 2, boasts some of the latest in technology. It utilizes HTML5, CSS3, Sass, MooTools, Titon, CakePHP, and more.

Why the change?

After 5 years, you get tired of looking at the same old design. I really wanted to utilize new HTML5 tags, as well as attempting some new CSS3 features like transitions and media queries. Releasing a new version allows for removal of certain features (like snippets), and the refactoring of old ones.

Another annoyance with the previous version was the usage of Decoda (a very very old version at that) in articles and code documentation. It caused nothing but headaches and restricted any customizability that I wanted to achieve. Decoda has its usage in certain situations; that was not one of them.

What technology is being used?

At the lowest level, HTML5 and CSS3 is used for the layout structure. Sass and Compass is used heavily to achieve responsive design at the following breakpoints: 1440, 1366, 1024, 768, 480, 320 (give it a try!). It took me a while to really enjoy Sass, but in the end, its variables, mixins and extremely easy support for responsiveness was welcoming. The Sass files relating to this site can be found by replacing css in the path to scss; for example, the style.scss and skeleton.scss.

On the outside, the Tooltip and Pin component from the Titon Toolkit, a UI toolkit for MooTools, is currently integrated. For code syntax highlighting, I am using the very powerful and nicely built Prism.js by Lea Verou. On the inside, a custom built CakePHP CMS powers everything.

What's next?

With many of my GitHub and website projects out of the way, I hope to find more time to blog about current technology. I mean, what else is there really to do?