Generic non-www to www (and vice versa) 301 redirect using .htaccess

November 3, 2008 – 4:33 pm

The problem:

I’ve always hardcoded the domain name in my htaccess’es, requiring me to make changes each time I deploy a new website.

The solution:

Behold, an alternate, generic method of redirecting non-www to www and www to non-www, requiring no changes between deployments!

Non-www to www

RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) http://www.%{HTTP_HOST}/$1 [R=301,L]

www to non-www

RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^/(.*)$ http://%1/$1 [R=301,L]

Bonus tip: Remove trailing slash from address line

RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]

Tags: , , ,

Yay – my dell new server is now online :D

July 16, 2008 – 11:15 pm

Finally I got the good news from my new hosting company

I can hardly wait to get it FreeBSD 7.0 installed on it and setup a nice vhost system with Lighttpd + PostgreSQL. It’s gonna be awsome.
The server I’m currently using is ‘only’ Dual core XEON w/ 3.5Gb ram, and some random SATA drives, so the improvement should be huge :D

I’m quite excited, because its going to be my first server ever without Apache and MySQL installed. Or well, atleast until some stupid customer or what not (Biesbjerg?) demands it ;)

If I can find the time, I will write a guide on how I’m going to configure my server (Lighttpd, PostgreSQL, Dovecot + sendmail, quota, fast-cgi php5), it might be useful for someone ;)

Let me know if it has any interest to you guys :)

Specs

- Dell PE 1950 III
- PE1950 PCIE Riser (2 Slots) 1 S
- Quad Core Xeon E5410 (2.33GHz, 2×6MB, 1333MHz FSB) (SMP supported)
- 4GB (2×2GB Dual Rank DIMMs) 667MHz FBD (up to 32 GB)
- 3x 146GB SAS 10k 2.5″ HDPE1950 III 2.5″ HDD support chassis
- Perc 6i Integrated Controller
- 8X DVD-ROM Drive IDE
- PE1950 III Non-Redundant Power Supply No Power Cord
- TCP/IP Offload Engine 2P
- Broadcom TCP/IP Offload Engine functionality (TOE) Not Enabled
- PE1950 OpenManage kit and FI Driver
- CFI EMEA Service. (SV-Hi) OR PowerEdge, RAID/partition
- RAID 1 Single Container
- RAID 0 (1 HDD)
- Rack Rails Static Rapid 1 S
- PE1950 III – C2,MSSR0,ADD IN PERC5i/6i/SAS6iR, min 2 / max 2 or 4

/Jippi

Tags: , , , ,

open_basedir will slow you down – security vs. speed

March 21, 2008 – 2:48 am

Just a quickie.

I’m working on some security enhancements for my new website project, and in that progress, I have moved away from Apache2.2.3 and now using Lighttpd instead. Lighttpd does not use the same method of invoking php as apache does (mod_php vs. fast-cgi php).

In my eager to make the application as secure and locked down as possible, I went berserk in the php-cgi.ini file and turned on just about any security feature I could find (not safemode!), including the innocent looking switch called “open_basedir”.

That was rather late in the night, so when I resumed my work the following day, I have long forgotten about all the fancy security settings I had enabled in php.

A few hours ago I noticed that the complete render time for the front page suddenly was ~2seconds(!) – and comparing with apache’s load time for the same page (0.9s) I was quite disappointed at lighttpd and fastcgi, but refused to give up my new found love without a fair trial.

I attacked google with full force without finding any useful resources that might be able to explain my issue.. I was quite sure it was APC that did not function well in a fastcgi environment – and therefore my google madness was focused around the keywords “apc + fastcgi”

While chatting to PatrickDK in the #lighttpd channel @ freenode, it suddenly hit me – let’s try to disable everything I have “fixed” last night – starting with XDebug, some 3rd party php modules (syck, memcache, simplexml, fileinfo) – and then, open_basedir flag.

