Tuesday, February 26, 2008

Caching data

If we are looking for ways to improve our website performance, the cache is the key.

There are many ways to do this, the most common cache is full pages, but sometimes this is not possible. In these cases, the main thing is to locate the slowest processes and try to save their outcome. To that end, the best thing is to use memcache that allows us to keep one variable (serialized, as a string) and recover very quickly.

A more generic solution can be implemented in a class that receives data to store, allowing change the way of doing (memcache, database, files), if necessary to migrate the code to a server that does not have the necessary technology.

Sunday, February 24, 2008

Surviving without GET parameters

CodeIgniter does not allow the use of variables GET default, to allow the "friendly URLs" However, parameters can still be passed.

Suppose a forum, and we want to pass the item number to display the comments. In PHP classic the URL would be view_thread.php?thread_id=1234 but in CI, on the other hand, we can make thread/view/1234. Then the controller is thread, the method view and parameter aditional is 1234.

How to recover the value of this parameter?
We have two options. We can define it as a parameter of the method view or through the URI class.
The first alternative would be something

function view($ id = 0)
(
// And it is defined $ id
)

The second option is

function view()
{
$id = $ this->uri->segment(3);
// And it is defined $id
}

The first seems more beautiful, right? Maybe someone will call attention to the parameter = 0 ... Because the user defines the URL the visitor may not send the parameter and this would generate a PHP fatal error, unrecoverable. In this way, we can do that if the id is empty, the user is redirected to an error page or to the list of items ... Basically, fail gracefully.

This case is simple. However becomes more complicated when the parameters are many. For example, to paginate the theme that we are showing, we can add a fourth parameter, leaving

function view($id = 0, $page = 1)
{

}

But things can be even more complicated when there are multiple parameters and not necessarily in order of importance (in the previous case, always require an ID, but not always a page number).
Suppose an advanced search form, within the same forum. In addition to keywords, we can select a range of time and a particular user. If we try to apply the same approach, come to something as confusing as

function results($keywords = '', $from_date = '',$to_date = '', $user = 0)
{
// ...
}

What seems more annoying than friendly. There are several possible solutions.

Sessions
One possible option is to send the form to a page and store the data in the session, and then knowing that sought to navigate through the session data. Against: if a user does not two searches can "surf" (enter items and return, or use the paging) simultaneously. Against II: can not be shared or saved as bookmarks page of search results.

Uri Assoc
While we can not do search_results.php?keywords=...&from_date=...&to_date=... We can make a URI associative and use search/results/keywords/.../desde_fecha/.../to_date/... And then take advantage of the method of the URI class uri_to_assoc to achieve a simple associative array.

Hash
Finally, we may use the URI to send an identifier of the search. For example search/results/bda90d48eda6d07d961b3ec26216fe05 and keep our database criteria mean "bda90d48eda6d07d961b3ec26216fe05".

Saturday, February 16, 2008

The first thing to know

The object being instance as a controller, has references to all the libraries and models who have instanciated as an attribute of the same name in the class.
So if we load the library Email, we have $ this->email is an instance of the class email.

The issue does not end there. Each model also has the same attributes loaded, then we have the code in the controller and the model is similar, as they have the same attributes. So, if we do some code in the controller and we think it is very general and we may need inside another, it's easy to make it a model.

But ... What if we are in a library?
At libraries this attributes are not loaded, but may need access to another library, or a model. For this, we can access the instance of the controller through the "get_instance" function.
For example, within the class we want to validate the email message with the method valid_email the kind of validation. Then:

Function valid_email ($ address)
{
// (& It is important to avoid creating a copy in PHP 4)
$CI =& get_instance();

// If not loaded the library, load it
if (!isset($CI->validation))
{
$CI->load->library('validation');
}

// Call the method
return $CI->validation->valid_email($address);
}

Simple, no?

Still, this follows ...
What if at the view, we want access to a library or model, for example, the validation to retrieve messages?

The views can also access as $ this->validation to the same object that the controller or models.
Internally, this is accomplished by assigning these instances to Class Loader, where the views are loaded.

Two long months

Since my change of job, my free time is shortened and the blog fell into oblivion.
Lately I've dedicate my PHP time to CodeIgniter, so I am going to start posting on the matter.

Basics. CodeIgniter is a Framework that works in PHP 4.3.2+. It's very lightweight and very flexible. Inspired by Ruby on rails. Use the MVC pattern. Promotes friendly URLs. The documentation is very good.