Archive for the ‘CakePHP’ Category

11 Dec 07 _ MAMP, PHP5, CakePHP, and Strict Standards

We’re making the move to PHP5 for our latest project, and it was much to my dismay when I saw a series of errors unleashed during the first test of the Cake pre-beta:



Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/basics.php on line 279

Strict Standards: Redefining already defined constructor for class Object in /Applications/MAMP/htdocs/xxxx/cake/libs/object.php on line 65

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/object.php on line 92

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/inflector.php on line 65

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/configure.php on line 96

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/configure.php on line 154

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/cache.php on line 71

Strict Standards: Assigning the return value of new by reference is deprecated in /Applications/MAMP/htdocs/xxxx/cake/libs/cache.php on line 157

Strict Standards: Non-static method Configure::getInstance() should not be called statically in /Applications/MAMP/htdocs/xxxx/cake/bootstrap.php on line 48

Now I know that this wasn’t Cake’s problem. This is PHP5’s new error reporting standard, which was turned on for some reason.

To disable Strict Error Reporting, edit your php.ini file and set the error_reporting to (line 270):


error_reporting  =  E_ALL & ~E_STRICT

Or, in your .htaccess file in your root cake installation, you can add the following line:


php_value error_reporting 6143

Which is the bit value of E_ALL & ~E_STRICT.

Either way, the errors should disappear. The reason they exist in the first place? According to Gwoo, it’s to maintain Cake’s functionality with PHP4.

If you’re still confused, you can always visit PHP’s page on error reporting for more on error-lovin’.

23 Oct 07 _ Configuring the othAuth Component for Cake 1.2 pre-Beta

After upgrading to the new CakePHP pre-beta that was released yesterday, I noticed that the excellent othAuth component 0.5.4.5, which we use here as part of our user Authentication process, was broken. Part of this was expected, as the new release of Cake has moved away from PHP defined constants, to the new Configure class. Essentially, the othAuth component was looking for the CAKE_ADMIN constant for admin routing, which no longer existed.

Here’s what I needed to do to make othAuth work again (I assume you’ve set up othAuth in the way described in the Bakery):

First, in your app_controller.php file, in the beforeFilter function, add this line above the rest of the othAuth initialization:


        $this->othAuthRestrictions[] = Configure::read('Routing.admin');

And remove any references to CAKE_ADMIN in the $othAuthRestrictions variable.

Then, in the oth_auth.php component, replace all references of:


     defined('CAKE_ADMIN')

to:


     Configure::read('Routing.admin')

and change all remaining occurrences of:


     CAKE_ADMIN

to:


     Configure::read('Routing.admin')

Most of these occur in if-then statements throughout the component.

The last thing I had to do was replace some model save actions. Specifically, if you’re using the standard othLogin, I needed to replace the following (line 328):


     $res = $UserModel->save($row,true,array($this->user_table_last_visit));

with two new lines:


     $UserModel->id = $row[$this->user_model]['id'];
     $res = $UserModel->saveField($this->user_table_last_visit,$row[$this->user_model][$this->user_table_last_visit],true);

Before, it was INSERT-ing a new entry with just the last visit information instead of updating the current user entry. When logging in a second time, I would receive a duplicate entry error from this. Switching from save to saveField helps guarantee that we’re UPDATE-ing the database, instead of INSERT-ing. I imagine you’d have to make a similar change if you use the naoLogin function.

After the above changes, everything worked once again.

01 Oct 07 _ Caching Model Data in CakePHP (Part 2)

In my last post on this topic, I discussed the occasional need to make large SQL calls (for example, calculating the navigation structure of your site), and the relative lack of good options for reducing the number of times Cake would need to make those large calls.

We needed to create a basic caching function that would work to reduce the load on the SQL server for common find and findAll queries. We might as well make it a general function, so any model can use it. So let’s add this function to our app_model.php file, located in the /app folder of the Cake distribution. If the file doesn’t exist (by default it does not), you can create it.