And with just one line commented out in my php-cgi.ini file, the render time went from 2.4 to 0.5 seconds !!(!!)

So just a little note to you guys out there, beware of the open_basedir setting in a setup where you include many files, it is a rather costly feature to use. And when running fastcgi php in chroot()ed setup, its not really required anyway

Its another +1 for lighty and fastcgi

And yes, I’m aware that open_basedir is slow because it has to validate EVERY file or path you work with inside php to check if its within the scope defined.

Tags: , ,

New books from amazon.co.uk

March 19, 2008 – 10:20 pm

Just got an email from Amazon.co.uk – the have shipped my new batch of dev-books :)

This time around it was more an impulze to buy some books, so I hope I will end up as satisfied as last time I purchased some books from them.

I will probably give a short review of the books once I have read them ;)

Tags: , , , , ,

Faster Page Loads – Bundle Your CSS and Javascript with lighttpd

March 18, 2008 – 4:23 pm

Hello again,

Preface

This time I have been busy playing with Lighttpd and mod_magnet. I found a blog post where darix mentions a post from sitepoint where they demostrate a technique to speed up the HTTP GET of javascript and CSS files.

Its quite simple really, instead of doing

<link href="/css/styles1.css" rel="stylesheet" type="text/css" />
<link href="/css/styles2.css" rel="stylesheet" type="text/css" />
<link href="/css/styles3.css" rel="stylesheet" type="text/css" />

you simply do

<link href="/css/styles1.css,styles2.css,styles3.css" rel="stylesheet" type="text/css" />

and then this script will automagic concat them together into one big file, and make lighty serve that one instead. (The same goes for javascript files, or anything really)

This could save ALOT of HTTP GET’s to your server, and increase the overall loadtime and performance of your site alot, especially if you use alot of Web2.0 stuff :)

However, the Lua source for their script was not made public, so nobody could benifit from their otherwise impressive speed gains. :(

Until now.. or, well, almost – its not their script, but my own attempt to mimic what they did in pure Lua :)

I tried to keep the dependencies down to a minimum, however I decided to use one, md5.
You can find the source here (5.1, 5.0)

Config

charset (Line 42)
Set it so it matches the headers in your lighttpd.conf file. Must match your mod_compress settings aswell to utilize that feature
prefix (Line 43)
Could be anything really, its just a mean to “namespace” your cached files so you can run the script with multiple configs
rootPath (Line 44)
The path to look for the files to concat, default should be fine for most DOC_ROOT/js and DOC_ROOT/css
concatRoot (Line 45)
The folder to store the concated files, can be anywhere :)

Setup

  • Put the source below somewhere on your disk, I asume you name it bundle.lua
  • Enable mod_magnet in lighttpd.conf
  • Add magnet.attract-physical-path-to = ( “YOUR_PATH/bundle.lua” ) to your config where needed
  • Restart lighttpd
  • Modify your css/js links to utilize the new feature:)

Optimal you can enable mod_compress aswell, bundle.lua works out of the box with any other lighttpd module you may have :)

Source

download source

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
--- get stat information on a path
-- @param path to stat
-- @param the ftype to return
-- @return false if ftype or path does not exist
function file_info(path, ftype)
    local attr = lighty.stat(path)
    if attr and attr[ftype] then
        return attr[ftype]
    end
    return false
end
 
--- Wrapper for reading a full file into a string
-- @param filename Full path to the file
-- @return a string with the content of the file
function read_file(filename) 
    local content = ""
    if file_info(filename, "is_file") then
        local file = io.open(filename, "r")
        content = file:read("*a")
        io.close(file)
    end
    return content
end
 
--- Wrapper for writeing content to a file
-- @param filename Full path to the destionation file
-- @param content The string to write
function write_cache(filename, content) 
    local file = io.open(filename, "w")
    file:write(content)
    io.close(file)
end
 
