Single Codeigniter Code Base for Multiple Domains - php

I'm looking for a clear explanation of how to use CodeIgniter for multiple domains. I want a single set of models and config files, with the ability to call different controllers depending on the domain the request is coming from. After doing some research, I am fairly certain the way I currently have this set up is not ideal, and I would like to fix it before I get too far into building. Here's the current set up:
I have three domains that I'm managing:
domainA.com
domainB.com
domainC.com
Each domain points to a different folder on my server:
/domains
/global
/models
/model1.php
/model2.php
/domainA.com <--- domainA.com points here
/application
/controllers
/domainAController1.php
/domainAController2.php
/assets
/system
/index.php
/domainB.com <--- domainB.com points here
/application
/controllers
/domainBController1.php
/domainBController2.php
/assets
/system
/index.php
/domainC.com <--- domainC.com points here
/application
/controllers
/domainCController1.php
/domainCController2.php
/assets
/system
/index.php
Then, in each controller, I add a package path in the constructor function so that the controllers have access to my global models:
$this->load->add_package_path(APPPATH.'../../global/');
This allows me to load models from the controllers as normal with something like:
$this->load->model('model1');
The folder hierarchy I'm showing above is not complete. Inside each of the domain folders, there is a full CI installation. So if I want to define constants or configuration parameters for the entire "app", I essentially have to do it three times. Also, the more I develop, the more I am coming across needs for more advanced features like base models and controllers and I have a feeling this "package path" solution I"m using now is not going to work.
This clearly is not the right way to go about it, and I was hoping someone could offer me a better way to implement this.
I am running CodeIgniter version 2.1.4.
***************************UPDATE***************************
Here's what I ended up doing to get this working. I would love someone's advice on if this is a good or bad idea, meaning, do you foresee any obvious issues using this method?
I used routes and controller subfolders to accomplish what I needed. I now have a single installation of CI, and within my controllers folder I have subfolders for domainA.com, domainB.com and domainC.com.
Then, in my routes.php file, I added this after the reserved routes:
switch($_SERVER['SERVER_NAME']){
case 'domainA.com':
$controllerSubDirectory = 'domainA.com';
break;
case 'domainB.com':
$controllerSubDirectory = 'domainB.com';
break;
case 'domainC.com':
$controllerSubDirectory = 'domainC.com';
break;
default:
$controllerSubDirectory = '';
break;
}
route['(.*)'] = "{$controllerSubDirectory}/$1";
In other words, I just take the incoming request and route it as if it were actually coming in with the appropriate subfolder as it's first URI segment.
Are there any issues with this I am not thinking of? Maybe some sort of security risks?

The short answer: take advantage of CodeIgniter "Third Party Packages" feature.
Your directory structure is not very well organized. It is not necessary to store multiple copies of the CodeIgniter System files, assuming of course that all applications are using the same system (version and no/same modifications to core files).
Check CodeIgniter Docs for more detail.
As mentioned above, you could take advantage of CI's packages to package your common code as a 3rd party package. Then you can just load models and other resources as you normally would, and CI will know how to find them on it's own.

Related

Fat free framework - prevent direct access to html files

