Where should assets go in a CodeIgniter project? - php

I'm just starting with CodeIgniter, and I am not sure where things such as css, js, and images should go. Outside the whole system folder seems ok, but that means everything is seperate. Inside means the filepaths are longer, and I'm worried that it might mess things up. What's the best practice on this issue?

I usually put separate folders at the root level, so I end up with a directory structure like this:
/system
/css
/js
/img
Seems to work for me - when you use site_url(url), the URL it generates is from the root, so you can use site_url('css/file.css') to generate URLs to your stylesheets etc.

Personally, I rip the application directory out of the system directory and make it a sibling to system. I then create a project directory in public_html (www) where I move index.php and store my public assets.
Let's assume the project you're working on is called projekt. In the parent directory to public_html (www) create a directory called CISYSTEM, and inside that directory create a directory from the version you're using, 202, 210 etc.
/CISYSTEM
/202
/210
/another_CI_version
/projekt_application
/models
/views
/controllers
/private_assets
/public_html
/projekt
index.php
.htaccess
css
img
js
lib
The beauty of this directory structure is it adds another layer of security and makes it dead-easy to upgrade/swap out your CI core. Plus, you're not supposed to make changes to the core - having a single directory where your core is stored and having all projects reference it keeps things DRY.
All this directory shuffling requires you to reroute a few things though. Luckily, CodeIgniter makes it easy -- all changes can be made in the index.php file.
Open index.php and reroute a couple things:
Change: $system_path = 'system';
To: $system_path = '../../CISYSTEM/210';
Change: $application_folder = 'application';
To: $application_folder = '../../projekt_application';
Also, I see a lot of people talking about using site_url() in the other answers. I recommend a less verbose way of using site_url()... you don't have to call it every time if you make use of HTML's <base> element:
<base href="<?= site_url();?>">
Just include that in your application's <head> and you can call your controllers directly... as in:
<a href='controllername/functionname'>Some Action</a>
Cheers

I hate having so many directories at the root level, so I use /public and use htaccess to rewrite /scripts to /public/scripts and so on.

I find it best to keep the assets on the root level. You can use <?=base_url()?> to echo the full root of the site. In the config file, you set up the root of the website. This statement just echoes that out.
Because of this, you can use includes like this:
<link href="<?=base_url()?>/css/style.css" rel="stylesheet" type="text/css" />
anywhere in your code, and it will still get http://example.com/css/style.css.

base_url()/css/name.css

In order to use the site_url(url) helper in this way you MUST first configure Apache mod_rewrite (or equivalent) to remove the index.php segment from the URI.
Otherwise the site_url method adds index.php to the URL which will likely screw up the paths to your assets if you've got them in the base directory like above.
Here's the CodeIgniter documentation on removing index.php from the URI:
http://codeigniter.com/wiki/mod_rewrite/

Related

Getting the absolute pathname in php

Consider the following scenario: I have a vhost defined to some paths on my home folder.
say ~/web/project-name/ is my root. such that when i point to http://some-name/ it points to the index.php inside ~/web/project-name.
I've a Model-View-Controller framework (self-made/minimal) and my views contains different client side links (js, or css, or a href) Since I made my working folder root, i used absoulte path names (for instance /client/css/my.css ).
Now a friends comes in takes my projects. Copies it to /var/www/ So, now the contents of my website is not root, so my links in the views does not work?
What is the best way to mitigate the above problem?
I tried defining a constant ROOT as define('ROOT', dirname(__FILE__)) in my index.php, but it returns the absolute path like /home/cipher/...
I want to make a function such that it returns the path of my index.php relative to the web root!
Thanks in advance!
You might want to try a $_SERVER['DOCUMENT_ROOT'].

Alternative to site root redirecting to "home/" to keep all site paths stored in one separate location

I keep all my scripts, stylesheets, and php files in separate folders. Each site page has a require() statement, then includes the necessary files. As a temporary measure, I have them relative to the site root, and only one directory deep. For example:
/back/php/scripts.php:
<script src="../back/js/lighbox.js"></script>
<script src="../back/js/site.js"></script>
/home/index.php, /services/index.php, /portfolio/index.php:
<head>
<? require "../back/php/scripts.php"; ?>
</head>
/:
<? header("Location: home/"); ?>
I'm certain there is a better way to handle site structure, as this limits me to only one depth for directories, and also an extra redirect at the start. I'd appreciate your input. How should this be changed? How do you structure your site architecture?
You could use a front controller type system.
All URLs are redirected through index.php using mod_rewrite and it handles the bootstrapping of the files you need (through an autoloader mechanism preferably) along with the related routing.
This also has the added benefit of allowing you to move almost all your PHP out of the httpdocs folder.
So your file layout would be something like this:
- site.com
- classes
- Pages.php
- Auth.php
- Route.php
- vendor
- PHPMailer
- Zend
- httpdocs
- media
- css
- js
- images
- index.php

PHP broken relative links in nested directories