--- Concat multiple files into one file 
-- @param lighty lighty global variable passed to the method
-- @param match The files that will be concat into a file
-- @param fileExtension Do !NOT! include the dot ( . )
function combine_files(lighty, files, fileExtension)
    require "md5" 
 
    local charset       = "; charset=utf-8"
    local prefix        = "cache-"
    local rootPath      = lighty.env["physical.doc-root"] .. fileExtension .. "/"
    local concatRoot     = "/tmp/cache/"
    local lastModified  = 0
 
    for file in string.gmatch(files, "(.-\." .. fileExtension .. "),?") do
        local fullPath = rootPath .. file
        modTime = file_info(fullPath, "st_mtime")
        if type(modTime) == "number" then
            lastModified = math.max(lastModified, modTime)
        end            
     end
 
     local hash = lastModified .. "-" .. md5.sumhexa(files)
     lighty.header["Etag"] = '"' .. hash ..'"'
 
    local cacheFile = prefix .. hash .. '.' .. fileExtension
    if not file_info(concatRoot .. cacheFile, "is_file") then
        local content = ""
        for file in string.gmatch(match, "(.-\." .. fileExtension .. "),?") do
            content = content .. "\n"
            content = content .. "/**\n"
            content = content .. " *\n"
            content = content .. " *  " .. file .. "\n"
            content = content .. " *\n"
            content = content .. " */\n"
            content = content .. "\n"
            content = content .. read_file(rootPath .. file)
        end
        write_cache(concatRoot .. cacheFile, content )
    end
    lighty.env["physical.path"] = concatRoot .. cacheFile
end
 
if (not file_info(lighty.env["physical.path"], "is_file")) then
    css = string.match(lighty.env["physical.path"], "css/(.*\.css)")
	if css then
        return combine_files(lighty, css, "css")
    end
 
    js = string.match(lighty.env["physical.path"], "js/(.*\.js)")	    
	if js then
        return combine_files(lighty, js, "js")
	end 
end

Tags: , , ,

A quick tutorial on CakePHP Set class (Part 1)

March 4, 2008 – 12:56 am

Test data

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
$data = array( 
    1 => array('Post' => array( 
            'id' => 1, 'post_comment_count' => 2, 
            'name' => 'My first title', 'body' => 'My first body' 
        ), 
        'PostComment' => array( 
            array( 
                'id' => 1, 'post_id' => 1, 'is_active' => 1, 
                'name' => 'My first comment', 'body' => 'My first comment'), 
            array( 
                'id' => 2, 'post_id' => 2, 'is_active' => 1, 
                'name' => 'My second comment', 'body' => 'My second comment'), 
            array( 
                'id' => 3, 'post_id' => 2, 'is_active' => 1, 
                'name' => 'My third comment', 'body' => 'My third comment') 
        ) 
    ), 
    2 => array('Post' => array( 
            'id' => 2, 'post_comment_count' => 1, 
            'name' => 'My second title', 'body' => 'My second title' 
        ), 
        'PostComment' => array( 
            array( 
                'id' => 4, 'post_id' => 2, 'is_active' => 
                1, 'name' => 'My fourth comment', 'body' => 'My fourth comment' 
            ) 
        ) 
    ), 
    3 => array('Post' => array( 
            'id' => 3, 'post_comment_count' => 0, 
            'name' => 'My third title', 'body' => 'My third title' 
        ), 
        'PostComment' => array(                   
 
        ) 
    ) 
);                   
 
$dataExtra = array( 
    4 => array('Post' => array( 
            'id' => 4, 'post_comment_count' => 1, 
            'name' => 'My fourth title', 'body' => 'My fourth title' 
        ), 
        'PostComment' => array( 
            array( 
                'id' => 5, 'post_id' => 4, 'is_active' => 1, 
                'name' => 'My fifth comment', 'bdoy' => 'My fifth comment' 
            ) 
        ) 
    ) 
);

