In August 2009 I had been
programming with CodeIgniter a little over 2 years, in that time I
learned a lot of things which would have been good to know when I began.
I made a list of stuff I considered best practices for programming in
CodeIgniter, which I have kept up to date. But as I have since moved on
to another framework this is it, the final update was on:
March 2nd, 2012
These 2 posts I licensed under MIT so do with it as you please as long as you give proper acknowledgement about the origin.
RT(F)M: Read the User Guide & watch tutorials
Clear and simple, don’t ask questions before you looked into the awesome thing that makes CI stand out among frameworks:
The CodeIgniter User Guide.
There’s a lot of references in this article to the user guide, but
those are highlights for specific topics - the whole thing should be
read!
Also to get started you can find some video tutorials on
nettuts+ or view the (very dated) video tutorials
on the CodeIgniter website. The latter is using an older version but
when you take that into consideration it’s still a nice place to start
understanding the basics of using CI.
MVC programming
If you don’t know the MVC pattern read up on it! You’ll learn soon the
value of putting the data-access in models, the application logic in
controllers and the visuals in views. But if you haven’t done
programming in such a pattern before it might take a while to sink in,
give it the chance to sink in!
A good guideline is to put as little as possible into your controller. Adhere to the
DRY
principle: Don’t Repeat Yourself. When functionality is needed in more
than one place, create a library, helper or model (depending on what
kind of functionality it is). You’ll notice that once you start to grasp
the MVC basics this will become habitual and you’ll start to reap the
benifits that good clean MVC code bring.
You can read up on MVC in the CI User Guide:
MVC, Flow chart, Models, Views & Controllers.
Or external sources like Wikipedia.
Error reporting and debugging
One of the most often made mistakes is to forget to turn off PHP errors
or Database errors, both of which are gigantic security riscs. It’s a
security risk because you allow an attacker to debug his hacking using
the displayed warnings.
Codeigniter offers
environment settings to help with this. On any public site error_reporting should be set to 0 (or at most E_ERROR), database setting db_debug should be set to false and just for extra measure I tend to do a ini_set(‘display_errors’, ‘Off’).
At the same time you should debug your application with error_reporting
set to -1 (this will show E_ALL and E_STRICT, E_ALL doesn’t include
E_STRICT warnings), and solve every notice and warning before making
your application public. You tend to spot “invisible” bugs sooner and
thus write better code. (more on the error reporting levels on php.net)
One way to make all of this easy has been for me to set the
db_debug
value (in the application/config/database.php config file) to a
constant I declare MP_DB_DEBUG. And add the following code to the top of
the main
index.php to replace the error_reporting() declaration when the site is live (will disable all errors):
ini_set('display_errors', 'Off');
error_reporting(0);
define('MP_DB_DEBUG', false);
But when in production or testing phase I’d suggest:
ini_set('display_errors', 'On');
error_reporting(-1);
define('MP_DB_DEBUG', true);
For even better error reporting Dan Horrigan ported a great error reporting script to CI which you can find on
Github.
This must never be switched on in a live-site environment but is a huge
help during production and has probably saved me hours already.
Application & System directory placement
An absolute best practice is to put the system & application directories outside the webroot. If your main
index.php is in your FTP in a directory like
/public_html/ try if you can upload the system directory to the root as
/system/. That way no one can access your PHP files except through the index.php.
Don’t forget to change the values
$system_folder and
$application_folder
in the main index.php file. $system_folder should be relative to the
index.php file, $application_folder should be relative to the system
folder.
Security
Read up on
SQL injection, XSS (CSS), CSRF
(XSRF) and understand them before you decide if you need measures
against them or not. Also read up in the CI user guide on the security guidelines and XSS filtering from the Input class.
Probably the most important guidline is to validate and check all the
input from users before any kind of interaction with your database,
filesystem, etc.
There’s a pretty good overview of all the issues and some solutions Writing secure PHP.
SQL Injection
Using CI’s Active Record should take care of this problem.
XSS
Be aware which parts of your site are vulnerable to attacks of this kind
and be sure to filter all user input when you can’t be a 100% sure the
user is to be trusted.
CSRF
As of CI2.0 support for tokens is built in, this is explained on the bottom of the
Security class
docs. To learn more you can do a google search on “CSRF tokens” for
protecting simple form submissions and actions done by URL. Or for AJAX
operations search Google for “double cookie submission”.
SPAM
Always protect your email forms, comment forms and any other kind of
free user submitted data against spamming. The easy way is to only allow
each IP/User agent to submit once every minute, while that doesn’t
protect against hackers & bots it does protect you against the usual
internet trolls.
The best way is to use Captcha like
reCAPTCHA
to protect email & comment forms on your website. You can search
the forums on how to intergrate reCAPTCHA with CI. CI2 also provides a CAPTCHA helper.
Performance
Write good clean code and understand your code, don’t just copy paste
the stuff others wrote and always look for ways to improve your code.
Just never ever sacrifice security for performance. The
PHP Style guide from the CodeIgniter manual is a very good place to learn to write better code.
DRY
Don’t Repeat Yourself. Put shared code where it belongs: in libraries,
helpers or models, but not in controllers. Definite rule of thumb: when
you’re copy-pasting code, you probably just put it in the wrong place
for a second time.
Caching
Caching is a pretty good way to improve performance, especially the
ammount of database operations needed can be scaled back easily by using
cache. Take a look into
page caching & database caching, and Caching drivers.
HTTP headers
On the client side you can improve performance by sending HTTP headers
along that instruct the browser to keep your stuff in it’s cache. This
is also good to read up on when using AJAX because you’ll need to
disable browser-cache for those operations. Google it!
Example for AJAX return data (that shouldn’t be browser-cached at all):
$this->output->set_header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
$this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate");
$this->output->set_header("Cache-Control: post-check=0, pre-check=0", false);
$this->output->set_header("Pragma: no-cache");
Example for things that should be kept for a long time (like css, javascripts):
$this->output->set_header('Cache-Control: private, pre-check=0, post-check=0, max-age=2592000');
$this->output->set_header('Expires: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() + 2592000));
$this->output->set_header('Last-Modified: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() - 20));
Database access & ORM
CodeIgniter has a library called
Active Record
(AR) that can help you write your queries without writing any SQL. It’s
pretty powerful and the better way to go when you’re no SQL expert or
aren’t sure how to protect your queries against SQL injections.
When you need more power an
Object Relational Mapper
(ORM) might be the thing for you, and while CI doesn’t come with an ORM
there are some options out there that are all very good.
The most populair is probably DataMapper OverZealous Edition (DMZ). Others are Doctrine (there’s a tutorial on PHP and stuff) and RapidDataMapper.
User auth & ACL
A very much debated topic since it doesn’t come with CI and there are as
many who think it should, as there are who think the opposite. All I
can advise you on this is to search the forums and look for a system
that’s still active, has good security and that intergrates easily into
your application. Or research the examples and write your own.
At this point I would recommend
Ion Auth,
it’s very well written and probably alot better than you’d write on
your first try. And if you are planning on writing your own, read
through it for inspiration.
Anything else?
Search the
forums and the wiki, and if you can’t find it you can always ask.
Did I forget anything or get anything wrong? Reply and I’ll look into into it.
More: http://ellislab.com/forums/viewthread/125687/