• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Starting with CodeIgniter setup: suggestions & best practices

#1
[eluser]Jelmer[/eluser]
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):
Code:
ini_set('display_errors', 'Off');
error_reporting(0);
define('MP_DB_DEBUG', false);

But when in production or testing phase I'd suggest:
Code:
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.

#2
[eluser]Jelmer[/eluser]
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):
Code:
$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):
Code:
$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.

#3
[eluser]Jondolar[/eluser]
You couldn't have posted this 3 months ago :-)

Nice job and great contribution.

#4
[eluser]Tyler Diaz[/eluser]
Thanks for taking the time in making this, nice contribution to the forums.

#5
[eluser]Jelmer[/eluser]
Someone mentioned an inconsistancy to me about error reporting. It used to say:
Quote:On any public site error_reporting should be set to E_ERROR
And then I went on to set error reporting to 0 instead of E_ERROR.

E_ERROR essentially means 1 and is as such one level more reporting than 0 (none at all). According to php.net, setting error reporting to E_ERROR means:
Quote:Fatal run-time errors. These indicate errors that can not be recovered from, such as a memory allocation problem. Execution of the script is halted.

My view is that in a live site any error should be either written by me (the programmer) or not shown at all. The users shouldn't know what went wrong except when I explicitly told the system what it should tell the user. Which is why in the example code error reporting is set to 0 and not to E_ERROR.

Which is why I've changed the suggested error reporting to 0 instead of E_ERROR for any live site. I've corrected the comment explanation of the levels in the error reporting switch code because in the PHP code 1 means fatal errors & DB errors (instead of only DB errors) and 2 means compiler errors & db errors (instead of fatal & db errors). Also I've added a link to the error reporting pre-defined constants on php.net (http://nl2.php.net/manual/en/errorfunc.constants.php).

#6
[eluser]marinaccio[/eluser]
Just wanted to say thanks for putting this together, very nice one stop, quick start guide to get people up to speed, and doing things correctly from the start. CI has some damn good forum members!

Thanks,

marinaccio

#7
[eluser]DCZ[/eluser]
Very nice.
Thx for the trouble !

#8
[eluser]Jelmer[/eluser]
Some small edits:
- location of the db_debug setting in the first post
- better structure in the bit on performance
- some HTTP headers examples
- removed link to the security presentation that went offline (pitty, was very good)

#9
[eluser]kidsman[/eluser]
It helped me
Thanks

#10
[eluser]Jamie Rumbelow[/eluser]
This is really helpful - thanks for posting it! I'm making it sticky so more people will hopefully read it Smile


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


Users browsing this thread:
1 Guest(s)


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2017 MyBB Group.