Set::merge

PHP doc blcok

This function can be thought of as a hybrid between PHP's array_merge and
array_merge_recursive. The difference to the two is that if an array key
contains another array then the function behaves recursive (unlike array_merge)
but does not do if for keys containing strings (unlike array_merge_recursive).
See the unit test for more information.         

Note: This function will work with an unlimited amount of arguments and
typecasts non-array parameters into arrays.

A bit like array_merge_recursive. Merge joins two arrays on their keys.
If we want to add the $extraData array into the $dat most people would probably think, hey, lets merge them using Set::merge… but.. no, dont, unless you know what your doing.

1
pr(Set::merge($data, $dataExtra));

The above cod will only produce the ‘expected’(?) result because I have added the numeric key 4 in the $extraData array (Line 40). If I had, as I did the first time around, just let php auto-increment the keys for me, both $datad and $extraData would contain the numeric index key 0, and since Set::merge works on keys, $extraData’s Fourth post would overwrite $data’s First post where they had anything in common (id, name, post_comment_count, body and everything in the first PostComment (My first comment)).

In case I had let php handle the index keys, I would have to use Set::insert to append the fourth comment to the list.

A better use of Set::merge is in CAKE/libs/model/model.php where is automagic merges ‘actsAs’ from your current model (PostComment) and your AppModel, so you automagic inherit the global behaviors from AppModel:

384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// model.php 
if (is_subclass_of($this, 'AppModel')) { 
    $appVars = get_class_vars('AppModel'); 
    $merge = array();             
 
    if ($this->actsAs !== null || $this->actsAs !== false) { 
        $merge[] = 'actsAs'; 
    }             
 
    foreach ($merge as $var) { 
        if (isset($appVars[$var]) && !empty($appVars[$var]) && is_array($this->{$var})) { 
            $this->{$var} = Set::merge($appVars[$var], $this->{$var}); 
        } 
    } 
}

A funny thing is that Set::merge is still rarely used in the core code yet. Probably because array_merge (or am()) is faster for simple operations like just merging two simple 1 level arrays like a config array.

Set::filter

PHP doc blcok

Filters empty elements out of a route array, excluding '0'.

This method is not recursive. So doing

1
2
< ?php 
pr(Set::filter($data, true));

wont change anything in the array sinc no elements in first level is empty.



1
2
3
4
5
6
7
8
9
pr(Set::filter($data[3], true));      
 
array('Post' => array( 
    'id' => 3, 
    'post_comment_count' => 0, 
    'name' => 'My third title', 
    'body' => 'My third title' 
    ) 
);

We will notice that the PostComment array is gone, since its empty

Set::pushDiff

PHP doc blcok

Pushes the differences in $array2 onto the end of $array

That sounds simple enough, and it really is.

1
pr(Set::pushDiff($data, $dataExtra));

just pushes the $dataExtra on the end of $data, since they have nothing in common. Again, this method operates on the array keys when comparing arrays.

Set::map

PHP doc block

Maps the contents of the Set object to an object hierarchy.
Maintains numeric keys as arrays of objects

That sounds very fancy, and it is! A lot of people migrating to CakePHP from Symfony (PHPDoctrine, Propel) will probably be confused at first that all model data in CakePHP is arrays, and not objects like other frameworks. This method attemps to ‘fix’ this issue by converting a model data array to a set of objects (StdClass). StdClass is a build-in dummy class in PHP, and it doesnt really do anything but contain data, no methods or fancy magic there.

1
2
3
4
5
6
7
8
9
< ?php 
// Convert to objects 
$map = Set::map($data); 
// id of first post (Object style) 
echo $map[0]->id; 
// name of first comment to first post (Object style) 
echo $map[0]->PostComment[0]->name; 
// name of first comment to first post (array style) 
echo $map[0]['PostComment'][0]['name']; // WONT WORK, Cannot access StdClass as an array