I made two functions for data-caching: cachedFind and cachedFindAll. They take the same inputs as the standard Cake functions find and findAll, to retain any and all flexibility we need. Here’s the code:


< ?php
class AppModel extends Model{

function cachedFindAll($conditions = null, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null)
{
$findID = null;
//construct the FindID
if (is_array($conditions)) {
$conditionsID = implode('.',$conditions);
} else {
$conditionsID = $conditions;
}

if (is_array($order)) {
$orderID = implode('.',$order);
} else {
$orderID = $order;
}

if (is_array($fields)) {
$fieldsID = implode('.',$fields);
} else {
$fieldsID = $fields;
}

$findID = md5($this->useTable . $conditionsID . $orderID . $fieldsID);

if (!$findID) {
return false;
}

//check to see if a cached version exists
$cachedSQLFile = CACHE . DS . 'models' . DS . $findID.'_data.php';

if (file_exists($cachedSQLFile)) {
//the file exists, so read the file and unserialize it.
if (function_exists('file_get_contents')) {
$serializedNav = file_get_contents($cachedSQLFile);
} else {
$serializedNav = implode('', file($cachedSQLFile));
}
$data = unserialize($serializedNav);
}

if (!isset($data) || !is_array($data)) {
//either we can't find the variable and it doesn't exist, or the data isn't an array, so reload it

$data = $this->findAll($conditions, $fields, $order, $limit, $page, $recursive);

//if it's there and the data was bad, delete the file
if (file_exists($cachedSQLFile)) {
@unlink(file_exists($cachedSQLFile));
}

//write the new, cached(!!) version
$cacheFile = fopen($cachedSQLFile,"w");
fwrite($cacheFile,serialize($data));
fclose($cacheFile);

}

return $data;

}

}
?>

I’ll go through the main points of this function:


$findID = null;
//construct the FindID
if (is_array($conditions)) {
$conditionsID = implode('.',$conditions);
} else {
$conditionsID = $conditions;
}

if (is_array($order)) {
$orderID = implode('.',$order);
} else {
$orderID = $order;
}

if (is_array($fields)) {
$fieldsID = implode('.',$fields);
} else {
$fieldsID = $fields;
}

$findID = md5($this->useTable . $conditionsID . $orderID . $fieldsID);

if (!$findID) {
return false;
}

Because we want flexibility here, we need to have a way to uniquely identify the cached data. The way I approach that is to create an MD5 – encoded string based on the input parameters of the findAll query, which associates a unique string with distinct queries. (A hat-tip to August Kaiser at Beehive Media for the recommendation to add the $this->useTable to ensure unique calls for each model).


$cachedSQLFile = CACHE . DS . 'models' . DS . $findID.'_data.php';

if (file_exists($cachedSQLFile)) {
//the file exists, so read the file and unserialize it.
if (function_exists('file_get_contents')) {
$serializedNav = file_get_contents($cachedSQLFile);
} else {
$serializedNav = implode('', file($cachedSQLFile));
}
$data = unserialize($serializedNav);
}

Now we create a link to where the cached file *should* be, using Cake’s defined CACHE location, the model directory, and then the fileID we created above, with the suffix of “_data.php”. If the file is found, the function attempts to read the contents of the file and unserialize it. The function check exists because file_get_contents isn’t standard until PHP 4.3 and up.


if (!isset($data) || !is_array($data)) {
//either we can't find the variable and it doesn't exist, or the data isn't an array, so reload it

$data = $this->findAll($conditions, $fields, $order, $limit, $page, $recursive);

//if it's there and the data was bad, delete the file
if (file_exists($cachedSQLFile)) {
@unlink(file_exists($cachedSQLFile));
}

//write the new, cached(!!) version
$cacheFile = fopen($cachedSQLFile,"w");
fwrite($cacheFile,serialize($data));
fclose($cacheFile);

}

Next we check if the unserialized data exists, and if does, if it’s an array. If either of those conditions are not met, we go and retrieve the data from the database, try to delete an old copy of the file if it exists, and serialize the new data, and write it to the model cache directory for next time.

