CodeIgniter pagination configuration file seems pointless

In the CodeIgniter documentation:

Simply create a new file called pagination.php, add the $config array in that file. Then save the file in application/config/pagination.php and it will be used automatically. You will NOT need to use $this->pagination->initialize() if you save your preferences in a config file.

However, one of the pagination configurations is the base_url, which presumably is going to be unique in every instance of pagination. For instance, if you use pagination for a controller function named yesterday your base_url might be something like /news/yesterday/pages/. Then for a controller function named today, your base_url might be /news/today/pages/. Given this scenario, you’ll need settings common for both instances stored in your pagination.php file and unique settings declared at the time you create the pagination links.

Consider this code:

In older versions of CodeIgniter, this code worked in conjunction with a pagination.php config file. However, after upgrading my project to version 3.1.0, I discovered the styling of my pagination links were totally broken. The settings contained within pagination.php were suddenly being ignored. Apparently the initialize() function is resetting pagination to its defaults, disregarding the pagination.php file entirely, and only using the $config settings array passed into it.

I no longer see the use of having a pagination.php file for common settings. If one of the core principals of CodeIgniter is DRY (Do not Repeat Yourself), then pagination.php has been rendered useless in this regard. You’re going to have both common configuration settings for all pagination instances in your project along with settings that are unique to each instance. If having unique settings for multiple instances precludes being able to use pagination.php, then its own purpose is already defeated. In order to use pagination.php, every instance of pagination would need an identical URL structure, which makes it impossible to use on more than one Controller function.

Consider two scenarios that illustrate the issue:

1. Do not use pagination.php file – Declare all settings for each instance of pagination by constructing the $config array in every Controller function. Settings common to all instances of pagination will need to be repeated for each instance of pagination throughout your Controller functions. Does not adhere to DRY principles. Not ideal.

2. Use pagination.php file – All pagination settings are contained in a central location adhering to DRY principles. However, since base_url is also a pagination setting, you’ll be forced to use the same Base URL for all instances of pagination. Impossible.

Workaround:

1. Copy your common pagination settings into your custom configuration file contained within application/config/ directory. If you don’t already have a custom configuration file, create and auto-load it. Assign the array to a single configuration item named pagination:

2. Access these common settings within your Controller by calling your new custom configuration item. Use a foreach to loop through the pagination settings array:

One advantage of this method is that you can individually over-ride any specific setting by simply assigning it to the $config array anytime after your foreach loop.

3. Delete the seemingly useless pagination.php file!

How to handle an expired CSRF token after a page is left open

I’m using CodeIgniter 2 along with the Ion Auth authorization system by Ben Edmunds.

After creating my project, I would sometimes get a CodeIgniter error upon certain login attempts but this error was intermittent.

The action you have requested is not allowed.

After some troubleshooting, it became apparent this error was caused by an invalid CSRF token. Why is the token invalid? Well, in CodeIgniter’s configuration file, it’s set to expire in 4 hours. So if you load your login page and allow it to sit there for 4 hours before attempting a login, the CSRF tokens will expire and this will generate the error message as above. Simply reloading the login page avoids any issues.

You can verify this error message for yourself by deleting the CSRF cookie after you load the login page.

A cleaner solution would be to redirect to a custom error page or to display a flash message. However, this solution is not as simple as it sounds because when you extend the CodeIgniter Security class, certain hook-points are not available and you cannot yet access CodeIgniter’s Super Object using get_instance().

So when you extend the Security class, you’re limited to standard PHP. In this case, I’m using PHP header() to redirect the offending login page (or any form page) back to itself.

This works fine except that the user gets a screen refresh without any indication why they have to enter their login credentials a seconds time.

I decided to make this a bit more user-friendly by adding another function into a Controller, in my case, the Ion Auth controller…

As you can see, this function sets a flash message telling the user what happened and then redirects them to a fresh instance of the login page.

Session cookie automatically reset due to expired browser session. Please try again.

Instead of using PHP header() to redirect a page refresh, redirect to this new Ion Auth controller function at /auth/csrf_redirect.

The minor downside to this method is that you are always redirected back to the login page rather than a refresh of whatever page/form you’re trying to submit. However, that should be a moot point, since the session cookie expires at nearly the same time as the CSRF cookie, you’d be redirected back to the same login page regardless. You may also not be requiring the user be logged in for your particular form, so please be aware and re-direct accordingly.

Extending the CodeIgniter Database Utility Class

You’d like to take advantage of CodeIgniter’s built-in database backup function as described here…

http://www.codeigniter.com/user_guide/database/utilities.html#backup

