Share Your CakePHP Core and Application Files Server Wide
December 10, 2008
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', ROOT);
}
with this:
if (!defined('CAKE_CORE_INCLUDE_PATH')) { define('CAKE_CORE_INCLUDE_PATH',DS . 'usr' . DS . 'lib' . DS . 'php' . DS . 'cake'); }
You are now using the common cake core. When a new update comes out to the library, just replace the files in /usr/lib/php/cake with the new version!
If you want to go a step further and share some of your own models, views, controllers, behaviors, helpers, or components between applications you can use a similar technique. For example create a folder in ‘/usr/lib/php/models’ and put all your common models in that folder, then in your application open up bootstrap.php and add the following:
$modelPaths = array(DS . 'usr' . DS . 'lib' . DS . 'php' . DS . 'models' );
Like I said the same thing can be done with views, controllers, helpers, behaviors or components. The cookbook says how! This is pretty handy for when you find a bug in a model and you have several applications using that model!
Cache Your Queries or Data Arrays in CakePHP
December 9, 2008
The Cache Function
CakePHP’s cache function is quite easy to use. The code snippet below shows how to use it.
$cache_name = 'settings';
$cache_data = Cache::read($cache_name);
if (empty($cache_data))
{
$siteSettings = $this->Setting->find('first');
Cache::write($cache_name, $siteSettings, array('config' => 'File', 'duration' => 7200));
}
else
{
$siteSettings = $cache_data;
}
The code above attempts to read in the data from the cache, given the $cache_name. If the data is not found, the query is executed and then written to the cache. As you can see in the Cache::write I am using the File engine for caching, but you can use whichever you desire. I also set the duration to 7200 seconds (2 hours). If the cache data IS found then the query is skipped and the cache data is assigned to $siteSettings. Pretty nifty eh?
I also believe that when you do a save operation on the Settings model Cake knows to automatically remove that cache data, so you don’t end up with out of sync info! If for some reason you want to manually delete the cached data you can use: Cache::delete($key) for a specific key, or Cache::clear() to delete everything in the cache.
Tip: Build Forms Quicker in CakePHP
December 9, 2008
Automagic Forms!
Using $form->input() is great, but when you have many fields or you are just creating a quick form there is a better way! The key is to set up your database table structure properly. If you follow the naming conventions creating a form is as easy as using the following code in the view (this is for a Contact model… obviously):
<?php
echo $form->create('Contact');
echo $form->inputs();
echo $form->end("Save Contact");
?>
This is pretty nice, but what happens if you have fields that you don’t want the user to fill out? Use the blacklist! The following code removes the fieldset and legend along with the fields id, created, and modified.
<?php
$inputs = array('fieldset' => false, 'legend' => false);
$blacklist = array('id', 'created', 'modified');
echo $form->create('Contact');
echo $form->inputs($inputs, $blacklist);
echo $form->end("Save Contact");
?>
Not too bad. Fully functional form in 5 lines of code! But wait… There’s more! You may still want to customize the form a little more to add certain options to some fields. This can be done with the $inputs array. Basically all you have to do is add a key in the $inputs array with the field name, and then assign the optional attributes as you would if you were using the $form->input() function. Here is an example of what the array would look like to add a hint after the “first name” field.
$inputs = array(
'fieldset' => false,
'legend' => false,
'first_name' => array('after' => 'i.e. Lane')
);
The only drawback with assigning the optional attributes is that now the $inputs array must contain a key for every input you want to have a form field for. I’m sure that there is a better way to do this, but you could do something like this in the controller:
<?php
function add()
{
$schema = $this->Contact->schema();
foreach($schema as &$field)
$field = array();
unset($field);
$this->set(compact('schema'));
}
?>
and then in the view do this:
$inputs = array('fieldset' => false, 'legend' => false);
$inputs = array_merge($inputs, $schema);
$inputs['first_name'] = array('after' => 'i.e. Lane');
This method would get the job done, but would really only be practical if you had a whole bunch of fields. Otherwise creating each $form->input() might be the way to go if you have to assign some options. Nonetheless, I’ve found that you can bypass having to set the $options array for specific fields by following the naming conventions, and when that is the case there is nothing better than $form->inputs()!
Related Links
Beginning CakePHP: The MVC Mindset
December 8, 2008
What is MVC anyway?
MVC stands for Model-View-Controller. MVC is a well known design pattern that basically keeps that data handling, application flow, and presentation seperate from each other. At first it may seem a little confusing, but it makes coding much easier and efficient. I will explain each aspect of the MVC below relative to a simple application to manage contacts.
The Model
The model is responsible for handling all of the data. In CakePHP each model usually corresponds to a table in the database. So if in our database we have a table named “contacts” to store all of our contacts then there will be a model named “Contact”. The plural and singular convention is important but I will not be explaining it at this time. I recommend you read the CakePHP conventions before you actually start using Cake because they will save you time and headaches. You can just trust me that the model name should be singular, and the database table should be plural. Here is a rough example of what a model would look like in CakePHP. This file would be stored at “/app/models/contact.php”:
<?php
class Contact extends AppModel
{
var $name = 'Contact';
}
?>
This is actually all you need to get started with a basic model in CakePHP. As you can see the class Contact extends the class AppModel so it inherits all of the functions that AppModel has access to. The AppModel has functions like find, save, delete, etc that allow you to interact with the database. The model should be responsible for all interaction with the database.
So in review, anything to do with manipulating data should be done in the model. Whether it is a query to CRUD (create, read, update, delete) operations to the database you should be doing it from the model. Extending Cake’s AppModel class allows you to use the built in functions for CRUD operations so that you should never have to write an SQL query again! If you would like to learn more about the model and the functions available to it check out the Models page in the Cookbook.
The View
The view is what it sounds like. It is the presentation layer, everything that has to do with displaying the data is done in the view. In cakePHP the view is set up in templates that displays data that is obtained from the model. The view should be the only place where HTML resides. This makes things a lot easier when it comes to modifying the look and feel of an application without having to touch the guts. The view is basically a template and in CakePHP they have the extension “ctp”. Here is what and example of what the view would look like to display a list of contacts… lets call it “index.ctp”. In an application setting this file would be stored in the folder “/app/views/contacts”.
<div class="contacts"> <?php foreach($contacts as $contact): ?> <span class="contact-name"> <?php echo $contact['Contact']['name']; ?> </span> <?php endforeach; ?> </div>
Of course this is an extremely basic example of printing out a list of contact names. In the view we would definitely want to present more information in a nicer way… the best part is in order to do that the only file we will have to edit is the view. You’re probably wondering where the $contacts variable came from, this brings us to the controller.
The Controller
Lastly, there is the controller. The controller manages the flow of the application. It is responsible for handling requests and passing the proper information for the given request. The controller consists of several functions, called “actions”, which determine what should be done. Each action (usually) has an associated view. So for example, if we have an action called “index” in our controller we will need a view called “index.ctp” that displays the information for the given action. The view in the example above uses a variable called $contact. That variable is set using the controller. Here is an example that ties in with the above view, this file would be “/app/controllers/contacts_controller.php” in an application setting.
<?php
class ContactsController extends AppController
{
var $name = 'Contacts';
function index()
{
$contacts = $this->Contact->find('all');
$this->set('contacts');
}
}
?>
The function in the controller above asks the Contact model to find all of the entries in the associated contacts table and then assigns it to the variable $contacts. Afterwards the controller sets the variable $contacts so that the view can now use the $contacts variable. The built in libraries will automatically search for the file “/app/views/contacts/index.ctp” and use it to display the information passed. The best convention is to keep the code in the controllers to a minimum and instead put the bulk of the code for manipulating the data into the model (see Fat Models, Skinny Controllers by Chris Hartjes).
Putting It All Together
So there you have it, we just created an extremely simple Model, View, and Controller for listing contacts. Of course from here you would build on creating actions in the controller for add, view, edit, etc. and views to go with those actions. But hopefully this gives you some insight in to how it works. If you have never followed this design practice before you are probably wondering some of the benefits of the MVC practice. It may not be immediately apparent, but there are several. First of all, separating code in this method allows the basic functionality of the code to be reused over and over again. When it comes to modifying the way the application looks you only have to edit the views instead of all of the code. This allows someone who is familiar with HTML to customize the look of things without having to search endless lines of code that may not be familiar to them. It also makes debugging much easier because you can pinpoint exactly where the problems may be coming from. If the data isn’t correct, it must be the model… If something is funky with the way it is displayed, it has got to be the view… and so on. This is of course just one of the great design patterns used by Cake and there are several others that will save time and headaches.