There’s one more step we need to do before this function becomes completely useful. In the same app_model.php file, we need to add one more function:


function afterSave()
{
clearCache('_data', 'models', '.php');
return true;
}

AfterSave() is a Cake-specific callback function that is executed after data is inserted into the model. What this function does, then, is clear out all the cached versions of our find calls every time we update the database, in order to make sure the user sees the most recent version of the data. Since we put this code into the AppModel class, it runs everytime we save something from ANY model in our system. This may not be the best implementation for web apps that have user-updated content areas, but for a single or multiuser CMS such as our WebTree system, it works quite nicely.

Now anytime you want to have Cake cache the returned data from a SQL call, you can use the cachedFindAll function exactly like the standard findAll function:


< ?php
$data = $this->Model->cachedFindAll(array('Model.displayed'=>'1'),null,array('Model.date'=>'DESC'));
?>

In case you’re curious, the cachedFind function is modeled exactly like the find function in Cake, where it just grabs the first array of data from a findAll call and returns that:


function cachedFind($conditions = null, $fields = null, $order = null, $recursive = null)
{
$data = $this->cachedFindAll($conditions, $fields, $order, 1, null, $recursive);
if (empty($data[0])) {
return false;
}
return $data[0];

}

Now you have two functions that will drastically reduce the amount of SQL calls made by your app. Enjoy.

14 Sep 07 _ Caching Model Data in CakePHP

A slightly more technical post for those of you who care.

CakePHP is great for a lot of things, but for effeciency it is not. Because of Cake’s smart data organization and recursive model associations, the system will frequently accesses the database several (dozen) more times that it really needs to, potentially dragging down a server if you’re not careful.

Since it’s so easy to access the data you need in Cake, you have to be careful to manage the intrinsic inefficiency in the system. There are some obvious things you can do, such as dynamic model unbinding, specific find calls, and knowing how to set your recursive model associations for specific controllers.

But then there are those times when you really do need to make a massive SQL call. I ran into this problem a week ago while working on Ancient Wisdom’s WebTree CMS application. One of the features of the system is that it auto-generates the main site navigation based on the content’s category structure. Because of this, Cake needs to call a self-joined Category model that is associated with a separate Content model, find all parent categories, all child categories, and then all the pages located inside those child categories to build out the site navigation. So even after paring down all unnecessary associations and grabbing only the necessary table data, a decent sized site (say seven top-level categories) required something like 50 or so queries to the SQL database.

This was clearly unnaceptable, as Cake would need to do this every time a page was loaded, in addition to the SQL calls necessary for the specific page content. The answer?

Caching!

Caching is a very common solution to problems such as these. Why access the same data over and over again when you can access it once, and have it ready to go each time a page is requested?

Cake actually includes some default Cache mechanisms. However, the most useful of these (sitewide view caching), still has a buggy implementation in Cake 1.2. The other option was element caching, where you can cache the rendered view of a specific element for a specified duration.

Neither of these would really work, as it was the results of the SQL query that I needed to parse in several ways.

The solution was to cache the output array of the SQL query, instead of caching a rendered view. That way, the data was there at a moment’s notice, and I could run it through as many functions as needed, without the dozens of SQL queries necessary to grab it in the first place.

The key to this problem is PHP serialize function, which converts (and preserves) the contents and structure of an array into a string. Once you serialize the results of the SQL query, you can write that into a file in Cake’s cache directory, and access it as needed.

We need to make a function that will do one of two things:

  • Check to see if a cached data file exists. If it does, open the file, unserialize the array, and return the data.
  • If the cached data doesn’t exist, execute the necessary SQL query, write those results to a cached file, and return the data.