As you can see, only the mysql PHP database extension is supported. However, since the mysql PHP database extension has been deprecated, maybe you’re using another PHP database extension like mysqli instead. Now the problem is that you can no longer use CodeIgniter’s built-in database backup function without getting this error…

Unsupported feature of the database platform you are using.

The error simply means that if you use any PHP database extension besides mysql, there is no function included within any of CodeIgniter’s database drivers’ utility file for doing the backup.

No problem, we’ll just “extend” CodeIgniter’s database class.

Wrong! As per documentation,

Note: The Database classes can not be extended or replaced with your own classes.

Despite this limitation, there is a workaround below that will not involve editing CodeIgniter’s core system files.


Solution:
Instead, we’ll simply “extend” CodeIgniter’s Loader class. Within this custom Loader, we’ll only copy and slightly modify the dbutil() function. Study the function below and compare it to the original. I simply check for the existence of my custom utility driver file and load it in place of the default.

application/core/MY_Loader.php contains…

Now we need to find the database driver that we’re using. For mysqli, it should be located within system/database/drivers/mysqli/mysqli_utility.php. This file contains the _backup() function and you can see that it’s empty (“unsupported”).

Create an exact duplicate of this file; rename it MY_DB_mysqli_utility.php and place it here…

application/libraries/MY_DB_mysqli_utility.php

Everything within this file should remain the same as the original, except for the name of the class and the contents of the _backup() function…

NOW you can put whatever code you see fit into this version of the _backup() function. I’m not going to tell you how to do this, but you could look inside of system/database/drivers/mysql/mysql_utility.php for some inspiration. You could also try the backup function suggested in this posting, which seems to be working.


The advantages to my technique are as follows…

– Updating the CodeIgniter system files leaves this solution intact.
– Changing the dbdriver setting in config/database.php will simply cause a fallback to the selected database utility driver. This solution is specific to one particular database driver (mysqli).
– Removing the MY_Loader.php file causes a fallback to the default database utility driver.
– Removing the MY_DB_mysqli_utility.php file causes a fallback to the default database utility driver.
– Update any other database utility driver by changing mysqli where-ever appropriate.

Note: This solution was successfully performed using CodeIgniter v2.2.0.

When CodeIgniter’s CSRF Protection breaks your Ajax

CSRF stands for “Cross Site Request Forgery” and if you’re using forms on your site, you’ll probably want to protect yourself and users against this kind of attack.

You just finished your latest PHP project using the CodeIgniter framework and decide to enable the CSRF protection option in your config.php file.

Enabling it within config.php is not enough. You also need to use the form helper form_open() function to construct the form’s HTML markup. This function constructs the form so that it contains a <input type="hidden"> element containing the CSRF token value. If the submitted form data is missing this token, it will not submit.

Now CSRF is working but you discover that your jQuery ajax requests are all suddenly failing with a type 500 server error. This is a direct result of activating the CSRF Protection option in CodeIgniter. As just explained, the submitted form data must contain the CSRF token, but it’s missing from your ajax requests.

The solution is simple. You need to make sure that your ajax requests simulate a regular form submission by including the CSRF token value within the submitted data.

There are two types of solutions:

Solution #1:

This only works if your ajax requests occur when a form is already constructed on the page, such as when doing remote validation to check to see if a password or username already exists.

You’ll need to copy the value from the hidden field called csrf_token (the name is exactly as per your $config['csrf_token_name'] option setting) and send this along with your ajax request.

Solution #2:

This works for all ajax requests, even when you do not have a form on the page, such as remotely loading some content.

In this case, you can’t get the CSRF token from a hidden field, since there is no form. You must retrieve it from the CSRF cookie. I’m using a jQuery cookie plugin.

Notice how the ajax in both solutions is sending the token with the same name, that’s your name as per your configuration, csrf_token. Only the source of the token value is different… Solution #1 gets the token value from the hidden field, where Solution #2 gets the same token value from the cookie.

You can only use Solution #1 when you have a form on the page constructed with the form_open() function. However, you can use Solution #2 with or without a form, in all cases.

NOTES:

I have CodeIgniter v2.1.4 and by default, the $config['csrf_token_name'] option is set to csrf_test_name. This mismatch might get a little confusing, but you can use whatever naming convention you wish. In my solution above, I changed it to csrf_token.

  • To retrieve the current token from the hidden input, use the name assigned to the $config['csrf_token_name'] option.
  • To retrieve the current token from the cookie, use the name assigned to the $config['csrf_cookie_name'] option.

No matter how you retrieve the token value, the important thing to remember is to always send the token value along with whatever name you’ve assigned to the $config['csrf_token_name'] option.