Set CakePHP layouts in app_controller

Fed up of writing $this->layout = ‘admin’ in all the admin methods of your controllers? Me too.

I realised that instead you could automatically set them in the beforeFilter() of your app_controller instead.

1
2
3
4
5
6
7
8
9
10
11
12
13
function beforeFilter(){
 
  if(isset($this->params['prefix'])) {
    //read the admin prefix set in core.php
    $admin = Configure::read('Routing.admin'); 
 
    if($this->params['prefix'] == $admin){
 
      $this->layout = $admin;
 
    }
  }    
}

If you need to over-ride this, you can just do so as normal in individual methods.

At last the CakePHP books have arrived

I’d like to say it never rains but it pours, but that would be entirely the wrong sentiment, I need something more like good things come to those who wait

Anyway after an epic wait a flurry of CakePHP books have arrived.

I haven’t read any of these books yet, but I from personal experience I would say the Apress books are bound to be good. I have no idea what the books from Packt are like. I have one Manning book which is good but is unfortunately a PDF (and I hate reading PDFs).

XAMPP and the PHP CLI

Like a lot of people I do most of my development work on windows PC and locally run a web a server and database. Like a a lot of people I just downloaded and installed a server bundle. For the last few years I have used Apache2triad and it has generally been pretty painless, but I’ve recently been forced to abandon it. Unfortunately the development seems to have been abandoned about 2 years ago.

The reason I abandoned Apache2triad was PHP versions – I wanted to do some work with Google Base using the Zend Google Data Library which required PHP 5.1.4+.

Looking around at the various bundles I decided to go with XAMPP – a lot of people seem to use it and it seems to get pretty good feedback. I won’t say the process was entirely painless (it took a couple of goes to get everything up and running) but eventually it all seemed OK.

The fun started when I decided to do a bit of baking (generating scaffolding code for my CakePHP app from a command line interface). Nothing worked.

Looking into it I discovered more than I wanted to know about the PHP Command Line Interface (CLI) which I had happily used for years with no idea it actually existed, having assumed it was just there as part of PHP.

After a lot googleing and a lot of trial and error I got it all working again and this is how I did it.

My environment is Windows XP Pro Service Pack 2 with XAMPP installed on E:/

  1. Downloaded the latest version of PHP and replaced the entire contents of E:\xampp\php\.
  2. Added to the E:\xampp\php to my environment PATH.

At this stage PHP CLI wwas now working but there were nasty errors e.g. I was uanble to connect to MySQL from scripts. I discovered that this is because PHP CLI uses a different php.ini file to regular PHP.

To fix this I copied my php.ini from E:\xampp\apache\bin\php.ini (the default XAMPP ini file) to E:\xampp\php.

I then checked the PHP CLI again using php -v at a command prompt. There were now about 6 errors displayed, concerned with modules that could not be loaded or found. I believe that these concern modules just that aren’t meaningful in CLI mode. So I went through my new php.ini in E:\xampp\php and commented out the directives that were causing the errors until PHP CLI ran without errors.

Displaying Auth Error Messages

I feel a bit daft posting this because in the end the answer was so easy to find – but maybe it will help somebody else.

I’ve been re-writing my users / groups permission system for CakePHP 1.2 and decided to incorporate as much built in functionality as possible so I’m using the Auth Component – which is great – but one thing kept bugging me, I couldn’t for the life of me figure out how to get the messages from Auth to display in my views – but by debugging I could see they were sitting there right in the Session.

I spent a long time Googling and looking at the API for clues, eventually in desperation I looked at the cookbook (I have no idea why I hadn’t already looked there – as I use it a lot…) and the answer was both very easy and staring me right in the face.

Just pop the following in a view or layout:

1
2
3
4
 
if ($session->check('Message.auth')) {
		$session->flash('auth');
	}

jQuery plugin to print HTML forms

Recently for a project, a client wanted to be able to print pages from a web application that were just forms. This was never intended when the application was originally built, so there were no separate view screens of data. Naively I thought this would be easy – knock up a print style sheet and bob’s your uncle… if only.

There are a couple of problems that just aren’t really fixable using a pure CSS solution, firstly <select> menus look pretty horrible no matter what you to them and <textarea> fields look fairly bad, but even worse than their aesthetic merits (or lack of rather) is the fact that the overflowing content i.e. the content that you need to scroll to see, will not be printed.

In the end for the application I ended up adding views, but it got me thinking and so I’ve written a quick jQuery plugin to print forms. It works by looking for any <select> menus or <textarea> fields and replacing them with <div> tags styled to look like form elements. When you click on one of the <div>s to edit it, it reverts to the original form element and when it looses the focus (using the jQuery blur() method) the field is swapped back and replaced by the <div>.

When you come to print the form because all of the <select> menus and <textarea> fields have been replaced by <div>s you can style them as you want using a print style sheet and get a nice looking form with no missing content.

Have a look at the working example and view source to see how to use it.

download printform plugin example

You will want to edit / write CSS for both screen and print appropriate to your situation.
Tested on IE6, IE7, Firefox 2.0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 
/*
 * printform 1.0
 * By John Elliott (http://www.flipflops.org)
 * Copyright (c) 2008 John Elliott
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/
 
/**
 * convert textareas and select tags to divs so that you HTML forms can be printed.
 *
 *
 *
 * @name printform
 * @type jQuery
 * @author John Elliott (http://www.flipflops.org)
 * @desc 
 * 
 * @example $('#tester').printform();
 * @desc call the plugin on #tester - any select or textareas will be replaced
 *
 * @param settings - not used, but included for future proofing! (I'm sure there will be options sometime...)
 *
*/
 
jQuery.fn.printform = function(settings){
	return this.each(function(){
		new jQuery.printform(this, settings);
	});
}
 
 
 
jQuery.printform = function(obj, settings) {
 
  	/*
  	* within a parent object - replace the textareas and select menus
  	*/
 
 
 	init(obj, 'textarea');
	init(obj, 'select');	
 
 
	function init(obj, fieldType) {
 
	/*
	* loop through each instance of an element within the parent 
	*/
 
		obj = jQuery(obj).attr('id');
 
		jQuery('#' + obj + ' ' + fieldType).each( function() {
 
			var id = jQuery(this).attr('id');
 
			field_replacer(id, fieldType);
		});
	}		
 
 
	function field_replacer(id, fieldType) {
 
	/*
	* function to replace the elements with divs
	*/
 
			str = jQuery('#' + id).val();
			str = str.replace(/\n/g, '<br />');
 
			if ( jQuery('#replace-' + id).length > 0 ) {
				// if a replacement div already exists for this element, then just show it.
				// update the content of the replacer with the edited content
				jQuery('#replace-' + id).html(str).show();			
			} else {
				// otherwise create a new replacement div for the element
				jQuery('#' + id).after('<div class="' + fieldType + '-replace" id="replace-' + id + '">' + str + '</div>');			
			}
 
			jQuery('#' + id).hide(); // hide the element that has just been replaced
			field_watcher(id, fieldType); // add event listeners
	}											
 
	function field_watcher(id,  fieldType) {
 
	/*
	* add listeners to the elements
	* onclick - show the original element and hide the replacer
	* onblur - call the field_replacer to update the page
	*/
 
		jQuery('#replace-' + id).click(function() {
 
		jQuery('#' + id).show().focus();
		jQuery('#replace-' + id).hide();
 
		jQuery('#' + id).blur(function() {
 
			field_replacer(id,  fieldType);								
 
		});
	});
	}
};

Thanks to to Mike Alsup for his great (if rather daunting) guide to writing plugins on Learning jQuery.