To read more about data caching, and to see code examples, stay tuned for part 2 of this post, coming early next week.

  • guitar modification parts
  • butcher paper roll dispenser
  • makers of dog kennels
  • credit card debt relief program
  • billet grills
  • studio rta the bug computer desk
  • shark cordless cyclonic hand vacuum
  • toastmaster parts toaster
  • men's suits shirts barney
  • saucony shoes outlet stores
  • 1 2 decorative square post caps
  • fruit of the loom union suits
  • maine snowmobile insurance requirements
  • boyne mountain grand lodge and spa
  • triple pet natural toothpaste
  • used kids dirt bikes for sale
  • 30 inch slide in electric range
  • create pdf word embed fonts
  • wholesale jelly jars
  • water as fuel denny klein
  • couch replacement pillows
  • coleman bayside elite replacement parts
  • sponge bob crabby patty candy
  • wholesale winter gloves hats
  • best at home treatment for blackheads
  • tub refinishing pgh pa
  • tile shower seat vintage
  • caught wearing high heels split skirt
  • kawasaki kx85 parts and exploded view
  • india and business dress
  • kid's camp crafts
  • cuff bracelets wholesale
  • golf gps systems reviews
  • wholesale patio pool furniture
  • crystal on the plaza
  • global travel shoes
  • spectrum products tanning bed
  • 84 wide wooden window blinds
  • consigning my lilly pulitzer clothes
  • no smoking rooms in boston hotels
  • aubrey organics skin cleanser
  • home decor liquidators furniture and flooring
  • hair regrowth products reviews
  • black bean corn citrus vinegar
  • jt paintball gear
  • how to create finger nail designs
  • popup tent cleaning
  • knife sound editing
  • hippie chick costumes
  • miniature surveillance cameras detection
  • hd high def video edit
  • recycle styrofoam cups
  • bamboo patio door blinds
  • money order promise rings
  • resurfacing bathtubs
  • mens star earrings
  • spray face foundation
  • remote home thermostats
  • phoenix skin rejuvenation
  • shower enclosures walls
  • kawasaki 440 aircraft engine parts
  • women's clothing sleep shirts
  • material requirements planning mrp systems
  • cryoserver back email compliance archiving message
  • home flea infestation
  • cuisinart 9-speed hand mixer brushed chrome
  • wholesale military surgical caps
  • nike drawstring backpack lavender
  • acutane colon problems
  • mercedes 320 wagon tires
  • ucla womens basketball camps
  • vida international fruta
  • kids camp crafts
  • compliance corporate email
  • good feet store onalaska wi
  • coach purse party
  • women's shoulder handbags
  • diy exterior patio blinds
  • pivot tub shower enclosures
  • dog harness and collar
  • shoi racing helmets
  • free shawl knit patterns
  • thyme essential oil price
  • tubeless bicycle wheels road
  • black edition magazine man swimsuit
  • 5 star car wax
  • italian charm bracelets wholesale
  • sleep t shirts
  • audio cards upside down
  • dell 5100cn colour network laser printer
  • fj cruiser trailer hitch receivers
  • sell structured settlement payment
  • organizational monitor stands
  • prom decorations and costumes
  • cats on behavior medication
  • golf palm computer gps system
  • budget wedding planning checklist
  • movie theater popcorn maker canada
  • water pump 3-inch suction hose
  • invest in stocks cheap
  • nike max air inline skates
  • star wars galactic heroes bedding comforter
  • airsoft outfitters gear
  • cheap new chevy trucks
  • discounted airfares cheapest airfares erfurt
  • floral furniture throws
  • schutt baseball equipment
  • acrobat distiller settings for news print
  • 2.4 to 3.8 s10 truck conversion
  • westgate villia resorts
  • fuzzy bunny slippers adult
  • shock doctor mouth pieces
  • midwest family vacations
  • red kap highland uniform shirts
  • play euchre free online
  • rockport shoes rosemont
  • elo entuitive touchscreen drivers
  • decorative garden pond fountains
  • kids online cake decorating games
  • america west airlines dividend miles program
  • in kind giving from popcorn company
  • camera ccd industrial
  • outdoor furniture pool harrows
  • raymond waites spring garland
  • lil boosie new mixtapes
  • household and cleaning forum
  • video piggy 1.3.0 crack