As you can see above, its important to decide what method you want to use, Object or Array style, since they cannot be mixed.
Also, the return from Set::map is a mix of arrays and StdClass, thats why I can access $map[0] as array, but not access $map[0]['name'].

Set::numeric

PHP doc blcok

Checks to see if all the values in the array are numeric

Not much to say on this one, because it doesnt do more or less than the name implies.

1
2
3
4
5
6
7
8
// false 
var_dump(Set::numeric($data)); 
// false 
var_dump(Set::numeric($data[1])); 
// false 
var_dump(Set::numeric($data[1]['PostComment'])); 
// true 
var_dump(Set::numeric(array(1,2,3)));

——-

Thats it for now, next time I will look at:

Set::enum, Set::format, Set::extract, Set::insert, Set::remove, Set::check, Set::diff, Set::isEqual, Set::contains, Set::countDim, Set::normalize, Set::combine and Set::reverse.

Look forward to it

Tags: , ,

A small change in RSS feeds.

March 3, 2008 – 11:52 pm

Hello again.

I have made a small change to the feeds now. Everybody who has subscribed by Feedburner should not notice anything strange.

The reason for the change is that I want to be able to blog in Danish too once in a while, and to avoid the ‘danish pølsesnak’ for you guys who does not understand Danish, I have moved the feed location to include only posts with the ‘english’ tag in the future :)

English posts only (Hopefully your using this one right now :) ), Danish posts only and Danish+English posts

/Jippi

Tags: , ,

Første danske post

March 3, 2008 – 11:49 pm

Dettte er min første danske post

Tags:

CakePHP talk from FOSDEM – Free and Open Source Software Developers’ European Meeting

March 3, 2008 – 10:43 pm

A small note, gwoo’s talk from FOSDM 2008 has been made public avilable here together with his slides.

Its actually a quite good presentation, too bad he ran out of time in the end ;)

Tags: , ,

CakePHP Weekly Summaries Issue #2

March 3, 2008 – 10:37 pm

Welcome

Welcome to the second edition of the CakePHP weekly summaries.
Its quite embarrassing that it had to take so long time to get the second editon out. Too long time has passed and the amount of things that has happend during that period is waaay too big to be covered here.
Therefor I present this half-done 2nd edition of the weekly summaries, with a promise that every week from now on I will give you the latest and greatest from the CakePHP world.
So with no further ado, please enjoy this old and probably rather outdated edition of the weeklymonthly summaries. :) See you at the 3rd edition soon :)