I'm sure I'm missing some simple explanation, but I want to confirm - so assume I know very little.
I have a directory structure like so (for the time being) of:
My main site (localhost/project/ on my testing server, and C:/xampp/htdocs/project on my HDD) with these files and folders:
Root
graphics
variousgraphics.png
support
stylesheet.css
templates
header.php
footer.php
initialize.php
you
default.php
index.php
anotherfile.php
Up until I created the folder 'you' everything was fine, i.e. I included the initialize file for index.php as <?php include(templates/initialize.php) ?>
But when I decide to include initialize.php using the above method for the default.php file (inside 'you'), it errored out with Warning: include(templates/initialize.php) [function.include]: failed to open stream: No such file or directory in C:\xampp\htdocs\photoquilt\you\default.php
So naturally I appended ../ to create <?php include(../templates/initialize.php) ?> but then of course that didn't work because the files referenced inside initialize.php weren't appended in the same way, and so I get to here.
It's worth noting for me, an echo of $_SERVER['document_root'] leads to C:/xampp/htdocs
So in summary:
Is there any way to make sure all the link/paths work correctly irrespective of where the originating path was from?
In default.php you can define a constant like
define('ROOT_PATH', dirname(__DIR__));
or for php versions prior to 5.3.0
define('ROOT_PATH', dirname(dirname(__FILE__)));
and then use ROOT_PATH in all scripts to build the the file paths.
see
- http://docs.php.net/language.constants.predefined
- http://docs.php.net/dirname
There are a couple problems here as far as I can tell: the server-sided and the client-sided.
As for the PHP goes, you are doing it fine. Referencing the file by its relative path (../templates/initialize.php) is the way to go. There's another way of achieving the same, though I wouldn't recommend it: editing the include_path to add the root directory of your project. You can do it in an .htaccess located in the root directory, ie:
php_value include_path ".:/path/to/your/project:/usr/local/lib/php"
For the HTML part (images not loading, stylesheets not found), you can set a base href:
<base href="http://path.to.your/in-server/" />
The base href should point the root of your directory. All the images, stylesheets, etc in HTML must then be fixed to use relative URIs from the root of the project (graphics/variousgraphics.png).

how to use config file from a subdirectory while it is been kept at root directory in PHP

I am developing a web application. contents are:
root dir (/var/www/)
config.php
index.php
details.php
admin dir (/var/www/admin)
admin.php
I have included config.php file into index.php, details.php in root directory using require_once('config.php') as this file contains database passwords, styles, images directory paths..
how can i include that config files in my admin/admin.php file so that one config file can be used in anywhere(even in subdirectories) of my web application. Will it make any difference for the value of define('APP_BASE_PATH', dirname(__FILE__)); when same config file is used by all files in the web application.
if i am wrong somewhere then please get me right.
If your server properly configured, just
include $_SERVER['DOCUMENT_ROOT']."/config.php";
anywhere
You have also 2 other possible ways.
a Front controller setup, where ALL user requests going into one file. And ths one going to include all others from their subdirectories. Personally I don't like it cause this front file become a mess. Though it's widely used.
I decided not to mention it because noone would use a hardcoded full path anyway.
Update after clarification in comments: You are looking for a way to include a central configuration file from anywhere in your project's folder structure.
#Col. Shrapnel shows one way, DOCUMENT_ROOT. It's the only way to use an "absolute" path from a nested folder structure. It has the limitation I describe above, but it's fine otherwise.
If you want maximum portability (i.e. the possibility to run the app with e.g. www.example.com/myapp/version_1 as its root directory), you would have to use relative references from within your folder structure to "climb down" to the config file, e.g. ../../config.php that will work reliably too, although be a bit cumbersome e.g. if you move a script to a different folder and you have to update the relative path.
you can use the same config file every time... using "/" will take you back to the root directory... so in admin/admin.php use this:
require_once("/config.php");
you can use "../" to take you up one directory eg:
require_once("../config.php");
was this what you were looking for?

Why are CodeIgniter application files in the public_html folder?

Isn't having all of the files in public view a bad thing?
Surely things such as /system/application/config/database.php should not be publicly visible!
The developers of CodeIgniter, EllisLabs, have set up the framework in this way for ease of use. It means that people wishing to try out the framework don't have to fiddle with any permissions settings on their server.
Of course on a production server, you are absolutely right, putting your PHP files in the public HTML folder is not a good idea.
A better way to organise your folders would be:
root
code_igniter
application_folder
config
controllers
models
...
system_folder
public_html
css
js
images
index.php
.htaccess
The only other change to be made here would be to change line 26 of index.php to read:
$system_folder = "../../code_igniter/system-folder";
You can add the following rule to your .htaccess file to further protect the system and application directories from being viewed (sends a 403 Forbidden error):
# Protect application and system files from being viewed
RewriteRule ^(application|system) - [F,L]
With this structure:
/application
/system
/public
index.php
You can change in public/index.php these two settings and you are done
$application_folder = '../application';
$system_path = '../system';
Jon Winstanley's answer is perfect,
also don't forget to secure file uploads folder, if you have one. I did that by also moving it outside public root, and get the images using below code:
<?php
// $details = getimagesize($_GET["path"] . '/' . $_GET["image"]);
$details = getimagesize($_GET["path"] . strip_tags($_GET["image"]));
header ('Content-Type: ' . $details['mime']);
readfile($_GET["path"] . strip_tags($_GET["image"]));
exit;
?>
Accessing the files within /system/ from a browser will not reveal any sensitive information, because the PHP will be parsed and nothing is output from those files (CI system files may even check to see if a variable has been defined that indicates the file wasn't accessed directly).
That being said, however, you should probably install your entire system folder above web root anyway.
You can always place the system directory outside the public directory. Don't forget to update paths inside the the front controller (index.php).

Categories