I'm wondering if there is any good way to prevent direct access to html files in Fat Free Framework...
So the intended way would be to call a route like /login. However, with the default configuration, users could also access /ui/login.html and get the html file directly, eventually displaying {{#variable}} content, which users shouldn't see...
Unfortunately, I didn't find a way to prevent this so far, neither with PHP methods directly, or into Fat Free Framework.. How could this be done?
This could be done with some .htaccess magic where any access to your .htm[l] files are sent a 404, but the proper way to do this is to actually get them out of your public directory. Like you just pointed out, it's a security risk to have those unrendered files there. Usually an app is setup like the following:
app/
config/
controllers/
ui/
mappers/
etc...
public/
index.php (where your fat free index file is that defines your autoloads, config, etc)
vendor/
(composer stuff)
If I were in your shoes, I would move your /ui/ files to a folder outside the public folder and then just change the UI hive variable to point to something like __DIR__.'/../app/ui/' instead which ultimately would solve your problem.
Also, I hope your config file isn't in the public folder! That shouldn't there either (or committed in your code repository!)

How does Laravel implement clean URL and redirect them to Controllers

The title says it pretty well... How does Laravel implement clean URL and redirect them to the right Controllers.
Some frameworks like CakePHP use .htaccess to redirect everything to a FrontController which then dispatch the requests but laravel doesn't use .htaccess so i am bit confused.
Laravel use the concept of "routing", where all clean url are usually defined and mapped to something that will resolve to a view, such as controller action, anonymous functions, plain string, etc...
Each request will be caught by a file located at: public/index.php (that is done by a .htaccess file located at the same location). That index.php file will boostrap or illuminate the Laravel framework, and Laravel will run your code. How is it done? Routing.
The routing configuration is stored in a file located at app/routes.php where a route might look as follows:
Route::get('/users', 'UserController#showUsers');
Route::get('/users/create', 'UserController#createUser');
Route::post('/users/create', 'UserController#processCreateUser');
Route::get('/users/edit/{id}', 'UserController#createUser');
Route::post('/users/edit/{id}', 'UserController#processCreateUser');
More information about routing can be read at the documentation. I strongly recommend you to read the docs since routing are quite powerful in Laravel.
Laravel sites use the public/ folder as their document root. You'll find the .htaccess file in there.

grouping and including files in a php project, by the book

I'm working on my first, rather big project in php. I decided to build everything from scratch, without any framework.
First I had the following structure:
index.php
includes/ //all php pages, except index.
includes/scripts/ //all php classes that do not print web pages.
styles/ //all my css files.
images/ //all images used on the website.
But this was giving me trouble when including files from within the various folders.
I have now changed it to:
index.php
the rest of my .php files
styles/
images/
All my includes are working properly now, without having to jump between folders. But I feel like I have lost overview on my project.
At the moment I'm a bit lost on how to do things. What is, by the book, the proper way to group my folders and to include my files?
EDIT: I would also like to see some tips on actually including the files. What are some techniques to include a file, no matter where include() is called? A specific example, according to my first structure.
There was a script in includes/scripts, login.php. login.php then included page.php (a simple page template) from includes/. page.php would include several parts of the template (header.php, footer.php). But I also had to call page.php from the files in include/.
This was giving me trouble, because the relative path would be different if page.php was called from includes/ or from includes/scripts/
Your problem was probably caused by relative paths.
This can be solved by using absolute paths eg.:
require_once("/var/www/clients/client05/web29/web/includes/scripts/myClass.php");
To make it easier you can also define constants in index.php (or any other file that will get included every time)
define("WEB_ROOT", "/var/www/clients/client05/web29/web/");
define("INCLUDES_DIR", WEB_ROOT . "includes/");
define("SCRIPTS_DIR", INCLUDES_DIR . "scripts/");
Files can then be easly included
require_once(SCRIPTS_DIR . "myClass.php");
require_once(INCLUDES_DIR . "acp.php");
A just straight forward suggestion:
index.php
app/
styles/
images/
All PHP code goes into app/ and can be further organized like you see fit, for example one directory for your templates, one to store third-party code and then your own library that you build for your application.
You should be able to move the app folder then anytime to any other location on disk, especially out of the document root.
This is most easily done with a so called front controller that is routing all request that are incomming to the application to the relevant code (technically this allows you to even have multiple applications side-by-side).
In the layout above, index.php plays that role. It's the entry-point to your application.
You should not think about mere files, but about strategies about how to interact with resources.
As PHP has nice object oriented support now, you may take advantage of namespaces, and organize your classes in folders, the way you like.
If you don't want to use a framework [thing I strongly advise you to do however, as it will make your app secure and more maintainable], you will find this article enlightening about how to organize your structure.
You can pick up some components like the symfony autoloader to load classes as you wish, then handle all the other resources [css, js, images] simply according to your filesystem organization.
My preferred organizational structure involves:
index.php and all other php pages in the root ("/")
/includes/ (directory for included template items like header, footer, analytics code, etc... anything frequently reused)
/includes/classes/ (for php classes)
/images/ (self explanitory; I also use several directories inside this based on the most sensible organization of my images)
/style/ (for css, with a "/style/fonts/" directory for font files)
/scripts/ (for js or similar)
/support/ (for any setup files I might be utilizing)

cakephp routing problem (or maybe just confusion)

I've just started learning cakephp and have gotten the Blog example working except for the routing, I'm still not quite sure how it works after reading many, many documents on routing (including the ones in the official cookbook).
My problem is with the '/' root routing, I want it to go to the index() function of the PostsController so I use:
Router::connect ('/', array('controller'=>'posts', 'action'=>'index'));
But this doesn't work if I go to the url: localhost/
This is probably (most definetely) because I don't know where to put the cake_1_3 folder/installation, currently my directory tree for localhost (in htdocs) looks as follows:
-htdocs>posts>cake_1_3
This means that when I navigate to: localhost/ I get nothing and when I navigate to: localhost/posts/ I get nothing, just the directory listing for the folder "posts" which shows I have the directory "cake_1_3".
It is only when I go to the url: localhost/posts/cake_1_3/posts/ does the routing work, as in it sees the second "posts" and so runs the "index" function of "PostsController".
Obviously this isn't what I want, I want to be able to go to: localhost/posts/ and it use the index function of the PostsController.
Update: I actually tried taking all the cakephp stuff out of "cake_1_3" and just into "posts" but then I have to go to: localhost/posts/posts/ for it to use the index() function of PostsController.
Is there any way I can just navigate to localhost/posts/ and I'll get the index() function of the PostsController running?
I know this is probably a very simple problem and I'm just missing something because I'm so tired (well that's my excuse anyway), but I've been searching around for about 3 hours now and wouldn't mind a helping hand.
Thanks for your time,
InfinitiFizz
P.S. I've just realised I can dump all the cakephp installation files/folders into the root (htdocs) and then localhost/posts/ will work but I've got loads of different test websites in their own folders in htdocs/ and so I'd rather have this posts test in its own folder too, not have all the cakephp folders mixed up with all the other websites' folders.
Just to be clear what directories we're talking about, a Cake installation comes with these folders:
/
app/
webroot/
cake
You will have to hit the top / directory with your browser to get a response from Cake at all. All routes are relative to that top / directory.
Let's say you have installed Cake in your web server like so:
/
htdocs/
someotherproject/
mycakeapp/
app/
webroot/
cake/
The htdocs directory is the root of your web server. If you go to http://localhost/, your web server will respond with the contents of /htdocs/. It's not even invoking Cake, so Cake can't route anything.
You'll have to open http://localhost/mycakeapp/ to invoke Cake. From there, Cake will do its routing. The Cake route Router::connect('/', …) corresponds to the URL http://localhost/mycakeapp/. All Cake routes are relative to the app installation path. The Cake routing is app-internal routing, it does not correspond to the absolute URL.
If you want http://localhost/ to be your Cake app, Cake will need to be the only app residing in /htdocs/. You can't have multiple apps in the root and yet have any one of them be "the root app"†‡.
For local development purposes this should be perfectly fine. When uploading the app to a real server with a real domain you'll usually make it the one and only app.
† Well you could, with elaborate rewrite-rules, virtual host configurations or by placing files in Cake's /app/webroot/ folder. Usually more hassle than it's worth though, keep your projects separate.
‡ You can't have your Cake and eat it, too. zing

Which comes first, the framework or the application? Dynamic framework and application folders

Okay, so I am creating an MVC framework in PHP and I want it to be pretty flexible. This is all fine - I'm working on this at the moment and things are going well (So I don't want to use Zend or another pre-existing framework, haha!), but I wanted to make both the framework and application quite dynamic. I'll try explain:
Here's a simplified directory structure:
- index.php (wants to use app1 or app2 depending on domain name)
- /app1 (wants to use framework 1.1)
- /config
- config.php
- /app2 (wants to use framework 1.2)
- /config
- config.php
- /framework_1.1
- /framework_1.2
A Bootstrap file /index.php receives all incoming requests. It will then load a certain application's config file from /app1/config/config.php or /app2/config/config.php, etc, depending on a certain condition, say.. the HTTP host:
// /index.php
switch ( $_SERVER[ 'HTTP_HOST' ] ) {
case 'localhost':
$app_root = ROOT . 'app1/';
break;
case 'site.com':
$app_root = ROOT . 'app2/';
break;
default:
$app_root = ROOT . 'application/';
break;
}
define('APP_ROOT', $app_root);
The bootstrap file then loads the application's config file:
// /index.php
include( APP_ROOT . 'config/config.php' );
A $config array will be returned from the application's config file, which will indicate where the framework files are located.
// /app2/config/config.php
$config['framework_root'] = '/framework_1.2/';
Bootstrap runs that framework.
// /index.php
include( $config['framework_root'] . 'config/bootstrap.php' );
Is this the best way to go about this?
The only problem with this, is that the /index.php file has to know about all possible applications, so the user will need to edit the switch statement in /index.php (or a /apps.php file that the /index.php includes, maybe?).
Also, the application's configuration file has to be loaded before loading the framework's files, which seems a bit weird to me...
Is there a simple way for making it so the request specifies application, and the application specifies which framework to use, or is the above way the simplest?
Sorry if this was confusing! Confused me a bit writing it ;)
I use Symfony most of the time, so I will apply my knowledge there when answering your questions:
Is there a simple way for making it so the request specifies application
Use multiple "index.php" (or use ?app=xxx) with a URL-rewrite combo. That makes things a bit cleaner.
Also, the application's configuration file has to be loaded before loading the framework's files, which seems a bit weird to me...
It's not weird, you certainly need to configure and initiate some states before bootstrapping your framework, but perhaps you may want to provide sub-class of your framework's bootstrap class, to define what shall be done during framework bootstrapping.
I recommend you to look into Symfony2 to find out how they modularize/manage libraries and dependencies. Seriously, there's no reason to write another framework but to contribute to an existing one - unless you find them not sharing the same visions with yours.

Categories