Trac changes

  • Changeset #6321 (phpnut) Fixes Ticket #3817, Some non-executable files in source tree have executable permissions
  • Changeset #6322 (phpnut) Updating controller tests created with the console. Added associated fixtures to model tests
  • Changeset #6323 (gwoo) Updating Cache to apply prefix for every key, closes Ticket #3821
  • Changeset #6324 (phpnut) Correcting links generated to additional app tests
  • Changeset #6325 (phpnut) Adding support for test fixture generation when creating models, this will eventually be moved to a task. Currently the $records are hard coded to create field type specific data, this will eventually be changed to create random data based on the field type. Refactored tests that are created for models, 3 working tests are not created when generating tests for the model. Added notice output to terminal when creating a project, the CAKE_CORE_INCLUDE_PATH is automatically altered and may need to be changed when moving to a production environment. ”
  • Changeset #6326 (phpnut) Fixes svn file property line
  • Changeset #6327 (phpnut) Removing unneeded ‘ : ‘
  • Changeset #6328 (phpnut) Removing unneeded ‘ : ‘
  • Changeset #6329 (nate) Fixing reading and writing in Configure class for references 3 levels deep, fixes Ticket #3845
  • Changeset #6330 (nate) Removing un-needed method from TimeHelper? test
  • Changeset #6331 (phpnut) Removing var $useTable; from generated model when tables follow conventions Fixed issue with model tests and fixtures not being created properly when Model name does not match table name
  • Changeset #6332 (phpnut) Updating controller tests created with the console. Added associated fixtures to model tests
  • Changeset #6333 (phpnut) Fixes Ticket #3849, Deprecated loadView() call in email component when using theme
  • Changeset #6334 (gwoo) updating HttpSocket? with auth, closes Ticket #3838 removing type casting, fixes Ticket #3827 adding socket.group to tests
  • Changeset #6335 (gwoo) updating component, removing use of Router not needed anymore, fixes Ticket #3858
  • Changeset #6336 (nate) Adding non-null association key fix in Model, and updating Model::isUnique() to account for current record, fixes [ticket fixed 38599, closes [ticket fixed #2032]
  • Changeset #6337 (nate) Fixing return value in Model::saveAll(), fixes Ticket #3852
  • Changeset #6338 (phpnut) Fixes Ticket #3829, Scaffolding and bake script has problems with tables that has underscore in it’s name
  • Changeset #6339 (phpnut) Fixes Ticket #3798, custom scaffolding file lookup paths inconsistent
  • Changeset #6340 (phpnut) Fixes Ticket #3862, set_time_limit(0) has no effect because of ini_set(‘max_execution_time’, 60 * 5); changed max_execution_time , 0. Since php 4.3 this is the default anyway
  • Changeset #6341 (phpnut) Fixes Ticket #3811, $_SESSION not found Fixes [ticked fixed 3823], Session not restarted after instantiating new SessionComponent? Fixes #3850, Configuration Session.start and SessionComponent::__active aren’t handle correctly
  • Changeset #6342 (phpnut) Fixes Ticket #3851, Acl component fails to check() if a permission is denied in action (*)
  • Changeset #6343 (phpnut) Adding test cases from [ticked closed 3810]
  • Changeset #6344 (phpnut) Reverting [] and [] this commit broke the working implementation. Closes Ticket #3810
  • Changeset #6345 (phpnut) Fixes Ticket #3854, Scaffolding is generating an id field with an empty value for auto_increment primary key
  • Changeset #6346 (phpnut) Fixing bug with scaffold and valid Session id check
  • Changeset #6347 (phpnut) Fixing bug with scaffold and valid Session id check in 1.1.x.x
  • Changeset #6348 (gwoo) updating View error handling for extensions, fixes Ticket #3795
  • Changeset #6349 (nate) Correcting parameter declaration in API shell
  • Changeset #6350 (nate) Fixing database drivers for UPDATE/DELETE changes, updating drivers to comply with model tests, most passing. Fixes Ticket #3794
  • Changeset #6351 (nate) Whitespace fixes
  • Changeset #6352 (gwoo) adding connection param to schema shell
  • Changeset #6353 (nate) Enabling alternate titles for PaginatorHelper::sort() links based on sort direction, closes Ticket #3865
  • Changeset #6354 (nate) Removing MySQL-specific schema code from core, improving support for PostgreSQL sequences, most tests passing

Google group topics

Why doesn't Find* return a group of model objects?

This topic has been discussed many times before, but Deane felt that it was required to ask yet again: “Why doesn't Find* return a group of model objects?“. He wanted to be able to work with his models in the view (!BAD DESIGN!), and was confused why he only got an array back from the find* methods. Gwoo replied, and I quote: “Speed, simplicity, clarity” and pointed out that Cake provide view helpers to work with the arrays in almost any way you can imagine, and that the models provide callback functions (afterFind, afterSave, beforeFind, beforeFind) to format your data.
Deane thanked gwoo for the reply, but “We couldn’t disagree more strenuously, and we think you’re wrong beyond belief in your reasoning, but we appreciate the response”…. didnt like gwoo’s reply at all.
Gwoo replied in a calmly matter that “Everyone is entitled to their opinion and their choice of frameworks.”
rtconner joined the discussion, offering a solution based on some old code by gwoo that would enable the models to return objects (StdClass, not models classes)instead of arrays.
Nick also joined the thread, backing up Deaen’s point of view (Cake is wrong, symfony lover is right) that its proper OO to use objects instead of arrays for the view data, but also reasoned that cake does indeed have the needed hooks and concepts to achieve Deane’s initial idea with a minimal effort. He explained that in a project he had created with CakePHP was that relationships (belongsTo, hasMany ect.) get more complicated with the OO styled approach, since the queries often fetched much more data than was really needed in the view. The combination of the controller didnt know wich fields the view required and the complex relation ships was in his opinion, not ideal at all. Their work a round was to create a “LazyData” class to handle it.
Robby Anderson dropped in his 2 cents, and agreed that the cake was isnt 100% pure OO, but that the concept of “having the view incapable of performing any meaningful business logic” is bad, and will sooner or later lead to an unmanagelbe code base.
Deane, the creater of the thread, posted a public apoligy to gwoo, explaining that he was fustrated at the time when he posted his previous post.

So, the summary must be that while some people dont like the design decission that CakePHP models return arrays instead of objects, others agree that its the right way to encapsulate the buisness logic in a correct Model View Control manner, and if you want to break theese convensions, its rather easy to do with minimal effort.

Passing Data To A Form

Travis asked how you are Passing Data To A Form. A bit unexpted (or perhaps expected given the flood of duplicate / newbie questions hitting the groups daily) nobody answered his question. The answer is pretty simple, and covered in any tutorial aviable on cakephp website AND in the documenation / manual.

1
2
3
function update($employeeID)  { 
     $this->data =  $this->Employee->findAllById($employeeID); 
}

The Show Is Back!

Jeff Loiselle aka phishy announced that the show is back. No replies, no thing, its sad… the show rocks !

I18n in 1.2 model validation message

Athies asked how does i18n in 1.2 model validation message work. His iniital attemp was to use the i18n method ‘__()’ in the model $validate array, but he was getting syntax errors when doing that.
Since PHP does not support useage of functions in instance delclarations its not possible to use i18n directly in the validate array.
Francky06l pointed at his solution in another google post i18n: static language references with __("My lang key", true) in models and controllers, and while the solution will work, its far from ideal when working with i18n.
A CakePHP google group regular, Dr. Tarique Sani, pointed out that the correct way to handle i18n validation messages was in the view, not at the model level. Amit Badkas backed up Tarique up and provided a simple example on how to do it:

1
2
3
4
5
< ?php echo 
$form->input('username', array('error' => array( 
    'alphanumeric' => __('Username must contain alpha-numeric characters', true), 
    'between' => __('Username must be between 8 to 20 characters', true)))); 
?>

Francky06l seemed to know that, his consern was the if he multiple views where the validation errors should show, it would be convenient to do it at model level.
Robby Anderson wasnt sure why you just couldnt do both, create the validation errors in the model, and wrap them in __() in the view.

And sure, that will work – but – you will loose some cake magic with that. The console application

cake i18n extract

will not add the i18n messages to the pot file automagic. Also, the i18n extract command will not even search your models for any i18n magic. It will only look in controllers and views. You can choose to call this a limit or a feature, but thats how cakephp has decided to do it, to enforce their paradime on how an application should be build and structured.

FormHelper Labels

Travis asked how it was possible to disable the automagic label in the FormHelper. Robby Anderson provided the correct solution for this issue, use ‘label’ => false:

< ?php echo $form->input('Employee.name',array('label' => false));?>

Using model objects in the controllers

Deane from earlier posted another question on Using model objects in the controllers. I dont really want to dwell much on this post, since its really attemp to take CakePHP in another direction than its supposed to. Deane clearly shows a lack of insight on how cakephp is supposed to work, and failed to provide any usefull examples that could show the group what he wanted to do.

Tags: , ,